Пример #1
0
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')
Пример #2
0
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'))
Пример #3
0
def _ifdown():
    ifname = db.get('interior_ifname')

    # Remove custom routing table
    db.del_from_file(
        '/etc/iproute2/rt_tables',
        '\n%s\t%s\n' % (BR_TABLE_NR, db.get('bridging_table')),
        '',
    )

    # Don't continue if the interface is already down
    idx = IPR.link_lookup(ifname=ifname, operstate='UP')
    if not idx:
        return
    # Delete traffic limits
    bash('tc qdisc del dev %s root handle 1: cbq avpkt 1000 bandwidth 12mbit' %
         ifname)

    # Delete custom rule
    IPR.rule(
        'delete',
        family=socket.AF_INET6,
        table=BR_TABLE_NR,
        priority=100,
        fwmark=int(db.get('bridging_mark')),
    )

    # Bring interior interface down
    logging.info('Bringing %s interface down.', ifname)
    try:
        IPR.link('set', index=db.get('interior_ifnumber'), state='down')
    except:
        logging.error('Exception bringing %s interface down.', ifname)
Пример #4
0
    async def render_post(self, request):
        # Incoming TLVs parsing
        logging.info('in %s qry: %s' %
                     (URI.A_AQ, ThreadTLV.sub_tlvs_str(request.payload)))

        # Message not handled by Secondary BBR
        if not 'primary' in db.get('bbr_status'):
            return COAP_NO_RESPONSE

        # Find sub TLVs
        dua = None
        value = ThreadTLV.get_value(request.payload, TLV.A_TARGET_EID)
        if value:
            dua = ipaddress.IPv6Address(bytes(value))
        if not dua:
            return COAP_NO_RESPONSE

        # Don't process requests for different prefixes than DUA
        dua_prefix = ipaddress.IPv6Address(db.get('prefix').split('/')[0])
        if dua.packed[:8] != dua_prefix.packed[:8]:
            return COAP_NO_RESPONSE

        # Obtain the RLOC16 from the source's RLOC
        rloc16 = ipaddress.IPv6Address(request.remote.sockaddr[0]).packed[-2:]

        # TODO: mantain a cache
        # Propagate Address Query to the Backbone
        await DUA_HNDLR.send_bb_query(DUA_HNDLR.coap_client, dua, rloc16)

        return COAP_NO_RESPONSE
Пример #5
0
def dongle_conf():
    '''Configure several network parameters'''
    # By Kirale convention, interior MAC address is obtained from the dongle
    # serial
    serial = db.get('dongle_serial').split('+')[-1]
    interior_mac = ':'.join([
        serial[0:2], serial[2:4], serial[4:6], serial[10:12], serial[12:14],
        serial[14:16]
    ])
    db.set('interior_mac', interior_mac)
    # Also dongle MAC is related to interior MAC
    dongle_mac = bytearray.fromhex(interior_mac.replace(':', ''))
    dongle_mac[0] |= 0x02
    db.set('dongle_mac', ':'.join(['%02x' % byte for byte in dongle_mac]))
    # Find the device with the configured MAC address
    links = IPR.get_links(IFLA_ADDRESS=db.get('interior_mac').lower())
    if links:
        db.set('interior_ifname', links[0].get_attr('IFLA_IFNAME'))
        db.set('interior_ifnumber', links[0]['index'])
    else:
        raise Exception('Error: Device not found with MAC ' +
                        db.get('interior_mac'))

    # Use last 32 bits of interior MAC as bridging mark
    db.set('bridging_mark',
           int(db.get('interior_mac').replace(':', '')[-8:], 16))
    db.set('bridging_table', db.get('interior_mac'))
Пример #6
0
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))
Пример #7
0
def start():
    global HTTPD, ANNOUNCER, LOOP

    LOOP = asyncio.get_event_loop()

    print('Loading web server...')
    while not HTTPD:
        # The port may have not been closed from the previous session
        # TODO: properly close server when stopping app
        try:
            HTTPD = V6Server(('', WEB_PORT), WebServer)
        except OSError:
            time.sleep(1)
    LOOP.run_in_executor(None, HTTPD.serve_forever)
    print('Webserver is up')

    if kibra.__harness__:
        props = {
            'ven': db.get('kibra_vendor'),
            'mod': db.get('kibra_model'),
            'ver': db.get('kibra_version'),
        }
        # Announce via Harness Discovery Protocol
        props['add'] = db.get('exterior_ipv6_ll')
        props['por'] = WEB_PORT
        ANNOUNCER = HDP_Announcer()
        LOOP.run_in_executor(None, ANNOUNCER.start, props)
        print('BBR announced via HDP')
