示例#1
0
 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)
示例#2
0
    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
示例#3
0
    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
示例#4
0
 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
示例#5
0
 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
示例#6
0
 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)))
示例#7
0
    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)
示例#8
0
    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))
示例#9
0
 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)))
示例#10
0
def test_formatIPv6Addr(expectedformatipv6):

    (ipv6_list, ipv6_string) = json.loads(expectedformatipv6)

    print ipv6_string

    assert u.formatIPv6Addr(ipv6_list) == ipv6_string
示例#11
0
 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)
示例#12
0
def test_formatIPv6Addr(expectedformatipv6):

    (ipv6_list, ipv6_string) = json.loads(expectedformatipv6)

    print ipv6_string

    assert u.formatIPv6Addr(ipv6_list) == ipv6_string
示例#13
0
 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)
示例#14
0
 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))
示例#15
0
    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
示例#16
0
    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)
示例#17
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)  
     )
示例#18
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)  
     )
示例#19
0
    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