コード例 #1
0
 def reg_update(self, addrs, addr_tout):
     for addr in addrs:
         if addr_tout > 0:
             self.addr_add(str(addr), addr_tout)
         elif str(addr) in self.maddrs.keys():
             self.addr_remove(str(addr))
     db.set('mlr_cache', str(self.maddrs))
コード例 #2
0
ファイル: ksh.py プロジェクト: JUDOKICK/KiBRA
def _configure():
    global SERIAL_DEV

    dongle_status = send_cmd('show status',
                             debug_level=kiserial.KiDebug.NONE)[0]

    # Wait for the dongle to reach a steady status
    logging.info('Waiting until dongle is joined...')
    db.set('dongle_status', 'disconnected')
    dongle_status = ''
    while not ('none' in dongle_status or 'joined' in dongle_status):
        dongle_status = send_cmd('show status',
                                 debug_level=kiserial.KiDebug.NONE)[0]
        time.sleep(1)

    # Different actions according to dongle status
    if dongle_status == 'none':
        if db.get('discovered') == 0:
            _dongle_apply_config()
        _enable_br()
        send_cmd('ifup')
        _configure()
    elif dongle_status == 'none - saved configuration':
        _enable_br()
        send_cmd('ifup')
        _configure()
    elif dongle_status == 'joined':
        pass
    else:  # Other 'none' statuses
        logging.warning('Dongle status was "%s".' % dongle_status)
        send_cmd('clear')
        _configure()
コード例 #3
0
ファイル: __main__.py プロジェクト: JUDOKICK/KiBRA
def _main():
    global SERVER

    # Load database
    db.load()

    # Exterior network configuration
    global_netconfig()

    # Find connected dongle
    enable_ncp()

    # Start web interface
    webserver.start()

    # Start subtasks
    mdns = MDNS()
    TASKS.append(SERIAL())
    TASKS.append(NETWORK())
    TASKS.append(DHCP())
    TASKS.append(NAT())
    TASKS.append(DNS())
    TASKS.append(MDNS())
    TASKS.append(DIAGS())
    TASKS.append(COAPSERVER())

    # Launch mDNS already
    asyncio.ensure_future(mdns.run())

    if db.get('autostart') == 1:
        db.set('action_kibra', 'start')

    asyncio.ensure_future(_master())

    asyncio.get_event_loop().run_forever()
コード例 #4
0
ファイル: ksh.py プロジェクト: simonlingoogle/KiBRA
def _configure():
    global SERIAL_DEV

    # Wait for the NCP to reach a steady status
    logging.info('Waiting until NCP is steady...')
    ncp_status = 'disconnected'
    while not ('none' in ncp_status or 'joined' in ncp_status):
        ncp_status = send_cmd('show status')[0]
        time.sleep(1)
    db.set('ncp_status', ncp_status)

    # Different actions according to NCP status
    if ncp_status == 'none':
        if not kibra.__harness__:
            _ncp_apply_config()
        _enable_br()
        send_cmd('ifup')
    elif ncp_status == 'none - saved configuration':
        _enable_br()
        send_cmd('ifup')
    elif ncp_status == 'joined':
        send_cmd('ifdown')
        _configure()
    else:  # Other 'none' statuses
        logging.warning('Dongle status was "%s".' % ncp_status)
        send_cmd('clear')
        SERIAL_DEV.wait_for('status', 'none')
        _configure()
コード例 #5
0
ファイル: ksh.py プロジェクト: simonlingoogle/KiBRA
def bbr_dataset_update():
    '''
    Update Thread BBR Service Data
    Automatically increases the sequence number
    '''
    # Increase sequence number
    bbr_sequence_number = (db.get('bbr_seq') + 1) % 0xFF

    # Build s_server_data
    reregistration_delay = db.get('rereg_delay')
    mlr_timeout = db.get('mlr_timeout')
    s_server_data = struct.pack(
        DEFS.THREAD_SERVICE_DATA_FMT,
        bbr_sequence_number,
        reregistration_delay,
        mlr_timeout,
    )

    # Store used values
    db.set('bbr_seq', bbr_sequence_number)

    # Enable BBR
    send_cmd('config service add %u %s %s' % (
        DEFS.THREAD_ENTERPRISE_NUMBER,
        DEFS.THREAD_SERVICE_DATA_BBR,
        bytes(s_server_data).hex(),
    ))
    logging.info('BBR update: Seq. = %d MLR Timeout = %d, Rereg. Delay = %d' %
                 (bbr_sequence_number, mlr_timeout, reregistration_delay))
