Exemplo n.º 1
0
def inametonets(iname):
    addrs = netifaces.ifaddresses(iname)
    try:
        addrs = addrs[netifaces.AF_INET]
    except KeyError:
        return
    for addr in addrs:
        ip = struct.unpack('!I', socket.inet_aton(addr['addr']))[0]
        mask = struct.unpack('!I', socket.inet_aton(addr['netmask']))[0]
        net = ip & mask
        net = socket.inet_ntoa(struct.pack('!I', net))
        yield (net, mask_to_cidr(addr['netmask']), addr['addr'])
Exemplo n.º 2
0
    def bind(self):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.socket.bind((self.multicast_group, self.port))
        self.socket.setsockopt(
            socket.SOL_IP, socket.IP_ADD_MEMBERSHIP,
            socket.inet_aton(self.multicast_group) +
            socket.inet_aton(self.listen_ip))

        self.poller = select.poll()
        self.poller.register(
            self.socket, select.POLLIN | select.POLLPRI | select.POLLERR
            | select.POLLHUP | select.POLLNVAL)
Exemplo n.º 3
0
    def update_newdevice(self,res):
        '''添加新的小机到数据库'''
        mirco_devices = QueryDB.get_devices_table(res.vendor)
        if not mirco_devices.exists(self.write_engine):
            mirco_devices.create(self.write_engine)
        ipadr = int(hexlify(socket.inet_aton(res.host[0])),16) & 0xFFFFFFFF
        ipprt = res.host[1] & 0xFFFF
        #print "host %d:%d" % (ipadr,ipprt)
        data = ''
        try:
            data = res.attrs[STUN_ATTRIBUTE_DATA]
        except:
            pass

        try: 
            upd = mirco_devices.update().values(is_online=True,chost = [ipadr,ipprt],data=data,
                    last_login_time=datetime.now()).where(mirco_devices.c.devid == res.tuid)
            try:
                result = self.db_write(upd)
            except:
                self.errqueue.put(','.join([LOG_ERROR_DB,res.tuid,str(sys._getframe().f_lineno)]))
        except exc.DataError: 
            ins = mirco_devices.insert().values(devid=res.tuid,is_active=True,
                    is_online=True,chost=[ipadr,ipprt],data=data,last_login_time=datetime.now())
            try:
                result = self.db_write(ins)
            except:
                self.errqueue.put(','.join([LOG_ERROR_DB,res.tuid,str(sys._getframe().f_lineno)]))
            #print "insert new devices result fetchall"
        ipadr = None
        ipprt = None
        data = None
Exemplo n.º 4
0
def get_prefix_len_for_ip(ip):
    # for now, we'll use the system route table
    # later may provide for configuration lookup to override the route
    # table
    ip = getaddrinfo(ip, 0, socket.AF_INET)[0][-1][0]
    try:
        ipn = socket.inet_aton(ip)
    except socket.error:  # For now, assume 64 for ipv6
        return 64
    # It comes out big endian, regardless of host arch
    ipn = struct.unpack('>I', ipn)[0]
    rf = open('/proc/net/route')
    ri = rf.read()
    rf.close()
    ri = ri.split('\n')[1:]
    for rl in ri:
        if not rl:
            continue
        rd = rl.split('\t')
        if rd[1] == '00000000':  # default gateway, not useful for this
            continue
        # don't have big endian to look at, assume that it is host endian
        maskn = struct.unpack('I', struct.pack('>I', int(rd[7], 16)))[0]
        netn = struct.unpack('I', struct.pack('>I', int(rd[1], 16)))[0]
        if ipn & maskn == netn:
            nbits = 0
            while maskn:
                nbits += 1
                maskn = maskn << 1 & 0xffffffff
            return nbits
    raise exc.NotImplementedException("Non local addresses not supported")
