Esempio n. 1
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()
Esempio n. 2
0
 async def periodic(self):
     # Launch NAT64 whenever the BBR is connected to an IPv4 network
     if not self.nat_enabled and db.has_keys(['exterior_ipv4']):
         _nat_enable()
         self.nat_enabled = True
     # Stop NAT64 whenever the BBR is disconnected from an IPv4 network
     elif self.nat_enabled and not db.has_keys(['exterior_ipv4']):
         _nat_disable()
         self.nat_enabled = False
Esempio n. 3
0
def nat_start(action):
    '''
    natMdnsStart I -> Insert the rules
    natMdnsStart D -> Delete the rules
    '''
    # NAT 4 -> 6
    if db.has_keys(['exterior_ipv4']):
        if action == 'I':
            bash('jool bib add %s#%s %s#%s --udp' %
                 (db.get('exterior_ipv4'), str(db.get('exterior_port_mc')),
                  db.get('dongle_rloc'), str(db.get('bagent_port'))))
        else:
            bash('jool bib remove %s#%s %s#%s --udp' %
                 (db.get('exterior_ipv4'), str(db.get('exterior_port_mc')),
                  db.get('dongle_rloc'), str(db.get('bagent_port'))))
        # Mark MC packets before they are translated, so they are not consumed by Linux but by the dongle
        # Flush old rules first
        bash('iptables -F -t mangle')
        bash(
            'iptables -w -t mangle -%s PREROUTING -i %s -d %s -p udp --dport %d -j MARK --set-mark %s'
            % (action, db.get('exterior_ifname'), db.get('exterior_ipv4'),
               db.get('exterior_port_mc'), db.get('bridging_mark')))
    # NAT 6 -> 6
    if db.has_keys(['exterior_ipv6_ll']):
        bash(
            'ip6tables -w -t nat -%s PREROUTING -i %s -d %s -p udp --dport %d -j DNAT --to [%s]:%d'
            % (action, db.get('exterior_ifname'), db.get('exterior_ipv6_ll'),
               db.get('exterior_port_mc'), db.get('dongle_rloc'),
               db.get('bagent_port')))
        bash(
            'ip6tables -w -t nat -%s POSTROUTING -o %s -s %s -p udp --sport %d -j SNAT --to [%s]:%d'
            % (action, db.get('exterior_ifname'), db.get('dongle_rloc'),
               db.get('bagent_port'), db.get('exterior_ipv6_ll'),
               db.get('exterior_port_mc')))
        bash(
            'ip6tables -w -t mangle -%s PREROUTING -i %s -d %s -p udp --dport %d -j MARK --set-mark %s'
            % (action, db.get('exterior_ifname'), db.get('exterior_ipv6_ll'),
               db.get('exterior_port_mc'), db.get('bridging_mark')))
Esempio n. 4
0
    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)
Esempio n. 5
0
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])
Esempio n. 6
0
def _dongle_get_config():
    db.set('dongle_role', send_cmd('show role')[0])
    db.set('dongle_status', send_cmd('show status')[0])
    db.set('dongle_heui64', send_cmd('show heui64')[0])

    # Get mesh rloc and link local addresses
    all_addrs = send_cmd('show ipaddr')

    # Remove not registered addresses
    addrs = []
    for line in all_addrs:
        try:
            state, addr = line.split(' ')
            if state == '[R]':
                addrs.append(addr)
        except:
            # Old versions don't include registration information
            addrs.append(line)

    for ip6_addr in addrs:
        if ip6_addr.startswith('ff'):
            # KiNOS registers multicast addresses with MLR.req
            continue
        elif ip6_addr.startswith('fe80'):
            db.set('dongle_ll', ip6_addr.strip('\r\n'))
            logging.info('Link local address is %s.', db.get('dongle_ll'))
        else:
            if 'ff:fe' in ip6_addr:
                db.set('dongle_rloc', ip6_addr.strip('\r\n'))
                logging.info('RLOC address is %s.', db.get('dongle_rloc'))
            else:
                # TODO: check prefix
                db.set('dongle_mleid', ip6_addr.strip('\r\n'))
                logging.info('EID address is %s.', db.get('dongle_mleid'))
    if not db.has_keys(['dongle_rloc']):
        raise Exception('Error: Mesh RLOC not found.')
Esempio n. 7
0
    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)
Esempio n. 8
0
def _nat_disable():
    if db.has_keys(['exterior_ipv4']):
        bash('jool pool4 remove --udp %s' %
             db.get('exterior_ipv4'))
        bash('jool pool4 remove --icmp %s' % db.get('exterior_ipv4'))
    bash('/sbin/modprobe -r jool')