コード例 #6
0
    async def render_post(self, request):
        req_dua = None
        status = DMStatus.ST_UNSPEC

        # Incoming TLVs parsing
        logging.info('in %s req: %s' %
                     (URI.N_DR, ThreadTLV.sub_tlvs_str(request.payload)))

        # BBR Primary/Secondary status
        if 'primary' not in db.get('bbr_status'):
            status = DMStatus.ST_NOT_PRI
        elif len(DUA_HNDLR.entries) >= DUA_LIMIT:
            status = DMStatus.ST_RES_SHRT
        else:
            dua = None
            eid = None
            elapsed = 0

            # ML-EID TLV
            value = ThreadTLV.get_value(request.payload, TLV.A_ML_EID)
            if value:
                eid = value.hex()

            # Target EID TLV
            value = ThreadTLV.get_value(request.payload, TLV.A_TARGET_EID)
            if value:
                try:
                    req_dua = bytes(value)
                    dua = ipaddress.IPv6Address(req_dua).compressed
                except:
                    status = DMStatus.ST_INV_ADDR

            # Time Since Last Transaction TLV
            value = ThreadTLV.get_value(request.payload,
                                        TLV.A_TIME_SINCE_LAST_TRANSACTION)
            if value:
                elapsed = struct.unpack('!I', value)[0]

            if eid and dua:
                # Thread Harness may force response status
                if db.get('dua_next_status'):
                    status = int(db.get('dua_next_status'))
                    db.set('dua_next_status', '')
                elif DUA_HNDLR.reg_update(eid, dua, elapsed):
                    status = DMStatus.ST_SUCESS
                else:
                    # Duplication detected (resource shortage not contemplated)
                    status = DMStatus.ST_DUP_ADDR

        # Fill and return the response
        payload = ThreadTLV(t=TLV.A_STATUS, l=1, v=[status]).array()
        if req_dua:
            payload += ThreadTLV(t=TLV.A_TARGET_EID, l=16, v=req_dua).array()
        logging.info(
            'out %s rsp: %s' % (URI.N_DR, ThreadTLV.sub_tlvs_str(payload)))
        return aiocoap.Message(code=Code.CHANGED, payload=payload)
コード例 #7
0
ファイル: ksh.py プロジェクト: simonlingoogle/KiBRA
    async def periodic(self):
        # Detect if serial was disconnected
        try:
            SERIAL_DEV.is_active()
        except IOError:
            logging.error('Device %s has been disconnected.',
                          db.get('serial_device'))
            self.kstop()
            self.kill()
        except Exception:
            logging.error('Device %s is not responding.',
                          db.get('serial_device'))
            return

        # Don't continue if device is not joined
        if db.get('ncp_status') != 'joined' or db.get(
                'status_serial') != 'running':
            return

        if not db.get('prefix_active'):
            slaac, dhcp, dp = _get_prefix_flags()

            # Don't continue if servers are not running
            if dhcp and db.get('status_dhcp') not in 'running':
                return
            if dp and db.get('status_coapserver') not in 'running':
                return

            # Enable border agent
            _bagent_on()

            # Add route
            NETWORK.ncp_route_enable(db.get('prefix'))

            # Announce prefix to the network
            prefix_handle(
                'prefix',
                'add',
                db.get('prefix'),
                stable=True,
                on_mesh=True,
                default=True,
                slaac=slaac,
                dhcp=dhcp,
                dp=dp,
            )

            # Start as Secondary (KiNOS will notify the change to Primary)
            db.set('bbr_status', 'secondary')
            logging.info('This BBR is now Secondary.')

            # Announce service
            bbr_dataset_update()

            # Mark prefix as active
            db.set('prefix_active', 1)
コード例 #8
0
ファイル: diags.py プロジェクト: JUDOKICK/KiBRA
 def kstart(self):
     ll_addr = ipaddress.IPv6Address(db.get('dongle_ll')).compressed
     self.br_permanent_addr = '%s%%%s' % (ll_addr,
                                          db.get('interior_ifname'))
     DIAGS_DB['nodes'] = []
     # Delete old values to prevent MDNS from using them before obtaning
     # the updated ones
     db.delete('dongle_xpanid')
     db.delete('dongle_netname')
     db.set('bbr_status', 'off')