Exemplo n.º 5
0
def stun_connect_address(host,res):
    buf = []
    stun_init_command_str(stun_make_success_response(STUN_METHOD_CONNECT),buf,)
    mip = "0001%04x%08x" % (host[1]^ (STUN_MAGIC_COOKIE >> 16),
            STUN_MAGIC_COOKIE ^ (int(hexlify(socket.inet_aton(host[0])),16)))
    stun_attr_append_str(buf,STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,mip)
    if res.attrs.has_key(STUN_ATTRIBUTE_DATA): #转发小机的基本信息
        stun_attr_append_str(buf,STUN_ATTRIBUTE_DATA,hexlify(res.attrs[STUN_ATTRIBUTE_DATA]))
    stun_add_fingerprint(buf)
    return (buf)
Exemplo n.º 6
0
def _find_srvtype(net, net4, srvtype, addresses, xid):
    """Internal function to find a single service type

    Helper to do singleton requests to srvtype

    :param net: Socket active
    :param srvtype: Service type to do now
    :param addresses:  Pass through of addresses argument from find_targets
    :return:
    """
    if addresses is not None:
        for addr in addresses:
            for saddr in socket.getaddrinfo(addr, 427):
                if saddr[0] == socket.AF_INET:
                    net4.sendto(data, saddr[4])
                elif saddr[0] == socket.AF_INET6:
                    net.sendto(data, saddr[4])
    else:
        data = _generate_request_payload(srvtype, True, xid)
        net4.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        v6addrs = []
        v6hash = _v6mcasthash(srvtype)
        # do 'interface local' and 'link local'
        # it shouldn't make sense, but some configurations work with interface
        # local that do not work with link local
        v6addrs.append(('ff01::1:' + v6hash, 427, 0, 0))
        v6addrs.append(('ff02::1:' + v6hash, 427, 0, 0))
        for idx in util.list_interface_indexes():
            # IPv6 multicast is by index, so lead with that
            net.setsockopt(IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, idx)
            for sa in v6addrs:
                try:
                    net.sendto(data, sa)
                except socket.error:
                    # if we hit an interface without ipv6 multicast,
                    # this can cause an error, skip such an interface
                    # case in point, 'lo'
                    pass
        for i4 in util.list_ips():
            if 'broadcast' not in i4:
                continue
            addr = i4['addr']
            bcast = i4['broadcast']
            net4.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF,
                            socket.inet_aton(addr))
            try:
                net4.sendto(data, ('239.255.255.253', 427))
            except socket.error as se:
                # On occasion, multicasting may be disabled
                # tolerate this scenario and move on
                if se.errno != 101:
                    raise
            net4.sendto(data, (bcast, 427))
Exemplo n.º 7
0
def _find_service(service, target):
    net4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    net6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
    if target:
        addrs = socket.getaddrinfo(target, 1900, 0, socket.SOCK_DGRAM)
        for addr in addrs:
            host = addr[4][0]
            if addr[0] == socket.AF_INET:
                net4.sendto(smsg.format(host, service), addr[4])
            elif addr[0] == socket.AF_INET6:
                host = '[{0}]'.format(host)
                net6.sendto(smsg.format(host, service), addr[4])
    else:
        net4.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        for idx in util.list_interface_indexes():
            net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, idx)
            try:
                net6.sendto(smsg.format('[{0}]'.format(mcastv6addr), service),
                            (mcastv6addr, 1900, 0, 0))
            except socket.error:
                # ignore interfaces without ipv6 multicast causing error
                pass
        for i4 in util.list_ips():
            if 'broadcast' not in i4:
                continue
            addr = i4['addr']
            bcast = i4['broadcast']
            net4.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF,
                            socket.inet_aton(addr))
            net4.sendto(smsg.format(mcastv4addr, service), (mcastv4addr, 1900))
            net4.sendto(smsg.format(bcast, service), (bcast, 1900))
    # SSDP by spec encourages responses to spread out over a 3 second interval
    # hence we must be a bit more patient
    deadline = util.monotonic_time() + 4
    r, _, _ = select.select((net4, net6), (), (), 4)
    peerdata = {}
    while r:
        for s in r:
            (rsp, peer) = s.recvfrom(9000)
            neighutil.refresh_neigh()
            _parse_ssdp(peer, rsp, peerdata)
        timeout = deadline - util.monotonic_time()
        if timeout < 0:
            timeout = 0
        r, _, _ = select.select((net4, net6), (), (), timeout)
    for nid in peerdata:
        yield peerdata[nid]
