Beispiel #1
0
 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
Beispiel #2
0
 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
Beispiel #3
0
 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)
Beispiel #4
0
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
Beispiel #5
0
    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
Beispiel #6
0
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
Beispiel #7
0
    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
Beispiel #8
0
 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)
Beispiel #9
0
 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)  
     )
Beispiel #10
0
 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
Beispiel #12
0
    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