コード例 #9
0
def coap_con_request():
    req_str = db.get('coap_req')
    if req_str:
        db.set('coap_req', '')
        req = json.loads(req_str.replace("'", '"'))
        dst = req.get('dst')[0]
        prt = int(req.get('prt')[0])
        uri = req.get('uri')[0]
        pld = bytes.fromhex(req.get('pld')[0])
        logging.info('out %s ntf: %s' % (uri, ThreadTLV.sub_tlvs_str(pld)))
        asyncio.ensure_future(DUA_HNDLR.ntf_client.con_request(dst, prt, uri, pld))
コード例 #10
0
ファイル: syslog.py プロジェクト: simonlingoogle/KiBRA
 def kstart(self):
     db.set('bbr_status', 'off')
     db.delete('ncp_rloc')
     db.delete('ncp_mleid')
     # Get interior link-local address
     iface_addrs = NETWORK.get_addrs(db.get('interior_ifname'),
                                     socket.AF_INET6)
     for addr in iface_addrs:
         if addr.startswith('fe80'):
             db.set('interior_ipv6_ll', addr)
             # Start listening to KiNOS syslog messages
             self.syslog = Syslog_Parser(addr)
コード例 #11
0
ファイル: webserver.py プロジェクト: JUDOKICK/KiBRA
 def start(self, props):
     while self.run:
         request = self.sock.recvfrom(1024)
         try:
             payload = request[0].decode()
         except:
             payload = ''
         if payload == 'BBR':
             db.set('discovered', 1)
             dst_addr = request[1][0]
             dst_port = request[1][1]
             logging.info('HDP request from %s' % dst_addr)
             self.sock.sendto(
                 json.dumps(props).encode(), (dst_addr, dst_port))
コード例 #12
0
    def kstop(self):
        logging.info('Stopping CoAP servers')
        for coap_server in self.running_coap_servers:
            coap_server.stop()

        db.set('bbr_status', 'off')

        # Un-listen for CoAP in required multicast addresses
        for group, params in self.mcast_groups.items():
            logging.info('Leaving %s group: %s' % (params[1], db.get(group)))
            MCAST_HNDLR.mcrouter.join_leave_group('leave', db.get(group),
                                                  db.get(params[0]))

        logging.info('Stopping Multicast handler')
        MCAST_HNDLR.stop()
        logging.info('Stopping DUA handler')
        DUA_HNDLR.stop()
コード例 #13
0
    def addr_remove(self, addr):

        # Remove the address from the volatile list
        self.maddrs.pop(addr)

        # Apply changes to cached addresses
        db.set('mlr_cache', self.maddrs)

        # Remove the address from the presistent list
        self.addr_perm_remove(addr)

        # Remove the existing multicast routes for this address
        self.mcrouter.rem_group_routes(addr)

        # Leave the multicast group
        self.mcrouter.join_leave_group('leave', addr)

        logging.info('Multicast address %s registration removed.' % addr)
コード例 #14
0
ファイル: network.py プロジェクト: simonlingoogle/KiBRA
    async def periodic(self):
        # Detect if interior interface goes down
        try:
            IPR.link_lookup(ifname=db.get('interior_ifname'), operstate='UP')
        except:
            logging.error('Interface %s went down.', db.get('interior_ifname'))
            self.kstop()
            self.kill()

        # Don't continue if NCP RLOC has not been asigned yet
        if not db.has_keys(['ncp_rloc']):
            return

        # Keep track of exterior addresses
        iface_addrs = []
        iface_addrs += get_addrs(db.get('exterior_ifname'), socket.AF_INET)
        iface_addrs += get_addrs(db.get('exterior_ifname'), socket.AF_INET6)

        # Find which addresses to remove and which ones to add
        ext_addrs = db.get('exterior_addrs')
        old_addrs = ext_addrs
        new_addrs = []
        for addr in iface_addrs:
            if addr not in old_addrs:
                new_addrs.append(addr)
            else:
                old_addrs.remove(addr)

        # Remove old addresses
        for addr in old_addrs:
            NAT.handle_nat64_masking(addr, enable=False)
            IPTABLES.handle_bagent_fwd(addr, db.get('ncp_rloc'), enable=False)

        # Add new addresses
        for addr in new_addrs:
            # TODO: except link local
            NAT.handle_nat64_masking(addr, enable=True)
            IPTABLES.handle_bagent_fwd(addr, db.get('ncp_rloc'), enable=True)

        # Notify MDNS service
        if new_addrs:
            MDNS.new_external_addresses()

        db.set('exterior_addrs', iface_addrs)