Exemplo n.º 8
0
    def app_user_update_status(self,user,host):
        """更新用户的状态"""
        uname = unhexlify(user)
        status_tables = QueryDB.get_account_status_table()
        ipadr = int(hexlify(socket.inet_aton(host[0])),16) & 0xFFFFFFFF
        ipprt = host[1] & 0xFFFF
        sss = ''
        try:
            sss = status_tables.update().values(last_login_time = datetime.now(),chost=[ipadr,ipprt]).where(status_tables.c.uname == user)
        except exc.DataError:
            sss = status_tables.insert().values(uname=uname,is_login=True,chost=[ipadr,ipprt])

        try:
            result = self.db_write(sss)
        except:
            self.errqueue.put(','.join([LOG_ERROR_DB,host[0],str(sys._getframe().f_lineno)]))
        uname = None
        status_tables = None
        ipadr = None
        ipprt = None
        sss = None
Exemplo n.º 9
0
def snoop(handler, protocol=None):
    """Watch for SLP activity

    handler will be called with a dictionary of relevant attributes

    :param handler:
    :return:
    """
    tracelog = log.Logger('trace')
    try:
        active_scan(handler, protocol)
    except Exception as e:
        tracelog.log(traceback.format_exc(),
                     ltype=log.DataTypes.event,
                     event=log.Events.stacktrace)
    net = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    net.setsockopt(IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
    slpg = socket.inet_pton(socket.AF_INET6, 'ff01::123')
    slpg2 = socket.inet_pton(socket.AF_INET6, 'ff02::123')
    for i6idx in util.list_interface_indexes():
        mreq = slpg + struct.pack('=I', i6idx)
        net.setsockopt(IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
        mreq = slpg2 + struct.pack('=I', i6idx)
        net.setsockopt(IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
    net4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    net.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    net4.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    for i4 in util.list_ips():
        if 'broadcast' not in i4:
            continue
        slpmcast = socket.inet_aton('239.255.255.253') + \
            socket.inet_aton(i4['addr'])
        try:
            net4.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
                            slpmcast)
        except socket.error as e:
            if e.errno != 98:
                raise
            # socket in use can occur when aliased ipv4 are encountered
    net.bind(('', 427))
    net4.bind(('', 427))

    while True:
        try:
            newmacs = set([])
            r, _, _ = select.select((net, net4), (), (), 60)
            # clear known_peers and peerbymacaddress
            # to avoid stale info getting in...
            # rely upon the select(0.2) to catch rapid fire and aggregate ip
            # addresses that come close together
            # calling code needs to understand deeper context, as snoop
            # will now yield dupe info over time
            known_peers = set([])
            peerbymacaddress = {}
            while r:
                for s in r:
                    (rsp, peer) = s.recvfrom(9000)
                    ip = peer[0].partition('%')[0]
                    if peer in known_peers:
                        continue
                    if ip not in neighutil.neightable:
                        neighutil.update_neigh()
                    if ip not in neighutil.neightable:
                        continue
                    known_peers.add(peer)
                    mac = neighutil.neightable[ip]
                    if mac in peerbymacaddress:
                        peerbymacaddress[mac]['addresses'].append(peer)
                    else:
                        q = query_srvtypes(peer)
                        if not q or not q[0]:
                            # SLP might have started and not ready yet
                            # ignore for now
                            known_peers.discard(peer)
                            continue
                        # we want to prioritize the very well known services
                        svcs = []
                        for svc in q:
                            if svc in _slp_services:
                                svcs.insert(0, svc)
                            else:
                                svcs.append(svc)
                        peerbymacaddress[mac] = {
                            'services': svcs,
                            'addresses': [peer],
                        }
                    newmacs.add(mac)
                r, _, _ = select.select((net, net4), (), (), 0.2)
            for mac in newmacs:
                peerbymacaddress[mac]['xid'] = 1
                _add_attributes(peerbymacaddress[mac])
                peerbymacaddress[mac]['hwaddr'] = mac
                peerbymacaddress[mac]['protocol'] = protocol
                for srvurl in peerbymacaddress[mac].get('urls', ()):
                    if len(srvurl) > 4:
                        srvurl = srvurl[:-3]
                    if srvurl.endswith('://Athena:'):
                        continue
                if 'service:ipmi' in peerbymacaddress[mac]['services']:
                    continue
                if 'service:lightttpd' in peerbymacaddress[mac]['services']:
                    currinf = peerbymacaddress[mac]
                    curratt = currinf.get('attributes', {})
                    if curratt.get('System-Manufacturing',
                                   [None])[0] == 'Lenovo' and curratt.get(
                                       'type',
                                       [None])[0] == 'LenovoThinkServer':
                        peerbymacaddress[mac]['services'] = [
                            'service:lenovo-tsm'
                        ]
                    else:
                        continue
                handler(peerbymacaddress[mac])
        except Exception as e:
            tracelog.log(traceback.format_exc(),
                         ltype=log.DataTypes.event,
                         event=log.Events.stacktrace)
Exemplo n.º 10
0
def ip2int(ip):
    """Convert IP as string to integer."""
    return struct.unpack('!L',socket.inet_aton(ip))[0]
Exemplo n.º 11
0
def snoop(handler, byehandler=None, protocol=None, uuidlookup=None):
    """Watch for SSDP notify messages

    The handler shall be called on any service coming online.
    byehandler is called whenever a system advertises that it is departing.
    If no byehandler is specified, byebye messages are ignored.  The handler is
    given (as possible), the mac address, a list of viable sockaddrs to reference
    the peer, and the notification type (e.g.
    'urn:dmtf-org:service:redfish-rest:1'

    :param handler:  A handler for online notifications from network
    :param byehandler: Optional handler for devices going off the network
    """
    # Normally, I like using v6/v4 agnostic socket. However, since we are
    # dabbling in multicast wizardry here, such sockets can cause big problems,
    # so we will have two distinct sockets
    tracelog = log.Logger('trace')
    known_peers = set([])
    net6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
    for ifidx in util.list_interface_indexes():
        v6grp = ssdp6mcast + struct.pack('=I', ifidx)
        net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, v6grp)
    net6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    net4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    for i4 in util.list_ips():
        ssdp4mcast = socket.inet_pton(socket.AF_INET, mcastv4addr) + \
                     socket.inet_aton(i4['addr'])
        try:
            net4.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
                            ssdp4mcast)
        except socket.error as e:
            if e.errno != 98:
                # errno 98 can happen if aliased, skip for now
                raise
    net4.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    net4.bind(('', 1900))
    net6.bind(('', 1900))
    peerbymacaddress = {}
    while True:
        try:
            newmacs = set([])
            machandlers = {}
            r, _, _ = select.select((net4, net6), (), (), 60)
            while r:
                for s in r:
                    (rsp, peer) = s.recvfrom(9000)
                    if rsp[:4] == b'PING':
                        continue
                    rsp = rsp.split(b'\r\n')
                    method, _, _ = rsp[0].split(b' ', 2)
                    if method == b'NOTIFY':
                        ip = peer[0].partition('%')[0]
                        if peer in known_peers:
                            continue
                        if ip not in neighutil.neightable:
                            neighutil.update_neigh()
                        if ip not in neighutil.neightable:
                            continue
                        mac = neighutil.neightable[ip]
                        known_peers.add(peer)
                        newmacs.add(mac)
                        if mac in peerbymacaddress:
                            peerbymacaddress[mac]['addresses'].append(peer)
                        else:
                            peerbymacaddress[mac] = {
                                'hwaddr': mac,
                                'addresses': [peer],
                            }
                            peerdata = peerbymacaddress[mac]
                            for headline in rsp[1:]:
                                if not headline:
                                    continue
                                headline = util.stringify(headline)
                                header, _, value = headline.partition(':')
                                header = header.strip()
                                value = value.strip()
                                if header == 'NT':
                                    peerdata['service'] = value
                                elif header == 'NTS':
                                    if value == 'ssdp:byebye':
                                        machandlers[mac] = byehandler
                                    elif value == 'ssdp:alive':
                                        machandlers[mac] = None  # handler
                    elif method == b'M-SEARCH':
                        if not uuidlookup:
                            continue
                        #ip = peer[0].partition('%')[0]
                        for headline in rsp[1:]:
                            if not headline:
                                continue
                            headline = util.stringify(headline)
                            headline = headline.partition(':')
                            if len(headline) < 3:
                                continue
                            if headline[0] == 'ST' and headline[-1].startswith(
                                    ' urn:xcat.org:service:confluent:'):
                                try:
                                    cfm.check_quorum()
                                except Exception:
                                    continue
                                for query in headline[-1].split('/'):
                                    if query.startswith('uuid='):
                                        curruuid = query.split('=',
                                                               1)[1].lower()
                                        node = uuidlookup(curruuid)
                                        if not node:
                                            break
                                        # Do not bother replying to a node that
                                        # we have no deployment activity
                                        # planned for
                                        cfg = cfm.ConfigManager(None)
                                        cfd = cfg.get_node_attributes(
                                            node, [
                                                'deployment.pendingprofile',
                                                'collective.managercandidates'
                                            ])
                                        if not cfd.get(node, {}).get(
                                                'deployment.pendingprofile',
                                            {}).get('value', None):
                                            break
                                        candmgrs = cfd.get(node, {}).get(
                                            'collective.managercandidates',
                                            {}).get('value', None)
                                        if candmgrs:
                                            candmgrs = noderange.NodeRange(
                                                candmgrs, cfg).nodes
                                            if collective.get_myname(
                                            ) not in candmgrs:
                                                break
                                        currtime = time.time()
                                        seconds = int(currtime)
                                        msecs = int(currtime * 1000 % 1000)
                                        reply = 'HTTP/1.1 200 OK\r\nNODENAME: {0}\r\nCURRTIME: {1}\r\nCURRMSECS: {2}\r\n'.format(
                                            node, seconds, msecs)
                                        if '%' in peer[0]:
                                            iface = peer[0].split('%', 1)[1]
                                            reply += 'MGTIFACE: {0}\r\n'.format(
                                                peer[0].split('%', 1)[1])
                                            ncfg = netutil.get_nic_config(
                                                cfg, node, ifidx=iface)
                                            if ncfg.get(
                                                    'matchesnodename', None):
                                                reply += 'DEFAULTNET: 1\r\n'
                                        elif not netutil.address_is_local(
                                                peer[0]):
                                            continue
                                        if not isinstance(reply, bytes):
                                            reply = reply.encode('utf8')
                                        s.sendto(reply, peer)
                r, _, _ = select.select((net4, net6), (), (), 0.2)
            for mac in newmacs:
                thehandler = machandlers.get(mac, None)
                if thehandler:
                    thehandler(peerbymacaddress[mac])
        except Exception:
            tracelog.log(traceback.format_exc(),
                         ltype=log.DataTypes.event,
                         event=log.Events.stacktrace)