Пример #8
0
    def run_daemon(self):
        while self.ndp_on:
            # Wait for some multicast traffic to arrive
            try:
                data, src = self.icmp6_sock.recvfrom(1280)
            except:
                # socket.timeout: timed out
                time.sleep(0.2)

            # Accepting Neighbor solicit only
            if data[0] != ND_NEIGHBOR_SOLICIT:
                continue

            # Get the paramters
            _, _, _, _, tgt = struct.unpack(NS_FMT, data[: struct.calcsize(NS_FMT)])

            # Debug
            ns_tgt = ipaddress.IPv6Address(tgt).compressed
            logging.info('in ns from %s for %s' % (src[0], ns_tgt))

            # Generate Neighbor Advertisement
            if ns_tgt in db.get('exterior_addrs'):
                self.send_na(src[0], ns_tgt)
            elif ns_tgt in list(self.duas.keys()):
                delayed = not ns_tgt in db.get('ncp_eid_cache')
                self.send_na(src[0], ns_tgt, delayed=delayed)
Пример #9
0
    async def render_post(self, request):
        # Incoming TLVs parsing
        logging.info('in %s ntf: %s' %
                     (URI.A_AE, ThreadTLV.sub_tlvs_str(request.payload)))

        # Message not handled by Secondary BBR
        if not 'primary' in db.get('bbr_status'):
            return COAP_NO_RESPONSE

        # Find sub TLVs
        dua = None
        eid = None
        value = ThreadTLV.get_value(request.payload, TLV.A_TARGET_EID)
        if value:
            dua = ipaddress.IPv6Address(bytes(value))
        value = ThreadTLV.get_value(request.payload, TLV.A_ML_EID)
        if value:
            eid = value.hex()
        if not dua or not eid:
            return COAP_NO_RESPONSE

        # Don't process notifications for different prefixes than DUA
        dua_prefix = ipaddress.IPv6Address(db.get('prefix').split('/')[0])
        if dua.packed[:8] != dua_prefix.packed[:8]:
            return COAP_NO_RESPONSE

        # Remove entry if it's registered with different EID
        entry_eid, _, dad = DUA_HNDLR.find_eid(dua.compressed)
        if not dad and entry_eid != eid:
            DUA_HNDLR.remove_entry(dua=dua)

        return COAP_NO_RESPONSE
Пример #10
0
    async def render_post(self, request):
        # Incoming TLVs parsing
        logging.info('in %s ans: %s' %
                     (URI.B_BA, ThreadTLV.sub_tlvs_str(request.payload)))

        # Message not handled by Secondary BBR
        if not 'primary' in db.get('bbr_status'):
            return COAP_NO_RESPONSE
            # TODO: 9.4.8.2.9 Caching DUAs Advertised on the Backbone Link

        # Check if all required TLVs are present
        dua, eid, rloc16, elapsed, net_name = _get_b_ba_params(request.payload)
        if None in (dua, eid, elapsed, net_name):
            return COAP_NO_RESPONSE

        logging.info(
            'BB.ans: DUA=%s, ML-EID=%s, Time=%d, Net Name=%s, RLOC16=%s' %
            (dua, eid, elapsed, net_name, rloc16))

        # See if we have this DUA in our table
        src_rloc, entry_eid, _, dad = DUA_HNDLR.find_eid(dua)

        # 9.4.8.2.8 Receipt of Backbone Answer BB.ans
        if not rloc16:
            if not entry_eid:
                # Nothing to do for this EID
                return COAP_NO_RESPONSE
            elif dad is True:
                if entry_eid == eid:
                    # This DUA is still registered somewhere else, inform others
                    DUA_HNDLR.duplicated_found(dua, delete=False)
                    # Send PRO_BB.ntf
                    asyncio.ensure_future(DUA_HNDLR.send_pro_bb_ntf(dua))
                else:
                    # Duplication detected during DAD
                    DUA_HNDLR.duplicated_found(dua, delete=True)
                    # Send ADDR_ERR.ntf
                    asyncio.ensure_future(
                        DUA_HNDLR.send_addr_err(src_rloc, aiocoap.CON, dua,
                                                eid))

        else:
            # Send ADDR_NTF.ans
            bbr_rloc16 = ipaddress.IPv6Address(db.get('ncp_rloc')).packed[-2:]
            # If this BBR NCP originated the addr_qry, send addr_ntf to its
            # link local address
            if rloc16 == bbr_rloc16:
                dst = db.get('ncp_ll')
            else:
                dst = THREAD.get_rloc_from_short(db.get('ncp_prefix'), rloc16)
            asyncio.ensure_future(
                DUA_HNDLR.send_addr_ntf_ans(dst,
                                            dua,
                                            eid=eid,
                                            rloc16=bbr_rloc16,
                                            elapsed=elapsed))

        # ACK
        return aiocoap.Message(mtype=Type.ACK, code=Code.CHANGED)