コード例 #15
0
ファイル: ksh.py プロジェクト: simonlingoogle/KiBRA
def enable_ncp():
    '''Find the device and initialize the port'''
    global SERIAL_DEV

    # Find device and initialize port
    port = _find_device(db.get('ncp_serial'))
    if not port:
        return
    logging.info('Serial device is %s.', port)
    db.set('serial_device', port)
    SERIAL_DEV = kiserial.KiSerial(port,
                                   debug=kiserial.KiDebug(
                                       kiserial.KiDebug.NONE))
    send_cmd('debug level none', debug_level=kiserial.KiDebug.NONE)

    # Save serial number
    serial = send_cmd('show snum')[0]
    db.set('ncp_serial', serial)

    # Update the NCP firmware if needed
    if kibra.__kinosver__ not in send_cmd('show swver')[-1]:
        logging.info('NCP needs a firmware update.')
        ncp_fw_update()
        enable_ncp()
    # No need to continue if NCP fw version is up to date
    else:
        logging.info('NCP firmware is up to date.')

        # Make sure we are running Thread v3 (1.2.0)
        if not kibra.__harness__ and 'Thread v3' not in send_cmd(
                'show thver')[0]:
            send_cmd('clear')
            SERIAL_DEV.wait_for('status', 'none')
            send_cmd('config thver 3')

        # Enable ECM if not enabled
        if 'off' in send_cmd('show hwconfig')[3]:
            logging.info('Enabling CDC Ethernet and reseting device.')
            send_cmd('config hwmode 4')
            send_cmd('reset')
            time.sleep(3)
            del SERIAL_DEV
            enable_ncp()
コード例 #16
0
ファイル: network.py プロジェクト: JUDOKICK/KiBRA
def global_netconfig():
    set_ext_iface()
    logging.info('External interface is %s.', db.get('exterior_ifname'))
    if not db.has_keys(['prefix']):
        logging.info('Trying to obtain a prefix via Prefix Delegation...')
        prefix = _get_prefix(db.get('exterior_ifname'))
        if not prefix:
            logging.info('It was not possible to obtain a global prefix.')
            prefix = _get_ula()
            logging.info('Generated the ULA prefix %s.' % prefix)
        # Obtain /64 subprefix
        prefix = '%s/64' % prefix.split('/')[0]
        db.set('prefix', prefix)

    # Find exterior interface addresses
    # Global IPv4 addresses
    ipv4_addrs = get_addrs(db.get('exterior_ifname'), AF_INET, scope=0)
    if ipv4_addrs:
        logging.info('Using %s as exterior IPv4 address.', ipv4_addrs[0])
        db.set('exterior_ipv4', ipv4_addrs[0])

    # Link-local IPv4 addresses
    ipv4_addrs = get_addrs(db.get('exterior_ifname'), AF_INET, scope=253)
    if ipv4_addrs:
        logging.info('Using %s as exterior IPv4 link-local address.',
                     ipv4_addrs[0])
        db.set('exterior_ipv4_ll', ipv4_addrs[0])

    # Global IPv6 addresses
    ipv6_addrs = get_addrs(db.get('exterior_ifname'), AF_INET6, scope=0)
    if ipv6_addrs:
        logging.info('Using %s as exterior IPv6 address.', ipv6_addrs[0])
        db.set('exterior_ipv6', ipv6_addrs[0])

    # Link-local IPv6 addresses
    ipv6_addrs = get_addrs(db.get('exterior_ifname'), AF_INET6, scope=253)
    if ipv6_addrs:
        logging.info('Using %s as exterior link-local IPv6 address.',
                     ipv6_addrs[0])
        db.set('exterior_ipv6_ll', ipv6_addrs[0])