Exemplo n.º 12
0
def _find_service(service, target):
    net4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    net6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
    if target:
        addrs = socket.getaddrinfo(target, 1900, 0, socket.SOCK_DGRAM)
        for addr in addrs:
            host = addr[4][0]
            if addr[0] == socket.AF_INET:
                msg = smsg.format(host, service)
                if not isinstance(msg, bytes):
                    msg = msg.encode('utf8')
                net4.sendto(msg, addr[4])
            elif addr[0] == socket.AF_INET6:
                host = '[{0}]'.format(host)
                msg = smsg.format(host, service)
                if not isinstance(msg, bytes):
                    msg = msg.encode('utf8')
                net6.sendto(msg, addr[4])
    else:
        net4.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        for idx in util.list_interface_indexes():
            net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, idx)
            try:
                msg = smsg.format('[{0}]'.format(mcastv6addr), service)
                if not isinstance(msg, bytes):
                    msg = msg.encode('utf8')
                net6.sendto(msg, (mcastv6addr, 1900, 0, 0))
            except socket.error:
                # ignore interfaces without ipv6 multicast causing error
                pass
        for i4 in util.list_ips():
            if 'broadcast' not in i4:
                continue
            addr = i4['addr']
            bcast = i4['broadcast']
            net4.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF,
                            socket.inet_aton(addr))
            msg = smsg.format(mcastv4addr, service)
            if not isinstance(msg, bytes):
                msg = msg.encode('utf8')
            net4.sendto(msg, (mcastv4addr, 1900))
            msg = smsg.format(bcast, service)
            if not isinstance(msg, bytes):
                msg = msg.encode('utf8')
            net4.sendto(msg, (bcast, 1900))
    # SSDP by spec encourages responses to spread out over a 3 second interval
    # hence we must be a bit more patient
    deadline = util.monotonic_time() + 4
    r, _, _ = select.select((net4, net6), (), (), 4)
    peerdata = {}
    while r:
        for s in r:
            (rsp, peer) = s.recvfrom(9000)
            neighutil.refresh_neigh()
            _parse_ssdp(peer, rsp, peerdata)
        timeout = deadline - util.monotonic_time()
        if timeout < 0:
            timeout = 0
        r, _, _ = select.select((net4, net6), (), (), timeout)
    querypool = gp.GreenPool()
    pooltargs = []
    for nid in peerdata:
        for url in peerdata[nid].get('urls', ()):
            if url.endswith('/desc.tmpl'):
                pooltargs.append((url, peerdata[nid]))
    for pi in querypool.imap(check_cpstorage, pooltargs):
        if pi is not None:
            yield pi
