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()
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
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')))
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)
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])
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.')
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)
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')
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())]))