コード例 #17
0
ファイル: syslog.py プロジェクト: simonlingoogle/KiBRA
def _process_message(msgid, uptime, payload):
    logging.debug('msgid = %s, uptime = %s, payload = %s' %
                  (msgid, uptime, payload))

    if msgid == SYSLOG_MSG_ID_CACHE_DEL:
        cached_eids = db.get('ncp_eid_cache')
        try:
            cached_eids.remove(payload)
            db.set('ncp_eid_cache', cached_eids)
        except:
            pass  # It didn't exist in the list
        logging.info('Address %s is not cached anymore.' % payload)
    elif msgid == SYSLOG_MSG_ID_CACHE_ADD:
        cached_eids = db.get('ncp_eid_cache')
        cached_eids.append(payload)
        db.set('ncp_eid_cache', cached_eids)
        logging.info('Address %s is now cached.' % payload)
    elif msgid == SYSLOG_MSG_ID_ALOC_DEL:
        NETWORK.handle_addr(payload, 'del')
    elif msgid == SYSLOG_MSG_ID_ALOC_ADD:
        NETWORK.handle_addr(payload, 'add')
    elif msgid == SYSLOG_MSG_ID_UNICAST_SYS_ADD:
        NETWORK.handle_addr(payload, 'add')
    elif msgid == SYSLOG_MSG_ID_AOPD_SAVED:
        _parse_active_dataset(payload)
        logging.info('Active dataset changed.')
    elif msgid == SYSLOG_MSG_ID_JOIN_STATUS_OK:
        db.set('ncp_status', 'joined')
        logging.info('Device just joined to the Thread network')
    elif msgid == SYSLOG_MSG_ID_JOIN_STATUS_ERR:
        # TODO: notify user
        logging.info('Device could not join to the Thread network')
コード例 #18
0
ファイル: ksh.py プロジェクト: JUDOKICK/KiBRA
    async def periodic(self):
        # Detect if serial was disconnected
        try:
            SERIAL_DEV.is_active()
        except IOError:
            logging.error('Device %s has been disconnected.',
                          db.get('serial_device'))
            self.kstop()
            self.kill()

        if not db.get('prefix_active'):
            dp = True if db.get('prefix_dua') else False
            dhcp = True if db.get('prefix_dhcp') else False
            slaac = True if not dp and not dhcp else False

            # Don't continue if servers are not running
            if dhcp and db.get('status_dhcp') not in 'running':
                return
            if dp and db.get('status_coapserver') not in 'running':
                return

            # Add route
            dongle_route_enable(db.get('prefix'))

            # Announce prefix to the network
            prefix_handle('prefix',
                          'add',
                          db.get('prefix'),
                          stable=True,
                          on_mesh=True,
                          default=True,
                          slaac=slaac,
                          dhcp=dhcp,
                          dp=dp)

            if dp:
                bbr_dataset_update()

            # Mark prefix as active
            db.set('prefix_active', 1)
コード例 #19
0
ファイル: network.py プロジェクト: simonlingoogle/KiBRA
def set_ext_iface():
    '''Select the right external interface'''

    if not db.get('exterior_ifname'):
        links = IPR.get_links()
        for link in links:
            # Don't choose the loopback interface
            if link['flags'] & IFF_LOOPBACK:
                continue
            # Must be up
            if not link['flags'] & IFF_UP:
                continue
            # Must have multicast enabled
            if not link['flags'] & IFF_MULTICAST:
                continue
            # Don't choose the Kirale's Thread device
            if link.get_attr('IFLA_ADDRESS').startswith('84:04:d2'):
                continue
            # First interface matching all criteria is selected
            db.set('exterior_ifname', link.get_attr('IFLA_IFNAME'))
            break

    # No appropiate interface was found
    if not db.get('exterior_ifname'):
        raise Exception('No exterior interface available.')

    # Set exterior index
    idx = IPR.link_lookup(ifname=db.get('exterior_ifname'))[0]
    db.set('exterior_ifnumber', idx)

    # Set exterior MAC
    db.set('exterior_mac', IPR.get_links(idx)[0].get_attr('IFLA_ADDRESS'))
コード例 #20
0
ファイル: ksh.py プロジェクト: JUDOKICK/KiBRA
    def kstop(self):
        if db.get('prefix_active'):
            # Remove prefix from the network
            dp = True if db.get('prefix_dua') else False
            dhcp = True if db.get('prefix_dhcp') else False
            slaac = True if not dp and not dhcp else False

            prefix_handle('prefix',
                          'remove',
                          db.get('prefix'),
                          stable=True,
                          on_mesh=True,
                          default=True,
                          slaac=slaac,
                          dhcp=dhcp,
                          dp=dp)

            # Mark prefix as active
            db.set('prefix_active', 0)

        _bagent_off()
        send_cmd('ifdown')