Пример #11
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)
Пример #12
0
 async def periodic(self):
     try:
         interior_link_up = IPR.link_lookup(
             ifname=db.get('interior_ifname'), operstate='UP')
     except:
         interior_link_up = False
     if not interior_link_up:
         logging.error('Interface %s went down.', db.get('interior_ifname'))
         self.kstop()
         self.kill()
Пример #13
0
 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')
Пример #14
0
    async def send_bb_query(self, client, dua, rloc16=None):
        dua_bytes = ipaddress.IPv6Address(dua).packed
        payload = ThreadTLV(t=TLV.A_TARGET_EID, l=16, v=dua_bytes).array()
        if rloc16:
            payload += ThreadTLV(t=TLV.A_RLOC16, l=2, v=rloc16).array()
        dst = '%s%%%s' % (db.get('all_domain_bbrs'), db.get('exterior_ifname'))

        logging.info(
            'out %s qry: %s' % (URI.B_BQ, ThreadTLV.sub_tlvs_str(payload)))

        await client.non_request(dst, DEFS.PORT_BB, URI.B_BQ, payload)
Пример #15
0
    def run_daemon(self):
        while self.mcr_on:
            # Wait for some multicast traffic to arrive
            try:
                data = self.mc6r_sock.recv(1280)
            except:
                # socket.timeout: timed out
                time.sleep(0.2)

            if not 'primary' in db.get('bbr_status'):
                continue

            # Signal must start with zero
            if data[0] != 0:
                continue

            # Get the upcall paramters
            _, type_, in_mif, _, src, dst = struct.unpack(
                mrt6msg_fmt, data[:struct.calcsize(mrt6msg_fmt)])

            # Debug
            src_addr = ipaddress.IPv6Address(src).compressed
            dst_addr = ipaddress.IPv6Address(dst).compressed
            logging.debug('Upcall: type=%d mif=%d src=%s dst=%s' %
                          (type_, in_mif, src_addr, dst_addr))

            if type_ != MRT6MSG_NOCACHE:
                continue

            # Packet from Backbone Network (9.4.7.3)
            if in_mif == EXT_MIF:
                # Filter by registered multicast groups
                if not db.get('mlr_cache'):
                    continue
                maddrs = list(db.get('mlr_cache').keys())
                if str(dst_addr) not in maddrs:
                    continue
                out_mif = INT_MIF
            # Packet from Thread Network (9.4.7.4)
            elif in_mif == INT_MIF:
                # Rules 1 and 3 handled by KiNOS
                # Filter by forwarding flags
                dst_scope = dst[1] & 0x0F
                if dst_scope < 4:
                    continue
                if db.get('mcast_out_fwd') == 0:
                    continue
                if dst_scope == 4 and db.get('mcast_admin_fwd') == 0:
                    continue
                out_mif = EXT_MIF
            else:
                continue

            self.add_route(MCRoute(src, dst, in_mif, out_mif))