Exemplo n.º 13
0
def check_reply(node, info, packet, sock, cfg, reqview):
    httpboot = info['architecture'] == 'uefi-httpboot'
    replen = 275  # default is going to be 286
    cfd = cfg.get_node_attributes(node, ('deployment.*'))
    profile = cfd.get(node, {}).get('deployment.pendingprofile',
                                    {}).get('value', None)
    myipn = info['netinfo']['recvip']
    myipn = socket.inet_aton(myipn)
    if not profile:
        return
    rqtype = packet[53][0]
    insecuremode = cfd.get(node, {}).get('deployment.useinsecureprotocols',
                                         'never')
    if not insecuremode:
        insecuremode = 'never'
    if insecuremode == 'never' and not httpboot:
        if rqtype == 1 and info['architecture']:
            log.log({
                'info':
                'Boot attempt by {0} detected in insecure mode, but '
                'insecure mode is disabled.  Set the attribute '
                '`deployment.useinsecureprotocols` to `firmware` or '
                '`always` to enable support, or use UEFI HTTP boot '
                'with HTTPS.'.format(node)
            })
        return
    reply = bytearray(512)
    repview = memoryview(reply)
    repview[:20] = iphdr
    repview[12:16] = myipn
    repview[20:28] = udphdr
    repview = repview[28:]
    repview[0:1] = b'\x02'
    repview[1:10] = reqview[1:10]  # duplicate txid, hwlen, and others
    repview[10:11] = b'\x80'  # always set broadcast
    repview[28:44] = reqview[28:44]  # copy chaddr field
    if httpboot:
        proto = 'https' if insecuremode == 'never' else 'http'
        bootfile = '{0}://{1}/confluent-public/os/{2}/boot.img'.format(
            proto, info['netinfo']['recvip'], profile)
        if not isinstance(bootfile, bytes):
            bootfile = bootfile.encode('utf8')
        repview[108:108 + len(bootfile)] = bootfile
    repview[20:24] = myipn
    gateway = None
    netmask = None
    niccfg = netutil.get_nic_config(cfg, node, ifidx=info['netinfo']['ifidx'])
    if niccfg.get('ipv4_broken', False):
        # Received a request over a nic with no ipv4 configured, ignore it
        return
    clipn = None
    if niccfg['ipv4_address']:
        clipn = socket.inet_aton(niccfg['ipv4_address'])
        repview[16:20] = clipn
        gateway = niccfg['ipv4_gateway']
        if gateway:
            gateway = socket.inet_aton(gateway)
        netmask = niccfg['prefix']
        netmask = (2**32 - 1) ^ (2**(32 - netmask) - 1)
        netmask = struct.pack('!I', netmask)
    repview[236:240] = b'\x63\x82\x53\x63'
    repview[240:242] = b'\x35\x01'
    if rqtype == 1:  # if discover, then offer
        repview[242:243] = b'\x02'
    elif rqtype == 3:  # if request, then ack
        repview[242:243] = b'\x05'
    repview[243:245] = b'\x36\x04'  # DHCP server identifier
    repview[245:249] = myipn
    repview[249:255] = b'\x33\x04\x00\x00\x00\xf0'  # fixed short lease time
    repview[255:257] = b'\x61\x11'
    repview[257:274] = packet[97]
    # Note that sending PXEClient kicks off the proxyDHCP procedure, ignoring
    # boot filename and such in the DHCP packet
    # we will simply always do it to provide the boot payload in a consistent
    # matter to both dhcp-elsewhere and fixed ip clients
    if info['architecture'] == 'uefi-httpboot':
        repview[replen - 1:replen + 11] = b'\x3c\x0aHTTPClient'
        replen += 12
    else:
        repview[replen - 1:replen + 10] = b'\x3c\x09PXEClient'
        replen += 11
    hwlen = bytearray(reqview[2:3].tobytes())[0]
    fulladdr = repview[28:28 + hwlen].tobytes()
    myipbypeer[fulladdr] = myipn
    if hwlen == 8:  # omnipath may present a mangled proxydhcp request later
        shortaddr = bytearray(6)
        shortaddr[0] = 2
        shortaddr[1:] = fulladdr[3:]
        myipbypeer[bytes(shortaddr)] = myipn
    if netmask:
        repview[replen - 1:replen + 1] = b'\x01\x04'
        repview[replen + 1:replen + 5] = netmask
        replen += 6
    if gateway:
        repview[replen - 1:replen + 1] = b'\x03\x04'
        repview[replen + 1:replen + 5] = gateway
        replen += 6
    repview[replen -
            1:replen] = b'\xff'  # end of options, should always be last byte
    repview = memoryview(reply)
    pktlen = struct.pack('!H', replen + 28)  # ip+udp = 28
    repview[2:4] = pktlen
    curripsum = ~(_ipsum(constiphdrsum + pktlen + myipn)) & 0xffff
    repview[10:12] = struct.pack('!H', curripsum)
    repview[24:26] = struct.pack('!H', replen + 8)
    datasum = _ipsum(b'\x00\x11' + repview[24:26].tobytes() +
                     repview[12:replen + 28].tobytes())
    datasum = ~datasum & 0xffff
    repview[26:28] = struct.pack('!H', datasum)
    if clipn:
        staticassigns[fulladdr] = (clipn, repview[:replen + 28].tobytes())
    elif fulladdr in staticassigns:
        del staticassigns[fulladdr]
    send_raw_packet(repview, replen + 28, reqview, info)