コード例 #21
0
ファイル: ksh.py プロジェクト: simonlingoogle/KiBRA
    def kstop(self):
        if db.get('prefix_active'):
            # Remove prefix from the network
            slaac, dhcp, dp = _get_prefix_flags()

            prefix_handle(
                'prefix',
                'remove',
                db.get('prefix'),
                stable=True,
                on_mesh=True,
                default=True,
                slaac=slaac,
                dhcp=dhcp,
                dp=dp,
            )

            # Mark prefix as inactive
            db.set('prefix_active', 0)

        _bagent_off()
        send_cmd('ifdown')
コード例 #22
0
    def addr_add(self, addr, addr_tout):
        if addr_tout == 0xffffffff:
            tout = datetime.datetime.max
            # Save the address in the presistent list
            maddrs_perm = db.get('maddrs_perm') or []
            if addr not in maddrs_perm:
                maddrs_perm.append(addr)
                db.set('maddrs_perm', maddrs_perm)
        else:
            if addr_tout < DEFS.MIN_MLR_TIMEOUT:
                addr_tout = DEFS.MIN_MLR_TIMEOUT
            tout = datetime.datetime.now().timestamp() + addr_tout

        # Join the multicast group in the external interface for MLDv2 handling
        if addr not in self.maddrs.keys():
            self.mcrouter.join_leave_group('join', addr)

        # Save the new address in the volatile list
        self.maddrs[addr] = tout

        logging.info('Multicast address %s registration updated (+%d s)' %
                     (addr, addr_tout))
コード例 #23
0
def main():
    global SERVER

    logging.info('Launching KiBRA v%s' % kibra.__version__)

    # Load database
    db.load()

    # Exterior network configuration
    global_netconfig()

    # Find connected NCP
    enable_ncp()

    # Start web interface
    webserver.start()

    # Start subtasks
    mdns = MDNS()
    TASKS.append(NETWORK())
    TASKS.append(SERIAL())
    TASKS.append(SYSLOG())
    TASKS.append(DHCP())
    TASKS.append(NAT())
    TASKS.append(DNS())
    TASKS.append(mdns)
    TASKS.append(DIAGS())
    if db.get('bbr_enable'):
        TASKS.append(COAPSERVER())

    # Launch mDNS already
    asyncio.ensure_future(mdns.run())

    if db.get('autostart') == 1:
        db.set('action_kibra', 'start')

    asyncio.ensure_future(_master())

    asyncio.get_event_loop().run_forever()
コード例 #24
0
    def kstop(self):
        logging.info('Stopping CoAP servers')
        for coap_server in self.coap_servers:
            coap_server.stop()

        all_network_bbrs = db.get('all_network_bbrs')
        logging.info('Leaving All Network BBRs group: %s' % all_network_bbrs)
        MCAST_HNDLR.mcrouter.join_leave_group('leave', all_network_bbrs)

        db.set('bbr_status', 'off')
        if db.get('prefix_dua'):
            all_domain_bbrs = db.get('all_domain_bbrs')
            logging.info('Leaving All Domain BBRs group: %s' % all_domain_bbrs)
            MCAST_HNDLR.mcrouter.join_leave_group('leave', all_domain_bbrs)

            logging.info('Leaving Realm-Local All-Routers group: ff03::2')
            MCAST_HNDLR.mcrouter.join_leave_group('leave', 'ff03::2',
                                                  db.get('interior_ifnumber'))

        logging.info('Stopping Multicast handler')
        MCAST_HNDLR.stop()
        logging.info('Stopping DUA handler')
        DUA_HNDLR.stop()