Esempio n. 9
0
    def kstart(self):
        global DUA_HNDLR
        global MCAST_HNDLR
        logging.info('Starting DUA handler')
        DUA_HNDLR = DUAHandler()
        logging.info('Starting Multicast handler')
        MCAST_HNDLR = MulticastHandler()

        # Set All Network BBRs multicast address as per 9.4.8.1
        all_network_bbrs = NETWORK.get_prefix_based_mcast(
            db.get('dongle_prefix'), 3)
        db.set('all_network_bbrs', all_network_bbrs)
        logging.info('Joining All Network BBRs group: %s' % all_network_bbrs)
        MCAST_HNDLR.mcrouter.join_leave_group('join', all_network_bbrs)
        # TODO: update it if dongle_prefix changes

        if db.get('prefix_dua'):
            # Set All Domain BBRs multicast address as per 9.4.8.1
            all_domain_bbrs = NETWORK.get_prefix_based_mcast(db.get('prefix'), 3)
            db.set('all_domain_bbrs', all_domain_bbrs)
            logging.info('Joining All Domain BBRs group: %s' % all_domain_bbrs)
            MCAST_HNDLR.mcrouter.join_leave_group('join', all_domain_bbrs)
            # TODO: enable radvd

            # Listen for CoAP in Realm-Local All-Routers multicast address
            logging.info('Joining Realm-Local All-Routers group: ff03::2')
            MCAST_HNDLR.mcrouter.join_leave_group('join', 'ff03::2',
                                                  db.get('interior_ifnumber'))

        # Thread side server
        self.coap_servers = []

        logging.info('Launching CoAP Servers in MM port')
        # TODO: bind to RLOC, LL, Realm-Local All-Routers
        '''
        # Bind to RLOC
        self.coap_servers.append(
            CoapServer(
                addr=db.get('dongle_rloc'),
                port=DEFS.PORT_MM,
                resources=[(URI.tuple(URI.N_DR), Res_N_DR()),
                           (URI.tuple(URI.N_MR), Res_N_MR()),
                           (URI.tuple(URI.A_AQ), Res_A_AQ()),
                           (URI.tuple(URI.A_AE), Res_A_AE())]))
        # Bind to LL
        self.coap_servers.append(
            CoapServer(
                addr=db.get('dongle_ll'),
                port=DEFS.PORT_MM,
                resources=[(URI.tuple(URI.N_DR), Res_N_DR()),
                           (URI.tuple(URI.N_MR), Res_N_MR()),
                           (URI.tuple(URI.A_AQ), Res_A_AQ()),
                           (URI.tuple(URI.A_AE), Res_A_AE())]))
        '''
        self.coap_servers.append(
            CoapServer(
                addr='::',
                port=DEFS.PORT_MM,
                resources=[(URI.tuple(URI.N_DR), Res_N_DR()),
                           (URI.tuple(URI.N_MR), Res_N_MR()),
                           (URI.tuple(URI.A_AQ), Res_A_AQ()),
                           (URI.tuple(URI.A_AE), Res_A_AE())]))

        logging.info('Launching CoAP Servers in MC port')
        # Bind to RLOC
        self.coap_servers.append(
            CoapServer(
                addr=db.get('dongle_rloc'),
                port=DEFS.PORT_MC,
                resources=[(URI.tuple(URI.N_MR), Res_N_MR())]))
        # Bind to LL
        self.coap_servers.append(
            CoapServer(
                addr=db.get('dongle_ll'),
                port=DEFS.PORT_MC,
                resources=[(URI.tuple(URI.N_MR), Res_N_MR())]))
        # Bind to exterior LL
        if db.has_keys(['exterior_ipv6_ll']):
            self.coap_servers.append(
                CoapServer(
                    addr=db.get('exterior_ipv6_ll'),
                    port=DEFS.PORT_MC,
                    resources=[(URI.tuple(URI.N_MR), Res_N_MR())]))
        # Bind to exterior IPv4
        if db.has_keys(['exterior_ipv4']):
            self.coap_servers.append(
                CoapServer(
                    addr=db.get('exterior_ipv4'),
                    port=DEFS.PORT_MC,
                    resources=[(URI.tuple(URI.N_MR), Res_N_MR())]))

        logging.info('Launching CoAP Servers in BB port')
        '''
        # Bind Res_B_BMR to all_network_bbrs
        self.coap_servers.append(
            CoapServer(
                addr=db.get('all_network_bbrs'),
                port=db.get('bbr_port'),
                resources=[(URI.tuple(URI.B_BMR), Res_B_BMR())]))
        # Bind Res_B_BQ to all_domain_bbrs
        self.coap_servers.append(
            CoapServer(
                addr='%s%%%s' % (db.get('all_domain_bbrs'),
                                 db.get('exterior_ifname')),
                port=db.get('bbr_port'),
                resources=[(URI.tuple(URI.B_BQ), Res_B_BQ())]))
        # Bind Res_B_BA to exterior link-local
        self.coap_servers.append(
            CoapServer(
                addr=db.get('exterior_ipv6_ll'),
                port=db.get('bbr_port'),
                resources=[(URI.tuple(URI.B_BA), Res_B_BA())]))
        '''
        self.coap_servers.append(
            CoapServer(
                # TODO: bind Res_B_BMR to all_network_bbrs
                # TODO: bind Res_B_BQ to all_domain_bbrs
                # TODO: bind Res_B_BA to exterior link-local
                addr='::',
                port=db.get('bbr_port'),
                resources=[(URI.tuple(URI.B_BMR), Res_B_BMR()),
                           (URI.tuple(URI.B_BQ), Res_B_BQ()),
                           (URI.tuple(URI.B_BA), Res_B_BA())]))