def _infoDagRoot_notif(self,sender,signal,data): ''' Record the DAGroot's EUI64 address. ''' # stop of we don't have a networkPrefix assigned yet if not self.networkPrefix: log.error("infoDagRoot signal received while not have been assigned a networkPrefix yet") return newDagRootEui64 = data['eui64'][:] with self.stateLock: sameDAGroot = (self.dagRootEui64==newDagRootEui64) # register the DAGroot if data['isDAGroot']==1 and (not sameDAGroot): # log log.info("registering DAGroot {0}".format(u.formatAddr(newDagRootEui64))) # register self.register( sender = self.WILDCARD, signal = ( tuple(self.networkPrefix + newDagRootEui64), self.PROTO_ICMPv6, self.IANA_ICMPv6_RPL_TYPE ), callback = self._fromMoteDataLocal_notif, ) # store DAGroot with self.stateLock: self.dagRootEui64 = newDagRootEui64 # unregister the DAGroot if data['isDAGroot']==0 and sameDAGroot: # log log.info("unregistering DAGroot {0}".format(u.formatAddr(newDagRootEui64))) # unregister from old DAGroot self.unregister( sender = self.WILDCARD, signal = ( tuple(self.networkPrefix + newDagRootEui64), self.PROTO_ICMPv6, self.IANA_ICMPv6_RPL_TYPE ), callback = self._fromMoteDataLocal_notif, ) # clear DAGroot with self.stateLock: self.dagRootEui64 = None
def _infoDagRoot_notif(self,sender,signal,data): ''' Record the DAGroot's EUI64 address. ''' # stop of we don't have a networkPrefix assigned yet if not self.networkPrefix: log.error("infoDagRoot signal received while not have been assigned a networkPrefix yet") return newDagRootEui64 = data['eui64'][:] with self.stateLock: sameDAGroot = (self.dagRootEui64==newDagRootEui64) # register the DAGroot if data['isDAGroot']==1 and (not sameDAGroot): # log log.info("registering DAGroot {0}".format(u.formatAddr(newDagRootEui64))) # register self.register( sender = self.WILDCARD, signal = ( tuple(self.networkPrefix + newDagRootEui64), self.PROTO_ICMPv6, self.IANA_ICMPv6_RPL_TYPE ), callback = self._fromMoteDataLocal_notif, ) # store DAGroot with self.stateLock: self.dagRootEui64 = newDagRootEui64 # unregister the DAGroot if data['isDAGroot']==0 and sameDAGroot: # log log.info("unregistering DAGroot {0}".format(u.formatAddr(newDagRootEui64))) # unregister from old DAGroot self.unregister( sender = self.WILDCARD, signal = ( tuple(self.networkPrefix + newDagRootEui64), self.PROTO_ICMPv6, self.IANA_ICMPv6_RPL_TYPE ), callback = self._fromMoteDataLocal_notif, ) # clear DAGroot with self.stateLock: self.dagRootEui64 = None
def _format_lowpan(self, lowpan, lowpan_bytes): output = [] output += [''] output += [''] output += [ '============================= lowpan packet ===================================' ] output += [''] output += ['tf: {0}'.format(u.formatBuf(lowpan['tf']))] output += ['nh: {0}'.format(u.formatBuf(lowpan['nh']))] output += [ 'hlim: {0}'.format(u.formatBuf(lowpan['hlim'])) ] output += ['cid: {0}'.format(u.formatBuf(lowpan['cid']))] output += [ 'src_addr: {0}'.format(u.formatBuf(lowpan['src_addr'])) ] output += [ 'dst_addr: {0}'.format(u.formatBuf(lowpan['dst_addr'])) ] if 'route' in lowpan: output += ['source route:'] for hop in lowpan['route']: output += [' - {0}'.format(u.formatAddr(hop))] output += [ 'payload: {0}'.format(u.formatBuf(lowpan['payload'])) ] output += [''] output += [self._formatWireshark(lowpan_bytes)] output += [''] return '\n'.join(output)
def test_sourceRoute(expectedSourceRoute): ''' This tests the following topology MOTE_A <- MOTE_B <- MOTE_C <- MOTE_D ''' sourceRoute = SourceRoute.SourceRoute() topo = topology.topology() sourceRoute.dispatch( signal='updateParents', data=(tuple(MOTE_B), [MOTE_A]), ) sourceRoute.dispatch( signal='updateParents', data=(tuple(MOTE_C), [MOTE_B]), ) sourceRoute.dispatch( signal='updateParents', data=(tuple(MOTE_D), [MOTE_C]), ) expectedDestination = json.loads(expectedSourceRoute)[0] expectedRoute = json.loads(expectedSourceRoute)[1] calculatedRoute = sourceRoute.getSourceRoute(expectedDestination) # log if log.isEnabledFor(logging.DEBUG): output = [] output += ['\n'] output += [ 'expectedDestination: {0}'.format( u.formatAddr(expectedDestination)) ] output += ['expectedRoute:'] for m in expectedRoute: output += ['- {0}'.format(u.formatAddr(m))] output += ['calculatedRoute:'] for m in calculatedRoute: output += ['- {0}'.format(u.formatAddr(m))] output = '\n'.join(output) log.debug(output) assert calculatedRoute == expectedRoute
def _infoDagRoot_notif(self, sender, signal, data): ''' Record the DAGroot's EUI64 address. ''' eui64 = data['eui64'][:] # register if DAGroot if data['isDAGroot'] == 1 and self.networkPrefix: # log log.info("registering to DAGroot {0}".format(u.formatAddr(eui64))) # register self.register( sender=self.WILDCARD, signal=(tuple(self.networkPrefix + eui64), self.PROTO_ICMPv6, self.IANA_ICMPv6_RPL_TYPE), callback=self._fromMoteDataLocal_notif, ) # store DAGroot with self.stateLock: self.dagRootEui64 = data['eui64'][:] # unregister if not DAGroot if data['isDAGroot'] == 0: # log log.info("unregistering from DAGroot {0}".format( u.formatAddr(eui64))) # unregister from old DAGroot self.unregister( sender=self.WILDCARD, signal=(tuple(self.networkPrefix + eui64), self.PROTO_ICMPv6, self.IANA_ICMPv6_RPL_TYPE), callback=self._fromMoteDataLocal_notif, ) # clear DAGroot with self.stateLock: self.dagRootEui64 = None
def test_sourceRoute(expectedSourceRoute): ''' This tests the following topology MOTE_A <- MOTE_B <- MOTE_C <- MOTE_D ''' sourceRoute = SourceRoute.SourceRoute() topo = topology.topology() sourceRoute.dispatch( signal = 'updateParents', data = (tuple(MOTE_B),[MOTE_A]), ) sourceRoute.dispatch( signal = 'updateParents', data = (tuple(MOTE_C),[MOTE_B]), ) sourceRoute.dispatch( signal = 'updateParents', data = (tuple(MOTE_D),[MOTE_C]), ) expectedDestination = json.loads(expectedSourceRoute)[0] expectedRoute = json.loads(expectedSourceRoute)[1] calculatedRoute = sourceRoute.getSourceRoute(expectedDestination) # log if log.isEnabledFor(logging.DEBUG): output = [] output += ['\n'] output += ['expectedDestination: {0}'.format(u.formatAddr(expectedDestination))] output += ['expectedRoute:'] for m in expectedRoute: output += ['- {0}'.format(u.formatAddr(m))] output += ['calculatedRoute:'] for m in calculatedRoute: output += ['- {0}'.format(u.formatAddr(m))] output = '\n'.join(output) log.debug(output) assert calculatedRoute==expectedRoute
def _infoDagRoot_notif(self, sender, signal, data): """ Record the DAGroot's EUI64 address. """ eui64 = data["eui64"][:] # register if DAGroot if data["isDAGroot"] == 1 and self.networkPrefix: # log log.info("registering to DAGroot {0}".format(u.formatAddr(eui64))) # register self.register( sender=self.WILDCARD, signal=(tuple(self.networkPrefix + eui64), self.PROTO_ICMPv6, self.IANA_ICMPv6_RPL_TYPE), callback=self._fromMoteDataLocal_notif, ) # store DAGroot with self.stateLock: self.dagRootEui64 = data["eui64"][:] # unregister if not DAGroot if data["isDAGroot"] == 0: # log log.info("unregistering from DAGroot {0}".format(u.formatAddr(eui64))) # unregister from old DAGroot self.unregister( sender=self.WILDCARD, signal=(tuple(self.networkPrefix + eui64), self.PROTO_ICMPv6, self.IANA_ICMPv6_RPL_TYPE), callback=self._fromMoteDataLocal_notif, ) # clear DAGroot with self.stateLock: self.dagRootEui64 = None
def _format_lowpan(self,lowpan,lowpan_bytes): output = [] output += [''] output += [''] output += ['============================= lowpan packet ==================================='] output += [''] output += ['tf: {0}'.format(u.formatBuf(lowpan['tf']))] output += ['nh: {0}'.format(u.formatBuf(lowpan['nh']))] output += ['hlim: {0}'.format(u.formatBuf(lowpan['hlim']))] output += ['cid: {0}'.format(u.formatBuf(lowpan['cid']))] output += ['src_addr: {0}'.format(u.formatBuf(lowpan['src_addr']))] output += ['dst_addr: {0}'.format(u.formatBuf(lowpan['dst_addr']))] if 'route' in lowpan: output += ['source route:'] for hop in lowpan['route']: output += [' - {0}'.format(u.formatAddr(hop))] output += ['payload: {0}'.format(u.formatBuf(lowpan['payload']))] output += [''] output += [self._formatWireshark(lowpan_bytes)] output += [''] return '\n'.join(output)
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 lowpan_to_ipv6(self, data): pkt_ipv6 = {} mac_prev_hop = data[0] pkt_lowpan = data[1] if pkt_lowpan[0] == self.PAGE_ONE_DISPATCH: ptr = 1 if pkt_lowpan[ ptr] & self.MASK_6LoRH == self.CRITICAL_6LoRH and pkt_lowpan[ ptr + 1] == self.TYPE_6LoRH_RPI: # next header is RPI (hop by hop) pkt_ipv6['next_header'] = self.IANA_IPv6HOPHEADER pkt_ipv6['hop_flags'] = pkt_lowpan[ptr] & self.FLAG_MASK ptr = ptr + 2 if pkt_ipv6['hop_flags'] & self.I_FLAG == 0: pkt_ipv6['hop_rplInstanceID'] = pkt_lowpan[ptr] ptr += 1 else: pkt_ipv6['hop_rplInstanceID'] = 0 if pkt_ipv6['hop_flags'] & self.K_FLAG == 0: pkt_ipv6['hop_senderRank'] = ((pkt_lowpan[ptr]) << 8) + ( (pkt_lowpan[ptr + 1]) << 0) ptr += 2 else: pkt_ipv6['hop_senderRank'] = (pkt_lowpan[ptr]) << 8 ptr += 1 # iphc is following after hopbyhop header pkt_ipv6['hop_next_header'] = self.IPV6_HEADER if pkt_lowpan[ ptr] & self.MASK_6LoRH == self.ELECTIVE_6LoRH and pkt_lowpan[ ptr + 1] == self.TYPE_6LoRH_IP_IN_IP: # ip in ip encapsulation length = pkt_lowpan[ptr] & self.MASK_LENGTH_6LoRH_IPINIP pkt_ipv6['hop_limit'] = pkt_lowpan[ptr + 2] ptr += 3 if length == 1: pkt_ipv6[ 'src_addr'] = openTun.IPV6PREFIX + openTun.IPV6HOST elif length == 9: pkt_ipv6['src_addr'] = self.networkPrefix + pkt_lowpan[ ptr:ptr + 8] ptr += 8 elif length == 17: pkt_ipv6['src_addr'] = pkt_lowpan[ptr:ptr + 16] ptr += 16 else: log.error("ERROR wrong length of encapsulate") elif pkt_lowpan[ ptr] & self.MASK_6LoRH == self.ELECTIVE_6LoRH and pkt_lowpan[ ptr + 1] == self.TYPE_6LoRH_DEADLINE: length = pkt_lowpan[ptr] & self.MASK_LENGTH_6LoRH_IPINIP nxt_byte = pkt_lowpan[ptr + 2] # 3rd byte o_val = (pkt_lowpan[ptr + 2] & self.ORG_FLAG) >> 7 d_val = (pkt_lowpan[ptr + 2] & self.DELAY_FLAG) >> 6 etl_val = (pkt_lowpan[ptr + 2] & self.ETL_FLAG) >> 3 otl_val = (pkt_lowpan[ptr + 2] & self.OTL_FLAG) # 4th byte tu_val = (pkt_lowpan[ptr + 3] & self.TU_FLAG) >> 6 exponent = (pkt_lowpan[ptr + 3] & self.EXP_FLAG) >> 3 # Expiration Time nxt_ptr = ptr + 4 exp_time = [] for counter in range(0, etl_val + 1): exp_time.append(pkt_lowpan[nxt_ptr + counter]) e_time = exp_time[::-1] # Origination Time if o_val == 1: org_time = [] nxt_ptr = nxt_ptr + counter + 1 for counter in range(0, otl_val + 1): org_time.append(pkt_lowpan[nxt_ptr + counter]) o_time = org_time[::-1] # log if log.isEnabledFor(logging.ERROR): output = [] output += [' '] output += ['Received a DeadLine Hop-by-Hop Header'] output += [ 'exp_time is {0}'.format(u.formatAddr(e_time)) ] if o_val == 1: output += [ 'org_time is {0}'.format(u.formatAddr(o_time)) ] output = '\n'.join(output) log.error(output) print output ptr += length + 1 else: log.error("ERROR no support this type of 6LoRH yet") else: ptr = 2 if (pkt_lowpan[0] >> 5) != 0x03: log.error("ERROR not a 6LowPAN packet") return # tf tf = ((pkt_lowpan[0]) >> 3) & 0x03 if tf == self.IPHC_TF_3B: pkt_ipv6['flow_label'] = ((pkt_lowpan[ptr]) << 16) + ( (pkt_lowpan[ptr + 1]) << 8) + ((pkt_lowpan[ptr + 2]) << 0) ptr = ptr + 3 elif tf == self.IPHC_TF_ELIDED: pkt_ipv6['flow_label'] = 0 else: log.error("Unsupported or wrong tf") # nh nh = ((pkt_lowpan[0]) >> 2) & 0x01 if nh == self.IPHC_NH_INLINE: pkt_ipv6['next_header'] = (pkt_lowpan[ptr]) ptr = ptr + 1 elif nh == self.IPHC_NH_COMPRESSED: # the next header will be retrieved later pass else: log.error("wrong nh field nh=" + str(nh)) # hlim hlim = (pkt_lowpan[0]) & 0x03 if hlim == self.IPHC_HLIM_INLINE: pkt_ipv6['hop_limit'] = (pkt_lowpan[ptr]) ptr = ptr + 1 elif hlim == self.IPHC_HLIM_1: pkt_ipv6['hop_limit'] = 1 elif hlim == self.IPHC_HLIM_64: pkt_ipv6['hop_limit'] = 64 elif hlim == self.IPHC_HLIM_255: pkt_ipv6['hop_limit'] = 255 else: log.error("wrong hlim==" + str(hlim)) # sac sac = ((pkt_lowpan[1]) >> 6) & 0x01 if sac == self.IPHC_SAC_STATELESS: prefix = self.LINK_LOCAL_PREFIX elif sac == self.IPHC_SAC_STATEFUL: prefix = self.networkPrefix # sam sam = ((pkt_lowpan[1]) >> 4) & 0x03 if sam == self.IPHC_SAM_ELIDED: #pkt from the previous hop pkt_ipv6['src_addr'] = prefix + mac_prev_hop elif sam == self.IPHC_SAM_16B: a1 = pkt_lowpan[ptr] a2 = pkt_lowpan[ptr + 1] ptr = ptr + 2 s = ''.join( ['\x00', '\x00', '\x00', '\x00', '\x00', '\x00', a1, a2]) pkt_ipv6['src_addr'] = prefix + s elif sam == self.IPHC_SAM_64B: pkt_ipv6['src_addr'] = prefix + pkt_lowpan[ptr:ptr + 8] ptr = ptr + 8 elif sam == self.IPHC_SAM_128B: pkt_ipv6['src_addr'] = pkt_lowpan[ptr:ptr + 16] ptr = ptr + 16 else: log.error("wrong sam==" + str(sam)) # dac dac = ((pkt_lowpan[1]) >> 2) & 0x01 if dac == self.IPHC_DAC_STATELESS: prefix = self.LINK_LOCAL_PREFIX elif dac == self.IPHC_DAC_STATEFUL: prefix = self.networkPrefix # dam dam = ((pkt_lowpan[1]) & 0x03) if dam == self.IPHC_DAM_ELIDED: if log.isEnabledFor(logging.DEBUG): log.debug( "IPHC_DAM_ELIDED this packet is for the dagroot!") pkt_ipv6['dst_addr'] = prefix + self.dagRootEui64 elif dam == self.IPHC_DAM_16B: a1 = pkt_lowpan[ptr] a2 = pkt_lowpan[ptr + 1] ptr = ptr + 2 s = ''.join( ['\x00', '\x00', '\x00', '\x00', '\x00', '\x00', a1, a2]) pkt_ipv6['dst_addr'] = prefix + s elif dam == self.IPHC_DAM_64B: pkt_ipv6['dst_addr'] = prefix + pkt_lowpan[ptr:ptr + 8] ptr = ptr + 8 elif dam == self.IPHC_DAM_128B: pkt_ipv6['dst_addr'] = pkt_lowpan[ptr:ptr + 16] ptr = ptr + 16 else: log.error("wrong dam==" + str(dam)) if nh == self.IPHC_NH_COMPRESSED: if ((pkt_lowpan[ptr] >> 4) & 0x0f) == self.NHC_DISPATCH: eid = (pkt_lowpan[ptr] & self.NHC_EID_MASK) >> 1 if eid == self.NHC_EID_HOPBYHOP: pkt_ipv6['next_header'] = self.IANA_IPv6HOPHEADER elif eid == self.NHC_EID_IPV6: pkt_ipv6['next_header'] = self.IPV6_HEADER else: log.error("wrong NH_EID==" + str(eid)) elif pkt_lowpan[ptr] & self.NHC_UDP_ID == self.NHC_UDP_ID: pkt_ipv6['next_header'] = self.IANA_UDP #hop by hop header #composed of NHC, NextHeader,Len + Rpl Option if pkt_ipv6['next_header'] == self.IANA_IPv6HOPHEADER: pkt_ipv6['hop_nhc'] = pkt_lowpan[ptr] ptr = ptr + 1 if (pkt_ipv6['hop_nhc'] & 0x01) == 0: pkt_ipv6['hop_next_header'] = pkt_lowpan[ptr] ptr = ptr + 1 else: # the next header filed will be elided pass pkt_ipv6['hop_hdr_len'] = pkt_lowpan[ptr] ptr = ptr + 1 #start of RPL Option pkt_ipv6['hop_optionType'] = pkt_lowpan[ptr] ptr = ptr + 1 pkt_ipv6['hop_optionLen'] = pkt_lowpan[ptr] ptr = ptr + 1 pkt_ipv6['hop_flags'] = pkt_lowpan[ptr] ptr = ptr + 1 pkt_ipv6['hop_rplInstanceID'] = pkt_lowpan[ptr] ptr = ptr + 1 pkt_ipv6['hop_senderRank'] = ((pkt_lowpan[ptr]) << 8) + ( (pkt_lowpan[ptr + 1]) << 0) ptr = ptr + 2 #end RPL option if (pkt_ipv6['hop_nhc'] & 0x01) == 1: if ((pkt_lowpan[ptr] >> 1) & 0x07) == self.NHC_EID_IPV6: pkt_ipv6['hop_next_header'] = self.IPV6_HEADER # payload pkt_ipv6['version'] = 6 pkt_ipv6['traffic_class'] = 0 pkt_ipv6['payload'] = pkt_lowpan[ptr:len(pkt_lowpan)] pkt_ipv6['payload_length'] = len(pkt_ipv6['payload']) pkt_ipv6['pre_hop'] = mac_prev_hop return pkt_ipv6
def lowpan_to_ipv6(self,data): pkt_ipv6 = {} mac_prev_hop=data[0] pkt_lowpan=data[1] if pkt_lowpan[0]==self.PAGE_ONE_DISPATCH: ptr = 1 if pkt_lowpan[ptr] & self.MASK_6LoRH == self.CRITICAL_6LoRH and pkt_lowpan[ptr+1] == self.TYPE_6LoRH_RPI: # next header is RPI (hop by hop) pkt_ipv6['next_header'] = self.IANA_IPv6HOPHEADER pkt_ipv6['hop_flags'] = pkt_lowpan[ptr] & self.FLAG_MASK ptr = ptr+2 if pkt_ipv6['hop_flags'] & self.I_FLAG==0: pkt_ipv6['hop_rplInstanceID'] = pkt_lowpan[ptr] ptr += 1 else: pkt_ipv6['hop_rplInstanceID'] = 0 if pkt_ipv6['hop_flags'] & self.K_FLAG==0: pkt_ipv6['hop_senderRank'] = ((pkt_lowpan[ptr]) << 8) + ((pkt_lowpan[ptr+1]) << 0) ptr += 2 else: pkt_ipv6['hop_senderRank'] = (pkt_lowpan[ptr]) << 8 ptr += 1 # iphc is following after hopbyhop header pkt_ipv6['hop_next_header'] = self.IPV6_HEADER if pkt_lowpan[ptr] & self.MASK_6LoRH == self.ELECTIVE_6LoRH and pkt_lowpan[ptr+1] == self.TYPE_6LoRH_IP_IN_IP: # ip in ip encapsulation length = pkt_lowpan[ptr] & self.MASK_LENGTH_6LoRH_IPINIP pkt_ipv6['hop_limit'] = pkt_lowpan[ptr+2] ptr += 3 if length == 1: pkt_ipv6['src_addr'] = openTun.IPV6PREFIX + openTun.IPV6HOST elif length == 9: pkt_ipv6['src_addr'] = self.networkPrefix + pkt_lowpan[ptr:ptr+8] ptr += 8 elif length == 17: pkt_ipv6['src_addr'] = pkt_lowpan[ptr:ptr+16] ptr += 16 else: log.error("ERROR wrong length of encapsulate") elif pkt_lowpan[ptr] & self.MASK_6LoRH == self.ELECTIVE_6LoRH and pkt_lowpan[ptr+1] == self.TYPE_6LoRH_DEADLINE: length = pkt_lowpan[ptr] & self.MASK_LENGTH_6LoRH_IPINIP nxt_byte = pkt_lowpan[ptr+2] # 3rd byte o_val = (pkt_lowpan[ptr+2] & self.ORG_FLAG) >> 7 d_val = (pkt_lowpan[ptr+2] & self.DELAY_FLAG) >> 6 etl_val = (pkt_lowpan[ptr+2] & self.ETL_FLAG) >> 3 otl_val = (pkt_lowpan[ptr+2] & self.OTL_FLAG) # 4th byte tu_val = (pkt_lowpan[ptr+3] & self.TU_FLAG) >> 6 exponent = (pkt_lowpan[ptr+3] & self.EXP_FLAG) >> 3 # Expiration Time nxt_ptr = ptr+4 exp_time = [] for counter in range (0,etl_val+1): exp_time.append(pkt_lowpan[nxt_ptr+counter]) e_time = exp_time[::-1] # Origination Time if o_val == 1: org_time = [] nxt_ptr = nxt_ptr+counter+1 for counter in range (0,otl_val+1): org_time.append(pkt_lowpan[nxt_ptr+counter]) o_time = org_time[::-1] # log if log.isEnabledFor(logging.ERROR): output = [] output += [' '] output += ['Received a DeadLine Hop-by-Hop Header'] output += ['exp_time is {0}'.format(u.formatAddr(e_time))] if o_val == 1: output += ['org_time is {0}'.format(u.formatAddr(o_time))] output = '\n'.join(output) log.error(output) print output ptr += length+1 else: log.error("ERROR no support this type of 6LoRH yet") else: ptr = 2 if (pkt_lowpan[0] >> 5) != 0x03: log.error("ERROR not a 6LowPAN packet") return # tf tf = ((pkt_lowpan[0]) >> 3) & 0x03 if tf == self.IPHC_TF_3B: pkt_ipv6['flow_label'] = ((pkt_lowpan[ptr]) << 16) + ((pkt_lowpan[ptr+1]) << 8) + ((pkt_lowpan[ptr+2]) << 0) ptr = ptr + 3 elif tf == self.IPHC_TF_ELIDED: pkt_ipv6['flow_label'] = 0 else: log.error("Unsupported or wrong tf") # nh nh = ((pkt_lowpan[0]) >> 2) & 0x01 if nh == self.IPHC_NH_INLINE: pkt_ipv6['next_header'] = (pkt_lowpan[ptr]) ptr = ptr+1 elif nh == self.IPHC_NH_COMPRESSED: # the next header will be retrieved later pass else: log.error("wrong nh field nh="+str(nh)) # hlim hlim = (pkt_lowpan[0]) & 0x03 if hlim == self.IPHC_HLIM_INLINE: pkt_ipv6['hop_limit'] = (pkt_lowpan[ptr]) ptr = ptr+1 elif hlim == self.IPHC_HLIM_1: pkt_ipv6['hop_limit'] = 1 elif hlim == self.IPHC_HLIM_64: pkt_ipv6['hop_limit'] = 64 elif hlim == self.IPHC_HLIM_255: pkt_ipv6['hop_limit'] = 255 else: log.error("wrong hlim=="+str(hlim)) # sac sac = ((pkt_lowpan[1]) >> 6) & 0x01 if sac == self.IPHC_SAC_STATELESS: prefix = self.LINK_LOCAL_PREFIX elif sac == self.IPHC_SAC_STATEFUL: prefix = self.networkPrefix # sam sam = ((pkt_lowpan[1]) >> 4) & 0x03 if sam == self.IPHC_SAM_ELIDED: #pkt from the previous hop pkt_ipv6['src_addr'] = prefix + mac_prev_hop elif sam == self.IPHC_SAM_16B: a1 = pkt_lowpan[ptr] a2 = pkt_lowpan[ptr+1] ptr = ptr+2 s = ''.join(['\x00','\x00','\x00','\x00','\x00','\x00',a1,a2]) pkt_ipv6['src_addr'] = prefix+s elif sam == self.IPHC_SAM_64B: pkt_ipv6['src_addr'] = prefix+pkt_lowpan[ptr:ptr+8] ptr = ptr + 8 elif sam == self.IPHC_SAM_128B: pkt_ipv6['src_addr'] = pkt_lowpan[ptr:ptr+16] ptr = ptr + 16 else: log.error("wrong sam=="+str(sam)) # dac dac = ((pkt_lowpan[1]) >> 2) & 0x01 if dac == self.IPHC_DAC_STATELESS: prefix = self.LINK_LOCAL_PREFIX elif dac == self.IPHC_DAC_STATEFUL: prefix = self.networkPrefix # dam dam = ((pkt_lowpan[1]) & 0x03) if dam == self.IPHC_DAM_ELIDED: if log.isEnabledFor(logging.DEBUG): log.debug("IPHC_DAM_ELIDED this packet is for the dagroot!") pkt_ipv6['dst_addr'] = prefix+self.dagRootEui64 elif dam == self.IPHC_DAM_16B: a1 = pkt_lowpan[ptr] a2 = pkt_lowpan[ptr+1] ptr = ptr+2 s = ''.join(['\x00','\x00','\x00','\x00','\x00','\x00',a1,a2]) pkt_ipv6['dst_addr'] = prefix+s elif dam == self.IPHC_DAM_64B: pkt_ipv6['dst_addr'] = prefix+pkt_lowpan[ptr:ptr+8] ptr = ptr + 8 elif dam == self.IPHC_DAM_128B: pkt_ipv6['dst_addr'] = pkt_lowpan[ptr:ptr+16] ptr = ptr + 16 else: log.error("wrong dam=="+str(dam)) if nh == self.IPHC_NH_COMPRESSED: if ((pkt_lowpan[ptr] >> 4) & 0x0f) == self.NHC_DISPATCH: eid = (pkt_lowpan[ptr] & self.NHC_EID_MASK) >> 1 if eid == self.NHC_EID_HOPBYHOP: pkt_ipv6['next_header'] = self.IANA_IPv6HOPHEADER elif eid == self.NHC_EID_IPV6: pkt_ipv6['next_header'] = self.IPV6_HEADER else: log.error("wrong NH_EID=="+str(eid)) elif pkt_lowpan[ptr] & self.NHC_UDP_ID == self.NHC_UDP_ID: pkt_ipv6['next_header'] = self.IANA_UDP #hop by hop header #composed of NHC, NextHeader,Len + Rpl Option if pkt_ipv6['next_header'] == self.IANA_IPv6HOPHEADER: pkt_ipv6['hop_nhc'] = pkt_lowpan[ptr] ptr = ptr+1 if (pkt_ipv6['hop_nhc'] & 0x01) == 0: pkt_ipv6['hop_next_header'] = pkt_lowpan[ptr] ptr = ptr+1 else : # the next header filed will be elided pass pkt_ipv6['hop_hdr_len'] = pkt_lowpan[ptr] ptr = ptr+1 #start of RPL Option pkt_ipv6['hop_optionType'] = pkt_lowpan[ptr] ptr = ptr+1 pkt_ipv6['hop_optionLen'] = pkt_lowpan[ptr] ptr = ptr+1 pkt_ipv6['hop_flags'] = pkt_lowpan[ptr] ptr = ptr+1 pkt_ipv6['hop_rplInstanceID'] = pkt_lowpan[ptr] ptr = ptr+1 pkt_ipv6['hop_senderRank'] = ((pkt_lowpan[ptr]) << 8) + ((pkt_lowpan[ptr+1]) << 0) ptr = ptr+2 #end RPL option if (pkt_ipv6['hop_nhc'] & 0x01) == 1: if ((pkt_lowpan[ptr]>>1) & 0x07) == self.NHC_EID_IPV6: pkt_ipv6['hop_next_header'] = self.IPV6_HEADER # payload pkt_ipv6['version'] = 6 pkt_ipv6['traffic_class'] = 0 pkt_ipv6['payload'] = pkt_lowpan[ptr:len(pkt_lowpan)] pkt_ipv6['payload_length'] = len(pkt_ipv6['payload']) pkt_ipv6['pre_hop'] = mac_prev_hop return pkt_ipv6