コード例 #25
0
ファイル: diags.py プロジェクト: JUDOKICK/KiBRA
    def _parse_net_data(self, tlvs):
        is_pbbr = False
        value = ThreadTLV.get_value(tlvs, TLV.D_NETWORK_DATA)
        if value:
            for tlv in ThreadTLV.sub_tlvs(value):
                type_ = tlv.type >> 1
                if type_ is TLV.N_SERVICE:
                    # Detect BBR Dataset encoding
                    if (tlv.value[0] >> 7 and tlv.value[1] is 1
                            and tlv.value[2] is 1):
                        server_tlvs = ThreadTLV.sub_tlvs(tlv.value[3:])
                        '''BBR is primary if there is only one Server TLV in the
                        BBR Dataset and the RLOC16 is the same as ours'''
                        if len(server_tlvs) == 1:
                            node_rloc = ipaddress.IPv6Address(
                                db.get('dongle_rloc')).packed
                            if node_rloc[14:16] == server_tlvs[0].value[0:2]:
                                is_pbbr = True
                elif type_ is TLV.N_PREFIX:
                    if db.get('prefix_dhcp') and not db.get('dhcp_aloc'):
                        # Detect DHCPv6 Agent ALOC
                        length = math.ceil(tlv.value[1] / 8)
                        byt_prefix = tlv.value[2:2 + length] + bytes(length)
                        int_prefix = int.from_bytes(byt_prefix,
                                                    byteorder='big')
                        str_prefix = ipaddress.IPv6Address(
                            int_prefix).compressed
                        str_prefix += '/%s' % tlv.value[1]
                        if str_prefix == db.get('prefix'):
                            # This is the prefix that we announced
                            for subtlv in ThreadTLV.sub_tlvs(
                                    tlv.value[(length + 2):]):
                                # TODO: verify that there is a Border Router TLV
                                # matching our RLOC16 and DHCP flag
                                if subtlv.type >> 1 is TLV.N_6LOWPAN_ID:
                                    cid = subtlv.value[0] & 0x0f
                                    rloc = db.get('dongle_rloc')
                                    aloc = list(
                                        ipaddress.IPv6Address(rloc).packed)
                                    aloc[14] = 0xfc
                                    aloc[15] = cid
                                    aloc = ipaddress.IPv6Address(
                                        bytes(aloc)).compressed
                                    db.set('dhcp_aloc', aloc)
                                    # Listen to the DHCP ALOC which is going to be
                                    # used by BR MTD children
                                    netmap(aloc, rloc)

        if is_pbbr:
            if 'primary' not in db.get('bbr_status'):
                logging.info('Setting this BBR as Primary')
            db.set('bbr_status', 'primary')
        else:
            if 'secondary' not in db.get('bbr_status'):
                logging.info('Setting this BBR as Secondary')
            db.set('bbr_status', 'secondary')
コード例 #26
0
ファイル: ksh.py プロジェクト: simonlingoogle/KiBRA
 def kstart(self):
     db.set('prefix_active', 0)
     db.set('ncp_heui64', send_cmd('show heui64')[0])
     _configure()
コード例 #27
0
ファイル: ktask.py プロジェクト: JUDOKICK/KiBRA
 def kill(self):
     logging.info('Killing task [%s]...', self.name)
     db.set(self.action_key, action.KILL)
コード例 #28
0
ファイル: diags.py プロジェクト: JUDOKICK/KiBRA
 def _parse_active_dataset(self, payload):
     # No response to /c/ag
     if payload is None or b'':
         db.set('dongle_secpol', '0')
     # Response present
     else:
         value = ThreadTLV.get_value(payload, TLV.C_CHANNEL)
         if value:
             db.set('dongle_channel', int(value[2]))
         value = ThreadTLV.get_value(payload, TLV.C_PAN_ID)
         if value:
             db.set('dongle_panid',
                    '0x' + ''.join('%02x' % byte for byte in value))
         value = ThreadTLV.get_value(payload, TLV.C_EXTENDED_PAN_ID)
         if value:
             db.set('dongle_xpanid',
                    '0x' + ''.join('%02x' % byte for byte in value))
         value = ThreadTLV.get_value(payload, TLV.C_NETWORK_NAME)
         if value:
             db.set('dongle_netname',
                    ''.join('%c' % byte for byte in value))
         value = ThreadTLV.get_value(payload,
                                     TLV.C_NETWORK_MESH_LOCAL_PREFIX)
         if value:
             prefix_bytes = bytes(value) + bytes(8)
             prefix_addr = ipaddress.IPv6Address(prefix_bytes)
             db.set('dongle_prefix', prefix_addr.compressed + '/64')
         value = ThreadTLV.get_value(payload, TLV.C_ACTIVE_TIMESTAMP)
         value = ThreadTLV.get_value(payload, TLV.C_SECURITY_POLICY)
         if value:
             db.set('dongle_secpol', value.hex())