Exemplo n.º 14
0
def ip2int(ip):
    """Convert IP as string to integer."""
    return struct.unpack('!L', socket.inet_aton(ip))[0]
Exemplo n.º 15
0
def snoop(handler, byehandler=None):
    """Watch for SSDP notify messages

    The handler shall be called on any service coming online.
    byehandler is called whenever a system advertises that it is departing.
    If no byehandler is specified, byebye messages are ignored.  The handler is
    given (as possible), the mac address, a list of viable sockaddrs to reference
    the peer, and the notification type (e.g.
    'urn:dmtf-org:service:redfish-rest:1'

    :param handler:  A handler for online notifications from network
    :param byehandler: Optional handler for devices going off the network
    """
    # Normally, I like using v6/v4 agnostic socket. However, since we are
    # dabbling in multicast wizardry here, such sockets can cause big problems,
    # so we will have two distinct sockets
    known_peers = set([])
    net6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
    for ifidx in util.list_interface_indexes():
        v6grp = ssdp6mcast + struct.pack('=I', ifidx)
        net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, v6grp)
    net6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    net4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    for i4 in util.list_ips():
        ssdp4mcast = socket.inet_pton(socket.AF_INET, mcastv4addr) + \
                     socket.inet_aton(i4['addr'])
        net4.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
                        ssdp4mcast)
    net4.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    net4.bind(('', 1900))
    net6.bind(('', 1900))
    peerbymacaddress = {}
    while True:
        newmacs = set([])
        machandlers = {}
        r, _, _ = select.select((net4, net6), (), (), 60)
        neighutil.update_neigh()
        while r:
            for s in r:
                (rsp, peer) = s.recvfrom(9000)
                rsp = rsp.split('\r\n')
                method, _, _ = rsp[0].split(' ', 2)
                if method == 'NOTIFY':
                    ip = peer[0].partition('%')[0]
                    if ip not in neighutil.neightable:
                        continue
                    if peer in known_peers:
                        continue
                    mac = neighutil.neightable[ip]
                    known_peers.add(peer)
                    newmacs.add(mac)
                    if mac in peerbymacaddress:
                        peerbymacaddress[mac]['peers'].append(peer)
                    else:
                        peerbymacaddress[mac] = {
                            'hwaddr': mac,
                            'peers': [peer],
                        }
                        peerdata = peerbymacaddress[mac]
                        for headline in rsp[1:]:
                            if not headline:
                                continue
                            header, _, value = headline.partition(':')
                            header = header.strip()
                            value = value.strip()
                            if header == 'NT':
                                peerdata['service'] = value
                            elif header == 'NTS':
                                if value == 'ssdp:byebye':
                                    machandlers[mac] = byehandler
                                elif value == 'ssdp:alive':
                                    machandlers[mac] = handler
            r, _, _ = select.select((net4, net6), (), (), 0.1)
        for mac in newmacs:
            thehandler = machandlers.get(mac, None)
            if thehandler:
                thehandler(peerbymacaddress[mac])
