def _format_IPv6(self, ipv6, ipv6_bytes): output = [] output += [''] output += [''] output += [ '============================= IPv6 packet =====================================' ] output += [''] output += ['Version: {0}'.format(ipv6['version'])] output += ['Traffic class: {0}'.format(ipv6['traffic_class'])] output += ['Flow label: {0}'.format(ipv6['flow_label'])] output += ['Payload length: {0}'.format(ipv6['payload_length'])] output += ['Hop Limit: {0}'.format(ipv6['hop_limit'])] output += ['Next header: {0}'.format(ipv6['next_header'])] output += [ 'Source Addr.: {0}'.format(u.formatIPv6Addr(ipv6['src_addr'])) ] output += [ 'Destination Addr.: {0}'.format(u.formatIPv6Addr(ipv6['dst_addr'])) ] output += [ 'Payload: {0}'.format(u.formatBuf(ipv6['payload'])) ] output += [''] output += [self._formatWireshark(ipv6_bytes)] output += [''] return '\n'.join(output)
def _createTunIf(self): ''' Open a TUN/TAP interface and switch it to TUN mode. :returns: The handler of the interface, which can be used for later read/write operations. ''' #===== log.info("opening tun interface") tun_counter = 0 while tun_counter < 16: try: ifname = 'tun{0}'.format(tun_counter) f = os.open("/dev/{0}".format(ifname), os.O_RDWR) break except OSError: tun_counter += 1 if tun_counter == 16: raise OSError( 'TUN device not found: check if it exists or if it is busy') else: #===== log.info("configuring IPv6 address...") prefixStr = u.formatIPv6Addr(openTun.IPV6PREFIX) hostStr = u.formatIPv6Addr(openTun.IPV6HOST) v = os.system('ifconfig {0} inet6 {1}:{2} prefixlen 64'.format( ifname, prefixStr, hostStr)) v = os.system( 'ifconfig {0} inet6 fe80::{1} prefixlen 64 add'.format( ifname, hostStr)) #===== log.info("adding static route route...") # added 'metric 1' for router-compatibility constraint # (show ping packet on wireshark but don't send to mote at all) # os.system('ip -6 route add ' + prefixStr + ':1415:9200::/96 dev ' + ifname + ' metric 1') os.system( 'route add -inet6 {0}:1415:9200::/96 -interface {1}'.format( prefixStr, ifname)) # trying to set a gateway for this route #os.system('ip -6 route add ' + prefixStr + '::/64 via ' + IPv6Prefix + ':' + hostStr + '/64') #===== log.info("enabling IPv6 forwarding...") # os.system('echo 1 > /proc/sys/net/ipv6/conf/all/forwarding') os.system('sysctl -w net.inet6.ip6.forwarding=1') #===== print('\ncreated following virtual interface:') os.system('ifconfig {0}'.format(ifname)) #=====start radvd #os.system('radvd start') return f
def _createTunIf(self): ''' Open a TUN/TAP interface and switch it to TUN mode. :returns: The handler of the interface, which can be used for later read/write operations. ''' try: #===== log.info("opening tun interface") returnVal = os.open("/dev/net/tun", os.O_RDWR) ifs = ioctl(returnVal, TUNSETIFF, struct.pack("16sH", "tun%d", IFF_TUN)) ifname = ifs[:16].strip("\x00") #===== log.info("configuring IPv6 address...") prefixStr = u.formatIPv6Addr(openTun.IPV6PREFIX) hostStr = u.formatIPv6Addr(openTun.IPV6HOST) v = os.system('ip tuntap add dev ' + ifname + ' mode tun user root') v = os.system('ip link set ' + ifname + ' up') v = os.system('ip -6 addr add ' + prefixStr + ':' + hostStr + '/64 dev ' + ifname) v = os.system('ip -6 addr add fe80::' + hostStr + '/64 dev ' + ifname) #===== log.info("adding static route route...") # added 'metric 1' for router-compatibility constraint # (show ping packet on wireshark but don't send to mote at all) os.system('ip -6 route add ' + prefixStr + ':1415:9200::/96 dev ' + ifname + ' metric 1') # trying to set a gateway for this route #os.system('ip -6 route add ' + prefixStr + '::/64 via ' + IPv6Prefix + ':' + hostStr + '/64') #===== log.info("enabling IPv6 forwarding...") os.system('echo 1 > /proc/sys/net/ipv6/conf/all/forwarding') #===== print('\ncreated following virtual interface:') os.system('ip addr show ' + ifname) #=====start radvd #os.system('radvd start') except IOError as err: # happens when not root print 'WARNING: could not created tun interface. Are you root? ({0})'.format( err) returnVal = None return returnVal
def _createTunIf(self): ''' Open a TUN/TAP interface and switch it to TUN mode. :returns: The handler of the interface, which can be used for later read/write operations. ''' #===== log.info("opening tun interface") tun_counter=0 while tun_counter<16: try: ifname='tun{0}'.format(tun_counter) f=os.open("/dev/{0}".format(ifname), os.O_RDWR) break except OSError: tun_counter+=1 if tun_counter==16: raise OSError('TUN device not found: check if it exists or if it is busy') else: #===== log.info("configuring IPv6 address...") prefixStr = u.formatIPv6Addr(openTun.IPV6PREFIX) hostStr = u.formatIPv6Addr(openTun.IPV6HOST) v=os.system('ifconfig {0} inet6 {1}:{2} prefixlen 64'.format(ifname, prefixStr, hostStr)) v=os.system('ifconfig {0} inet6 fe80::{1} prefixlen 64 add'.format(ifname, hostStr)) #===== log.info("adding static route route...") # added 'metric 1' for router-compatibility constraint # (show ping packet on wireshark but don't send to mote at all) # os.system('ip -6 route add ' + prefixStr + ':1415:9200::/96 dev ' + ifname + ' metric 1') os.system('route add -inet6 {0}:1415:9200::/96 -interface {1}'.format(prefixStr, ifname)) # trying to set a gateway for this route #os.system('ip -6 route add ' + prefixStr + '::/64 via ' + IPv6Prefix + ':' + hostStr + '/64') #===== log.info("enabling IPv6 forwarding...") # os.system('echo 1 > /proc/sys/net/ipv6/conf/all/forwarding') os.system('sysctl -w net.inet6.ip6.forwarding=1') #===== print('\ncreated following virtual interface:') os.system('ifconfig {0}'.format(ifname)) #=====start radvd #os.system('radvd start') return f
def _createTunIf(self): ''' Open a TUN/TAP interface and switch it to TUN mode. :returns: The handler of the interface, which can be used for later read/write operations. ''' try: #===== log.info("opening tun interface") returnVal=os.open("/dev/net/tun", os.O_RDWR) ifs=ioctl(returnVal,TUNSETIFF,struct.pack("16sH","tun%d",IFF_TUN)) ifname=ifs[:16].strip("\x00") #===== log.info("configuring IPv6 address...") prefixStr = u.formatIPv6Addr(openTun.IPV6PREFIX) hostStr = u.formatIPv6Addr(openTun.IPV6HOST) v = os.system('ip tuntap add dev ' + ifname + ' mode tun user root') v = os.system('ip link set ' + ifname + ' up') v = os.system('ip -6 addr add ' + prefixStr + ':' + hostStr + '/64 dev ' + ifname) v = os.system('ip -6 addr add fe80::' + hostStr + '/64 dev ' + ifname) #===== log.info("adding static route route...") # added 'metric 1' for router-compatibility constraint # (show ping packet on wireshark but don't send to mote at all) os.system('ip -6 route add ' + prefixStr + ':1415:9200::/96 dev ' + ifname + ' metric 1') # trying to set a gateway for this route #os.system('ip -6 route add ' + prefixStr + '::/64 via ' + IPv6Prefix + ':' + hostStr + '/64') #===== log.info("enabling IPv6 forwarding...") os.system('echo 1 > /proc/sys/net/ipv6/conf/all/forwarding') #===== print('\ncreated following virtual interface:') os.system('ip addr show ' + ifname) #=====start radvd #os.system('radvd start') except IOError as err: # happens when not root print 'WARNING: could not created tun interface. Are you root? ({0})'.format(err) returnVal = None return returnVal
def _setPrefix_notif(self, sender, signal, data): ''' Record the network prefix. ''' with self.stateLock: self.networkPrefix = data log.info('Set network prefix {0}'.format(u.formatIPv6Addr(data)))
def _updateStats(self): # load stats newStats = json.loads(self.eventBusMonitor.getStats()) for i in range(len(newStats)): if type(newStats[i]['signal']) == list and len( newStats[i]['signal']) == 3: [ip, tran, port] = newStats[i]['signal'] signal = [] signal += [u.formatIPv6Addr(ip)] signal += [tran] signal += [str(port)] newStats[i]['signal'] = ','.join(signal) # update table self.dataTable.update(newStats, columnOrder=[ 'sender', 'signal', 'num', ]) # update in case changed by something besides GUI self.zepToggle.setState(self.eventBusMonitor.wiresharkDebugEnabled) # schedule next update self.after(self.GUIUPDATEPERIOD, self._updateStats)
def close(self): if self.tunReadThread: self.tunReadThread.close() # Send a packet to openTun interface to break out of blocking read. attempts = 0 while self.tunReadThread.isAlive() and attempts < 3: attempts += 1 try: log.info('Sending UDP packet to close openTun') sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) # Destination must route through the TUN host, but not be the host itself. # OK if host does not really exist. dst = IPV6PREFIX + IPV6HOST dst[15] += 1 # Payload and destination port are arbitrary sock.sendto('stop', (u.formatIPv6Addr(dst), 18004)) # Give thread some time to exit time.sleep(0.05) except Exception as err: log.error( 'Unable to send UDP to close tunReadThread: {0}'.join( err))
def _setPrefix_notif(self,sender,signal, data): ''' Record the network prefix. ''' with self.stateLock: self.networkPrefix = data log.info('Set network prefix {0}'.format(u.formatIPv6Addr(data)))
def test_formatIPv6Addr(expectedformatipv6): (ipv6_list, ipv6_string) = json.loads(expectedformatipv6) print ipv6_string assert u.formatIPv6Addr(ipv6_list) == ipv6_string
def _updateStats(self): # load stats newStats = json.loads(self.eventBusMonitor.getStats()) for i in range(len(newStats)): if type(newStats[i]['signal'])==list and len(newStats[i]['signal'])==3: [ip,tran,port] = newStats[i]['signal'] signal = [] signal += [u.formatIPv6Addr(ip)] signal += [tran] signal += [str(port)] newStats[i]['signal'] = ','.join(signal) # update table self.dataTable.update( newStats, columnOrder = [ 'sender', 'signal', 'num', ] ) # update in case changed by something besides GUI self.zepToggle.setState(self.eventBusMonitor.wiresharkDebugEnabled) # schedule next update self.after(self.GUIUPDATEPERIOD,self._updateStats)
def _format_IPv6(self,ipv6,ipv6_bytes): output = [] output += [''] output += [''] output += ['============================= IPv6 packet ====================================='] output += [''] output += ['Version: {0}'.format(ipv6['version'])] output += ['Traffic class: {0}'.format(ipv6['traffic_class'])] output += ['Flow label: {0}'.format(ipv6['flow_label'])] output += ['Payload length: {0}'.format(ipv6['payload_length'])] output += ['Hop Limit: {0}'.format(ipv6['hop_limit'])] output += ['Next header: {0}'.format(ipv6['next_header'])] output += ['Source Addr.: {0}'.format(u.formatIPv6Addr(ipv6['src_addr']))] output += ['Destination Addr.: {0}'.format(u.formatIPv6Addr(ipv6['dst_addr']))] output += ['Payload: {0}'.format(u.formatBuf(ipv6['payload']))] output += [''] output += [self._formatWireshark(ipv6_bytes)] output += [''] return '\n'.join(output)
def close(self): self.tunReadThread.close() # Send a packet to openTun interface to break out of blocking read. attempts = 0 while self.tunReadThread.isAlive() and attempts < 3: attempts += 1 try: log.info('Sending UDP packet to close openTun') sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) # Destination must route through the TUN host, but not be the host itself. # OK if host does not really exist. dst = IPV6PREFIX + IPV6HOST dst[15] += 1 # Payload and destination port are arbitrary sock.sendto('stop', (u.formatIPv6Addr(dst),18004)) # Give thread some time to exit time.sleep(0.05) except Exception as err: log.error('Unable to send UDP to close tunReadThread: {0}'.join(err))
def _v6ToMesh_notif(self, sender, signal, data): ''' Converts a IPv6 packet into a 6LoWPAN packet. This function assumes there is a component listening on the EventBus which answers to the 'getSourceRoute' signal. This function dispatches the 6LoWPAN packet with signal 'bytesToMesh'. ''' try: ipv6_bytes = data # turn raw byte into dictionary of fields ipv6 = self.disassemble_ipv6(ipv6_bytes) # filter out multicast packets if ipv6['dst_addr'][0] == 0xff: return if ipv6['dst_addr'][0] == 0xfe and ipv6['dst_addr'][1] == 0x80: isLinkLocal = True else: isLinkLocal = False # log if log.isEnabledFor(logging.DEBUG): log.debug(self._format_IPv6(ipv6, ipv6_bytes)) # convert IPv6 dictionary into 6LoWPAN dictionary lowpan = self.ipv6_to_lowpan(ipv6) # add the source route to this destination if len(lowpan['dst_addr']) == 16: dst_addr = lowpan['dst_addr'][8:] elif len(lowpan['dst_addr']) == 8: dst_addr = lowpan['dst_addr'] else: dst_addr = None log.warning('unsupported address format {0}'.format( lowpan['dst_addr'])) if isLinkLocal: lowpan['route'] = [dst_addr] else: lowpan['route'] = self._getSourceRoute(dst_addr) if len(lowpan['route']) < 2: # no source route could be found log.error('no source route to {0}'.format( lowpan['dst_addr'])) # TODO: return ICMPv6 message return lowpan['route'].pop() #remove last as this is me. lowpan['nextHop'] = lowpan['route'][ len(lowpan['route']) - 1] #get next hop as this has to be the destination address, this is the last element on the list # Whisper, update ping route if link testing packet if self.whisperController is not None: if ipv6['next_header'] == self.IANA_ICMPv6 and self.whisperController.getOpenLbrCatchPing( ): # Change source route of ping request print "Changing ping request of " + str(lowpan) lowpan = self.whisperController.updatePingRequest(lowpan) # turn dictionary of fields into raw bytes lowpan_bytes = self.reassemble_lowpan(lowpan) # log if log.isEnabledFor(logging.DEBUG): log.debug(self._format_lowpan(lowpan, lowpan_bytes)) # don't forward the ICMPv6 packets to the motes (unsupported) if (ipv6['next_header'] == self.IANA_ICMPv6) and ( ipv6['payload'][0] == self.ERR_DESTINATIONUNREACHABLE): log.error( 'ICMPv6 packet to forward to {0}, The packet is dropped (DESTINATIONUNREACHABLE not supported by openWSN)' .format(u.formatIPv6Addr(ipv6['dst_addr']))) log.error(self._format_lowpan(lowpan, lowpan_bytes)) return #print "output:" #print lowpan_bytes # dispatch self.dispatch( signal='bytesToMesh', data=(lowpan['nextHop'], lowpan_bytes), ) except (ValueError, NotImplementedError) as err: log.error(err) pass
def _indicateDAO_inWhisper(self, tup): ''' Indicate a new DAO was received. This function parses the received packet, and if valid, updates the information needed to compute source routes. ''' # retrieve source and destination try: source = tup[0] if len(source) > 8: source = source[len(source) - 8:] dao = tup[1] except IndexError: #log.info("DAO too short ({0} bytes), no space for destination and source".format(len(dao))) return # retrieve DAO header dao_header = {} dao_transit_information = {} dao_target_information = {} try: # RPL header dao_header['RPL_InstanceID'] = dao[0] dao_header['RPL_flags'] = dao[1] dao_header['RPL_Reserved'] = dao[2] dao_header['RPL_DAO_Sequence'] = dao[3] # DODAGID dao_header['DODAGID'] = dao[4:20] dao = dao[20:] # retrieve transit information header and parents parents = [] children = [] while len(dao) > 0: if dao[0] == self._TRANSIT_INFORMATION_TYPE: # transit information option dao_transit_information['Transit_information_type'] = dao[ 0] dao_transit_information[ 'Transit_information_length'] = dao[1] dao_transit_information['Transit_information_flags'] = dao[ 2] dao_transit_information[ 'Transit_information_path_control'] = dao[3] dao_transit_information[ 'Transit_information_path_sequence'] = dao[4] dao_transit_information[ 'Transit_information_path_lifetime'] = dao[5] # address of the parent prefix = dao[6:14] parents += [dao[14:22]] dao = dao[22:] elif dao[0] == self._TARGET_INFORMATION_TYPE: dao_target_information['Target_information_type'] = dao[0] dao_target_information['Target_information_length'] = dao[ 1] dao_target_information['Target_information_flags'] = dao[2] dao_target_information[ 'Target_information_prefix_length'] = dao[3] # address of the child prefix = dao[4:12] children += [dao[12:20]] dao = dao[20:] else: #log.info("DAO with wrong Option {0}. Neither Transit nor Target.".format(dao[0])) return (None, None, None, None) except IndexError: #log.info("DAO too short ({0} bytes), no space for DAO header".format(len(dao))) return src = '{0}:{1}'.format(u.formatIPv6Addr(self.networkPrefix), u.formatIPv6Addr(source)) output_parents = [] for p in parents: output_parents.append( [u.formatIPv6Addr(self.networkPrefix), u.formatIPv6Addr(p)]) output_children = [] for c in children: output_children.append( [u.formatIPv6Addr(self.networkPrefix), u.formatIPv6Addr(p)]) return (u.formatIPv6Addr(self.networkPrefix), u.formatIPv6Addr(source), output_parents, output_children)
def _indicateDAO(self,tup): ''' Indicate a new DAO was received. This function parses the received packet, and if valid, updates the information needed to compute source routes. ''' # retrieve source and destination try: source = tup[0] if len(source)>8: source=source[len(source)-8:] dao = tup[1] except IndexError: log.warning("DAO too short ({0} bytes), no space for destination and source".format(len(dao))) return # log if log.isEnabledFor(logging.DEBUG): output = [] output += ['received DAO:'] output += ['- source : {0}'.format(u.formatAddr(source))] output += ['- dao : {0}'.format(u.formatBuf(dao))] output = '\n'.join(output) log.debug(output) # retrieve DAO header dao_header = {} dao_transit_information = {} dao_target_information = {} try: # RPL header dao_header['RPL_InstanceID'] = dao[0] dao_header['RPL_flags'] = dao[1] dao_header['RPL_Reserved'] = dao[2] dao_header['RPL_DAO_Sequence'] = dao[3] # DODAGID dao_header['DODAGID'] = dao[4:20] dao = dao[20:] # retrieve transit information header and parents parents = [] children = [] while len(dao)>0: if dao[0]==self._TRANSIT_INFORMATION_TYPE: # transit information option dao_transit_information['Transit_information_type'] = dao[0] dao_transit_information['Transit_information_length'] = dao[1] dao_transit_information['Transit_information_flags'] = dao[2] dao_transit_information['Transit_information_path_control'] = dao[3] dao_transit_information['Transit_information_path_sequence'] = dao[4] dao_transit_information['Transit_information_path_lifetime'] = dao[5] # address of the parent prefix = dao[6:14] parents += [dao[14:22]] dao = dao[22:] elif dao[0]==self._TARGET_INFORMATION_TYPE: dao_target_information['Target_information_type'] = dao[0] dao_target_information['Target_information_length'] = dao[1] dao_target_information['Target_information_flags'] = dao[2] dao_target_information['Target_information_prefix_length'] = dao[3] # address of the child prefix = dao[4:12] children += [dao[12:20]] dao = dao[20:] else: log.warning("DAO with wrong Option {0}. Neither Transit nor Target.".format(dao[0])) return except IndexError: log.warning("DAO too short ({0} bytes), no space for DAO header".format(len(dao))) return # log output = [] output += [''] output += ['received RPL DAO from {0}:{1}'.format(u.formatIPv6Addr(self.networkPrefix),u.formatIPv6Addr(source))] output += ['- parents:'] for p in parents: output += [' {0}:{1}'.format(u.formatIPv6Addr(self.networkPrefix),u.formatIPv6Addr(p))] output += ['- children:'] for p in children: output += [' {0}:{1}'.format(u.formatIPv6Addr(self.networkPrefix),u.formatIPv6Addr(p))] output = '\n'.join(output) if log.isEnabledFor(logging.DEBUG): log.debug(output) print output node = u.formatIPv6Addr(source) if not (node in self.parentsDaoSeq.keys()): self.parentsDaoSeq[node] = [dao_header['RPL_DAO_Sequence']] else: self.parentsDaoSeq[node].append(dao_header['RPL_DAO_Sequence']) with open('dao_sequence.txt','a') as f: f.write(str(self.parentsDaoSeq)+'\n') # if you get here, the DAO was parsed correctly # update parents information with parents collected -- calls topology module. self.dispatch( signal = 'updateParents', data = (tuple(source),parents) )
def _indicateDAO(self,tup): ''' Indicate a new DAO was received. This function parses the received packet, and if valid, updates the information needed to compute source routes. ''' # retrieve source and destination try: source = tup[0] if len(source)>8: source=source[len(source)-8:] dao = tup[1] except IndexError: log.warning("DAO too short ({0} bytes), no space for destination and source".format(len(dao))) return # log if log.isEnabledFor(logging.DEBUG): output = [] output += ['received DAO:'] output += ['- source : {0}'.format(u.formatAddr(source))] output += ['- dao : {0}'.format(u.formatBuf(dao))] output = '\n'.join(output) log.debug(output) # retrieve DAO header dao_header = {} dao_transit_information = {} dao_target_information = {} try: # RPL header dao_header['RPL_InstanceID'] = dao[0] dao_header['RPL_flags'] = dao[1] dao_header['RPL_Reserved'] = dao[2] dao_header['RPL_DAO_Sequence'] = dao[3] # DODAGID dao_header['DODAGID'] = dao[4:20] dao = dao[20:] # retrieve transit information header and parents parents = [] children = [] while len(dao)>0: if dao[0]==self._TRANSIT_INFORMATION_TYPE: # transit information option dao_transit_information['Transit_information_type'] = dao[0] dao_transit_information['Transit_information_length'] = dao[1] dao_transit_information['Transit_information_flags'] = dao[2] dao_transit_information['Transit_information_path_control'] = dao[3] dao_transit_information['Transit_information_path_sequence'] = dao[4] dao_transit_information['Transit_information_path_lifetime'] = dao[5] # address of the parent prefix = dao[6:14] parents += [dao[14:22]] dao = dao[22:] elif dao[0]==self._TARGET_INFORMATION_TYPE: dao_target_information['Target_information_type'] = dao[0] dao_target_information['Target_information_length'] = dao[1] dao_target_information['Target_information_flags'] = dao[2] dao_target_information['Target_information_prefix_length'] = dao[3] # address of the child prefix = dao[4:12] children += [dao[12:20]] dao = dao[20:] else: log.warning("DAO with wrong Option {0}. Neither Transit nor Target.".format(dao[0])) return except IndexError: log.warning("DAO too short ({0} bytes), no space for DAO header".format(len(dao))) return # log output = [] output += [''] output += ['received RPL DAO from {0}:{1}'.format(u.formatIPv6Addr(self.networkPrefix),u.formatIPv6Addr(source))] output += ['- parents:'] for p in parents: output += [' {0}:{1}'.format(u.formatIPv6Addr(self.networkPrefix),u.formatIPv6Addr(p))] output += ['- children:'] for p in children: output += [' {0}:{1}'.format(u.formatIPv6Addr(self.networkPrefix),u.formatIPv6Addr(p))] output = '\n'.join(output) if log.isEnabledFor(logging.DEBUG): log.debug(output) print output # if you get here, the DAO was parsed correctly # update parents information with parents collected -- calls topology module. self.dispatch( signal = 'updateParents', data = (tuple(source),parents) )
def _v6ToMesh_notif(self,sender,signal,data): ''' Converts a IPv6 packet into a 6LoWPAN packet. This function assumes there is a component listening on the EventBus which answers to the 'getSourceRoute' signal. This function dispatches the 6LoWPAN packet with signal 'bytesToMesh'. ''' try: ipv6_bytes = data # turn raw byte into dictionary of fields ipv6 = self.disassemble_ipv6(ipv6_bytes) # filter out multicast packets if ipv6['dst_addr'][0]==0xff: return if ipv6['dst_addr'][0]==0xfe and ipv6['dst_addr'][1]==0x80: isLinkLocal = True else: isLinkLocal = False # log if log.isEnabledFor(logging.DEBUG): log.debug(self._format_IPv6(ipv6,ipv6_bytes)) # convert IPv6 dictionary into 6LoWPAN dictionary lowpan = self.ipv6_to_lowpan(ipv6) # add the source route to this destination if len(lowpan['dst_addr'])==16: dst_addr=lowpan['dst_addr'][8:] elif len(lowpan['dst_addr'])==8: dst_addr=lowpan['dst_addr'] else: dst_addr=None log.warning('unsupported address format {0}'.format(lowpan['dst_addr'])) if isLinkLocal: lowpan['route'] = [dst_addr] else: lowpan['route'] = self._getSourceRoute(dst_addr) if len(lowpan['route'])<2: # no source route could be found log.error('no source route to {0}'.format(lowpan['dst_addr'])) # TODO: return ICMPv6 message return lowpan['route'].pop() #remove last as this is me. lowpan['nextHop'] = lowpan['route'][len(lowpan['route'])-1] #get next hop as this has to be the destination address, this is the last element on the list # turn dictionary of fields into raw bytes lowpan_bytes = self.reassemble_lowpan(lowpan) # log if log.isEnabledFor(logging.DEBUG): log.debug(self._format_lowpan(lowpan,lowpan_bytes)) # don't forward the ICMPv6 packets to the motes (unsupported) if (ipv6['next_header'] == self.IANA_ICMPv6) and (ipv6['payload'][0] == self.ERR_DESTINATIONUNREACHABLE) : log.error('ICMPv6 packet to forward to {0}, The packet is dropped (DESTINATIONUNREACHABLE not supported by openWSN)'.format( u.formatIPv6Addr(ipv6['dst_addr']) )) log.error(self._format_lowpan(lowpan,lowpan_bytes)) return #print "output:" #print lowpan_bytes # dispatch self.dispatch( signal = 'bytesToMesh', data = (lowpan['nextHop'],lowpan_bytes), ) except (ValueError,NotImplementedError) as err: log.error(err) pass