Пример #16
0
def _nat_enable():
    bash('/sbin/modprobe jool')
    if 'default' not in str(bash('jool instance display')):
        bash('jool instance add --netfilter --pool6 64:ff9b::/96')
        bash('jool global update logging-session true')
        bash('jool global update logging-bib true')
    logging.info('Prefix 64:ff9b::/96 added to NAT64 engine.')
    bash('jool pool4 add --udp %s' % db.get('exterior_ipv4'))
    bash('jool pool4 add --icmp %s' % db.get('exterior_ipv4'))
    logging.info('%s used as stateful NAT64 masking address.',
                 db.get('exterior_ipv4'))
Пример #17
0
    def service_update(self):
        r_txt = '\t\t<txt-record>%s=%s</txt-record>'
        r_bin = '\t\t<txt-record value-format="binary-hex">%s=%s</txt-record>'

        try:
            records = get_records()
            hostname = socket.gethostname()
        except:
            logging.warning('Unable to get the mDNS records.')
            return
        # Compose the new service data
        snw = []
        snw.append('<?xml version="1.0" encoding="utf-8" standalone="no"?>')
        snw.append('<!DOCTYPE service-group SYSTEM "avahi-service.dtd">')
        snw.append('<service-group>')
        snw.append('\t<name>%s %s %s</name>' %
                   (db.get('dongle_name'), records['vn'], records['mn']))
        snw.append('\t<service>')
        snw.append('\t\t<type>_meshcop._udp</type>')
        snw.append('\t\t<host-name>%s.local</host-name>' % hostname)
        snw.append('\t\t<port>%d</port>' % db.get('exterior_port_mc'))
        snw.append(r_txt % ('rv', '1'))
        snw.append(r_txt % ('tv', '1.2.0'))
        snw.append(r_bin % ('sb', records['sb']))
        snw.append(r_txt % ('vn', records['vn']))
        snw.append(r_txt % ('mn', records['mn']))
        if 'nn' in records.keys():
            snw.append(r_txt % ('nn', records['nn']))
        if 'xp' in records.keys():
            snw.append(r_bin % ('xp', records['xp']))
        if 'sq' in records.keys():
            snw.append(r_bin % ('sq', records['sq']))
        if 'bb' in records.keys():
            snw.append(r_bin % ('bb', records['bb']))
        snw.append('\t</service>')
        snw.append('</service-group>\n')
        snw = '\n'.join(snw)

        # Load the previous service file, or create it
        pathlib.Path(MDNS_SERVICES).mkdir(parents=True, exist_ok=True)
        service_file = '%s/%s.service' % (MDNS_SERVICES, db.get('dongle_name'))
        file_name = pathlib.Path(service_file)
        file_name.touch(exist_ok=True)

        with open(str(service_file), 'r') as file_:
            sod = file_.read()

        # Only restart service if something changed
        if snw != sod:
            with open(str(file_name), 'w') as file_:
                file_.write(snw)
            bash('service avahi-daemon reload')
            logging.info('mDNS service updated.')
Пример #18
0
    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)
Пример #19
0
def handle_diag(action):
    '''handle_diag('I') -> Insert the rules
    diagNetfilter('D') -> Delete the rules'''
    if action is 'I':
        logging.info('Redirecting MM port traffic to interior interface.')
    elif action is 'D':
        logging.info('Deleting ip6tables diagnostics rules.')
    else:
        return

    bash(
        'ip6tables -w -t mangle -%s OUTPUT -o lo -d %s -p udp --dport %s -j MARK --set-mark "%s"'
        %
        (action, db.get('dongle_rloc'), DEFS.PORT_MM, db.get('bridging_mark')))
Пример #20
0
def _get_prefix_flags():
    slaac = True if db.get('prefix_slaac') else False
    dhcp = True if db.get('prefix_dhcp') else False
    dp = True if db.get('prefix_dua') else False

    # Force SLAAC if no other flags are set
    if not dp and not dhcp:
        slaac = True

    # DHCP overrides SLAAC
    if dhcp:
        slaac = False

    return slaac, dhcp, dp