Exemplo n.º 16
0
def snoop(handler):
    """Watch for SLP activity

    handler will be called with a dictionary of relevant attributes

    :param handler:
    :return:
    """
    active_scan(handler)
    net = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    net.setsockopt(IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
    slpg = socket.inet_pton(socket.AF_INET6, 'ff01::123')
    slpg2 = socket.inet_pton(socket.AF_INET6, 'ff02::123')
    for i6idx in util.list_interface_indexes():
        mreq = slpg + struct.pack('=I', i6idx)
        net.setsockopt(IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
        mreq = slpg2 + struct.pack('=I', i6idx)
        net.setsockopt(IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
    net4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    net.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    net4.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    for i4 in util.list_ips():
        if 'broadcast' not in i4:
            continue
        slpmcast = socket.inet_aton('239.255.255.253') + \
            socket.inet_aton(i4['addr'])
        try:
            net4.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
                            slpmcast)
        except socket.error as e:
            if e.errno != 98:
                raise
            # socket in use can occur when aliased ipv4 are encountered
    net.bind(('', 427))
    net4.bind(('', 427))

    while True:
        newmacs = set([])
        r, _, _ = select.select((net, net4), (), (), 60)
        # clear known_peers and peerbymacaddress
        # to avoid stale info getting in...
        # rely upon the select(0.2) to catch rapid fire and aggregate ip
        # addresses that come close together
        # calling code needs to understand deeper context, as snoop
        # will now yield dupe info over time
        known_peers = set([])
        peerbymacaddress = {}
        neighutil.update_neigh()
        while r:
            for s in r:
                (rsp, peer) = s.recvfrom(9000)
                ip = peer[0].partition('%')[0]
                if ip not in neighutil.neightable:
                    continue
                if peer in known_peers:
                    continue
                known_peers.add(peer)
                mac = neighutil.neightable[ip]
                if mac in peerbymacaddress:
                    peerbymacaddress[mac]['addresses'].append(peer)
                else:
                    q = query_srvtypes(peer)
                    if not q or not q[0]:
                        # SLP might have started and not ready yet
                        # ignore for now
                        known_peers.discard(peer)
                        continue
                    # we want to prioritize the very well known services
                    svcs = []
                    for svc in q:
                        if svc in _slp_services:
                            svcs.insert(0, svc)
                        else:
                            svcs.append(svc)
                    peerbymacaddress[mac] = {
                        'services': svcs,
                        'addresses': [peer],
                    }
                newmacs.add(mac)
            r, _, _ = select.select((net, net4), (), (), 0.2)
        for mac in newmacs:
            peerbymacaddress[mac]['xid'] = 1
            _add_attributes(peerbymacaddress[mac])
            peerbymacaddress[mac]['hwaddr'] = mac
            handler(peerbymacaddress[mac])