コード例 #29
0
ファイル: ktask.py プロジェクト: JUDOKICK/KiBRA
    async def run(self):
        logging.info('Loading task [%s]...', self.name)
        self.is_alive = True

        # Preconfiguration
        if self.check_status() is status.STOPPED:
            db.set(self.status_key, status.STOPPED)
            db.set(self.action_key, action.START)
        else:
            db.set(self.action_key, action.NONE)
            db.set(self.status_key, self.check_status())

        # Loop
        while self.is_alive:
            task_action = db.get(self.action_key)

            if task_action in (action.STOP, action.KILL):
                db.set(self.status_key, status.STOPPING)

            task_status = db.get(self.status_key)

            # Stopped case
            if task_status is status.STOPPED:
                # Start task if needed
                if task_action is action.START:
                    db.set(self.status_key, status.STARTING)
                    # Wait for tasks
                    for task in self.start_tasks:
                        logging.info('Task [%s] is waiting for [%s] to start.',
                                     self.name, task)
                        while db.get('status_' + task) is not status.RUNNING:
                            await asyncio.sleep(1)
                    # Wait for keys
                    while not db.has_keys(self.start_keys):
                        await asyncio.sleep(1)
                    try:
                        self.kstart()
                        db.set(self.status_key, status.RUNNING)
                        logging.info('Task [%s] has now started.', self.name)
                    except Exception as exc:
                        db.set(self.status_key, status.ERRORED)
                        logging.error('Task [%s] errored on start: %s',
                                      self.name, exc)
                    db.set(self.action_key, action.NONE)
                elif task_action is action.KILL:
                    self.is_alive = False
            # Running case
            if task_status is status.RUNNING:
                # Check if other dependant tasks have stopped or errored
                for task in self.start_tasks:
                    if db.get('status_' + task) is not status.RUNNING:
                        logging.info(
                            'Task [%s] stopped and forced [%s] to stop.', task,
                            self.name)
                        self.kill()
                        break
                # Periodic tasks
                if task_action is action.NONE:
                    # Avoid execution on start/stop processes
                    await self.periodic()
            # Stop task if needed
            if task_status is status.STOPPING:
                if task_action in (action.STOP, action.KILL):
                    for task in self.stop_tasks:
                        logging.info('Task [%s] is waiting for [%s] to stop.',
                                     self.name, task)
                        while db.get('status_' + task) is not (status.STOPPED
                                                               or None):
                            await asyncio.sleep(1)
                    while not db.has_keys(self.stop_keys):
                        logging.info('Task [%s] cannot be stopped' % self.name)
                        await asyncio.sleep(1)
                    self.kstop()
                    if task_action is action.KILL:
                        self.is_alive = False
                    db.set(self.action_key, action.NONE)
                    db.set(self.status_key, status.STOPPED)
                    logging.info('Task [%s] has now stopped.', self.name)
            # All cases
            await asyncio.sleep(self.period)
コード例 #30
0
ファイル: __main__.py プロジェクト: JUDOKICK/KiBRA
async def _master():
    # TODO: Have a way to completely stop the daemon
    while True:
        # Start over
        db.set('status_kibra', 'stopped')

        # Wait until the start command is received
        while db.get('action_kibra') != 'start':
            await asyncio.sleep(0.2)

        # Start all tasks
        db.set('status_kibra', 'starting')
        for thread in TASKS:
            asyncio.ensure_future(thread.run())

        # Wait until all tasks have started
        for thread in TASKS:
            while db.get('status_' + thread.name) is not status.RUNNING:
                await asyncio.sleep(1)
        db.set('action_kibra', 'none')
        db.set('status_kibra', 'running')
        db.save()
        logging.info('All tasks have now started.')

        # Run forever
        tasks_alive = True
        while tasks_alive:
            tasks_alive = False
            for thread in TASKS:
                if db.get('status_' + thread.name) is status.RUNNING:
                    tasks_alive = True
                    break
            await asyncio.sleep(0.2)

            # Kill all tasks if stop command is received
            if db.get('action_kibra') == 'stop':
                db.set('status_kibra', 'stopping')
                for thread in TASKS:
                    db.set('action_' + thread.name, 'kill')
                db.set('action_kibra', 'none')
                logging.info('Killing all tasks...')

        db.set('status_kibra', 'stopped')
        logging.info('All tasks have now stopped.')