Пример #21
0
def dhcp_server_stop():
    # Don't stop if DHCP is not to be used
    if not db.get('prefix_dhcp'):
        return
        
    # Stop DHCP daemon
    bash(DHCP_DAEMON + ' stop')
    # Remove previous configuration for this NCP
    db.del_from_file(DHCP_CONFIG, '\niface %s' % db.get('interior_ifname'), '\n}\n')
    # Allow for the file to be stored
    time.sleep(0.2)

    # Start DHCP daemon
    bash(DHCP_DAEMON + ' start')
Пример #22
0
    def __init__(self):
        # List of PBBR DUAs with finished DAD
        self.duas = {}

        try:
            # Create and init the ICMPv6 socket
            self.icmp6_sock = socket.socket(socket.AF_INET6, socket.SOCK_RAW,
                                            IPPROTO_ICMPV6)

            # Bind to exterior interface only
            self.icmp6_sock.setsockopt(SOL_SOCKET, SO_BINDTODEVICE,
                                       db.get('exterior_ifname').encode())

            # Receive Neighbor Solicitation messages in this socket
            icmp6_filter = bytearray(32)  # 256 bit flags
            icmp6_filter = icmp6_filter_setpass(icmp6_filter,
                                                ND_NEIGHBOR_SOLICIT)
            self.icmp6_sock.setsockopt(IPPROTO_ICMPV6, ICMP6_FILTER,
                                       icmp6_filter)

            # Set the outgoing hop limit
            self.icmp6_sock.setsockopt(IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255)
            self.icmp6_sock.setsockopt(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255)

            # Run the daemon
            self.ndp_on = True
            #asyncio.ensure_future(self.run_daemon())
            asyncio.get_event_loop().run_in_executor(None, self.run_daemon)
        except:
            logging.error('Unable to create the ND Proxy socket.')
Пример #23
0
    def run_daemon(self):
        ext_ifname = db.get('exterior_ifname')
        while self.ndp_on:
            # Wait for some multicast traffic to arrive
            data, src = self.icmp6_sock.recvfrom(1280)
            #print('%s | %d: %s' % (src[0], len(data), data.hex()))

            # Accepting Neighbor solicit only
            if data[0] != ND_NEIGHBOR_SOLICIT:
                continue

            # Get the paramters
            _, _, _, _, tgt = struct.unpack(NS_FMT,
                                            data[:struct.calcsize(NS_FMT)])

            # Debug
            ns_tgt = ipaddress.IPv6Address(tgt).compressed
            logging.info('in ns from %s for %s' % (src[0], ns_tgt))

            # Generate Neighbor Advertisement
            try:
                EXT_IPV6_ADDRS = NETWORK.get_addrs(ext_ifname, socket.AF_INET6)
            except:
                # pyroute2.netlink.exceptions.NetlinkError:
                #  (16, 'Device or resource busy')
                pass
            addrs = list(self.duas.keys()) + EXT_IPV6_ADDRS
            if ns_tgt in addrs:
                self.send_na(src[0], ns_tgt)
Пример #24
0
    def kstart(self):
        logging.info('Configuring Avahi daemon.')
        ip4 = 'yes' if db.has_keys(['exterior_ipv4']) else 'no'
        ip6 = 'yes' if db.has_keys(['exterior_ipv6_ll']) else 'no'
        with open(MDNS_CONFIG, 'w') as file_:
            lines = []
            lines.append('[server]')
            lines.append('use-ipv4=%s' % ip4)
            lines.append('use-ipv6=%s' % ip6)
            lines.append('allow-interfaces=%s' % db.get('exterior_ifname'))
            lines.append('disallow-other-stacks=yes\n')
            lines.append('[publish]')
            lines.append('publish-addresses=yes')
            lines.append('publish-hinfo=no')
            lines.append('publish-workstation=no')
            lines.append('publish-domain=no')
            lines.append('publish-aaaa-on-ipv4=no')
            lines.append('publish-a-on-ipv6=no\n')
            lines.append('[rlimits]')
            lines.append('rlimit-core=0')
            lines.append('rlimit-data=4194304')
            lines.append('rlimit-fsize=0')
            lines.append('rlimit-nofile=30')
            lines.append('rlimit-stack=4194304')
            lines.append('rlimit-nproc=3')
            lines = '\n'.join(lines)
            file_.write(lines)

        # Enable service
        self.service_update()
