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'])
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)
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
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")
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)
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))
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]
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
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)
def ip2int(ip): """Convert IP as string to integer.""" return struct.unpack('!L',socket.inet_aton(ip))[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)
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
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)
def ip2int(ip): """Convert IP as string to integer.""" return struct.unpack('!L', socket.inet_aton(ip))[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])
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])