Пример #25
0
    async def render_post(self, request):
        # Incoming TLVs parsing
        logging.info('in %s ntf: %s' %
                     (URI.B_BMR, ThreadTLV.sub_tlvs_str(request.payload)))

        # Primary BBR shouldn't receive this message
        if not 'secondary' in db.get('bbr_status'):
            return COAP_NO_RESPONSE
        '''
        # IPv6 Addresses TLV
        addrs = []
        value = ThreadTLV.get_value(request.payload, TLV.A_IPV6_ADDRESSES)
        if value:
            _, addrs, _ = Res_N_MR.parse_addrs(value)

        # Timeout TLV
        timeout = ThreadTLV.get_value(request.payload, TLV.A_TIMEOUT)

        # Register valid addresses
        if addrs and timeout:
            MCAST_HNDLR.reg_update(addrs, timeout)
        '''
        # TODO: mantain a Backup Multicast Listeners Table

        return COAP_NO_RESPONSE
Пример #26
0
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()
Пример #27
0
def _get_oobcom(brouter):
    try:
        if brouter.ksh_cmd('show status')[0] != 'joined':
            return None
    except:
        print('%s is busy' % brouter.port.port)
        return None

    oobcom = {}
    settings = brouter.ksh_cmd('show netconfig')
    for line in settings:
        if '| Channel' in line:
            oobcom['channel'] = line.split(':')[-1].strip()
        elif '| PAN ID' in line:
            oobcom['panid'] = line.split(':')[-1].strip()
        elif '| Extended PAN ID' in line:
            oobcom['xpanid'] = ''.join(line.split()[5:9])
        elif '| Network Name' in line:
            oobcom['netname'] = '"%s"' % line.split(':')[1].strip()
        elif '| Mesh-Local ULA' in line:
            oobcom['mlprefix'] = line.split(' : ')[-1].split('/')[0]
        elif '| Active Timestamp' in line:
            oobcom['actstamp'] = line.split(':')[-1].strip()
        elif '| Master Key' in line:
            oobcom['mkey'] = line.split(':')[-1].strip()
    oobcom['commcred'] = '"%s"' % db.get('ncp_commcred')

    return oobcom
Пример #28
0
def clear_topology():
    db.load()
    _, ncps = _get_devices(db.get('ncp_serial'))
    threads = []

    for device in ncps:
        threads.append(Thread(target=_stop_topology, args=[device]))
Пример #29
0
def _handle_ipv4(action):
    '''
    Block most of the exterior traffic
     _handle_ipv4('A')  --> Add the rules
     _handle_ipv4('D')  --> Delete the rules
    '''
    if action == 'A':
        # This should not be needed if KiBRA was closed correctly
        bash('iptables -F -t mangle')

    exterior_ifname = db.get('exterior_ifname')

    bash('iptables -w -t filter -%s INPUT -i %s -p icmp -j ACCEPT' %
         (action, exterior_ifname))
    bash(
        'iptables -w -t filter -%s INPUT -i %s -p udp --dport mdns -j ACCEPT' %
        (action, exterior_ifname))
    bash(
        'iptables -w -t filter -%s INPUT -i %s -p udp --dport dhcpv6-client -j ACCEPT'
        % (action, exterior_ifname))
    bash(
        'iptables -w -t filter -%s INPUT -i %s -m state --state ESTABLISHED,RELATED -j ACCEPT'
        % (action, exterior_ifname))
    bash('iptables -w -t filter -%s INPUT -i %s -j DROP' %
         (action, exterior_ifname))
Пример #30
0
    async def periodic(self):

        MCAST_HNDLR.reg_periodic()

        # Keept track of RLOC changes
        current_ncp_rloc = db.get('ncp_rloc')
        if current_ncp_rloc != self.last_ncp_rloc:
            self._ncp_rloc_changed(self.last_ncp_rloc)
            self.last_ncp_rloc = current_ncp_rloc

        # Keep track of BBR status changes
        current_bbr_status = db.get('bbr_status')
        if current_bbr_status != self.last_bbr_status:
            if current_bbr_status == 'primary':
                self._launch_servers()
            self.last_bbr_status = current_bbr_status