def dhcp_server_start(): # Don't start 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') # Add new configuration with open(DHCP_CONFIG, 'w') as file_: file_.write('\n') file_.write('iface ' + db.get('interior_ifname') + ' {\n') file_.write('\tclient-max-lease 1\n') file_.write('\tunicast ' + db.get('ncp_rloc') + '\n') file_.write('\trapid-commit yes\n') file_.write('\toption ntp-server ' + db.get('ncp_mleid') + '\n') file_.write('\toption dns-server ' + db.get('ncp_mleid') + '\n') file_.write('\tpreference 255\n') file_.write('\tclass {\n') file_.write('\t\tT1 0\n') file_.write('\t\tT2 0\n') file_.write('\t\tpreferred-lifetime 86400\n') file_.write('\t\tvalid-lifetime 86400\n') file_.write('\t\tpool ' + db.get('prefix') + '\n') file_.write('\t}\n') file_.write('}\n') # Allow for the file to be stored time.sleep(0.2) # Start DHCP daemon bash(DHCP_DAEMON + ' start')
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)
def handle_nat64_masking(ext_addr, enable=True): '''Enable or disable one exterior IPv4 address in the NAT64 Pool 4''' global POOL4_ACTIVE # Don't allow IPv6 addresses here try: ipaddress.IPv4Address(ext_addr) except: return jool_action = 'add' if enable else 'remove' log_action = 'used' if enable else 'removed' # Only allow one address in the Pool 4 if (enable and POOL4_ACTIVE) or (not enable and not POOL4_ACTIVE): logging.info('Unable to %s %s as stateful NAT64 masking address.', jool_action, ext_addr) return params = (jool_action, ext_addr) bash('jool pool4 %s %s 61001-65535 --udp' % params) bash('jool pool4 %s %s 61001-65535 --icmp' % params) POOL4_ACTIVE = True logging.info('%s %s as stateful NAT64 masking address.', ext_addr, log_action)
def ncp_fw_update(): ''' Compare the NCP firmware with the one available in the 'ncp_fiwmare' folder and update if needed ''' # Find the DFU file that matches the required fw version dfu_file = None ver_num = kibra.__kinosver__.split(' v')[-1] for file_name in importlib_resources.contents(NCP_FW_FOLDER): if ver_num in file_name: # TODO: This relies on the file name, we could also check the file # contents to make sure dfu_file = file_name break if not dfu_file: logging.error('Required NCP firmware not present.') sys.exit() # Flash the NCP and re-enable it with importlib_resources.path(NCP_FW_FOLDER, dfu_file) as dfu_path: logging.warn('NCP will be updated with firmware v%s' % ver_num) try: dfu_file = kidfu.DfuFile(str(dfu_path)) kifwu.dfu_find_and_flash(dfu_file, unattended=True) # TODO: Remove this when KiTools is fixed for a proper USB re-enumeration # Reset USB device in KTBRN1 bash('sh -c "echo 0 > /sys/bus/usb/devices/6-1/authorized"') bash('sh -c "echo 1 > /sys/bus/usb/devices/6-1/authorized"') except Exception as exc: logging.error('Problem updating NCP firmware: %s' % exc) sys.exit() logging.info('NCP updated successfully.')
def block_local_multicast(action, maddr): src = db.get('exterior_ipv6_ll') if action is 'I': logging.info('Blocking local traffic to %s' % maddr) elif action is 'D': logging.info('Unblocking local traffic to %s' % maddr) else: return bash('%s -%s INPUT -s %s -d %s -j DROP' % (IP6TF, action, src, maddr))
def kstop(self): if self.nat_enabled: # Disnable NAT logging.info('Disabling Border Agent NAT.') self.nat_enabled = False nat_start('D') # Disable service logging.info('Removing Avahi service.') bash('rm /etc/avahi/services/%s.service' % db.get('dongle_name')) bash('service avahi-daemon reload')
def _nat_enable(): global POOL4_ACTIVE _nat_disable() bash('/sbin/modprobe jool') POOL4_ACTIVE = False logging.info('NAT64 engine started.') bash('jool instance add --netfilter --pool6 64:ff9b::/96') logging.info('Prefix 64:ff9b::/96 added to NAT64 engine.')
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.')
def handle_diag(action, ncp_rloc): '''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( '%s -%s OUTPUT -o lo -d %s -p udp --dport %s -j MARK --set-mark "%s"' % (IP6TM, action, ncp_rloc, DEFS.PORT_MM, db.get('bridging_mark')))
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')
def kstop(self): # Don't stop if DHCP is not to be used if not db.get('prefix_dhcp'): return #TODO: https://www.claudiokuenzler.com/blog/694/get-unbount-dns-lookups-resolution-working-ubuntu-16.04-xenial # Stop DNS daemon bash('service %s stop' % DNS_DAEMON) # Remove previous configuration for this dongle db.del_from_file(DNS_CONFIG, '\nserver:', '\n dns64-synthall: yes\n') # Allow for the file to be stored sleep(0.2) # Start DNS daemon bash('service %s start' % DNS_DAEMON)
def kstop(self): # 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 dongle db.del_from_file(DHCP_CONFIG, '\niface %s' % db.get('interior_ifname'), '\n}\n') # Allow for the file to be stored sleep(0.2) # Remove route dongle_route_disable(db.get('prefix')) # Start DHCP daemon bash(DHCP_DAEMON + ' start')
def kstart(self): # Don't start if DHCP is not to be used if not db.get('prefix_dhcp'): return # Stop DNS daemon bash('service %s stop' % DNS_DAEMON) # Remove previous configuration db.del_from_file(DNS_CONFIG, '\nserver:', '\n dns64-synthall: yes\n') # Add new configuration with open(DNS_CONFIG, 'w') as file_: file_.write('\nserver:') file_.write('\n interface: %s' % db.get('dongle_mleid')) file_.write('\n access-control: ::/0 allow') file_.write('\n module-config: "dns64 validator iterator"') file_.write('\n dns64-prefix: 64:ff9b::/96') file_.write('\n dns64-synthall: yes\n') # Allow for the file to be stored sleep(0.2) # Start DNS daemon bash('service %s start' % DNS_DAEMON)
def kstart(self): # Don't start 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 dongle db.del_from_file(DHCP_CONFIG, '\niface %s' % db.get('interior_ifname'), '\n}\n') # Add new configuration with open(DHCP_CONFIG, 'w') as file_: file_.write('\n') file_.write('iface ' + db.get('interior_ifname') + ' {\n') file_.write('\tclient-max-lease 1\n') file_.write('\tunicast ' + db.get('dongle_rloc') + '\n') file_.write('\trapid-commit yes\n') # file_.write('\toption 224 address ' + db.get('dongle_rloc') + '\n') # CoAP RD #file_.write('\toption 56 duid ' + ntp_server_opt(db.get('dongle_rloc')) + '\n') file_.write('\toption ntp-server ' + db.get('dongle_mleid') + '\n') file_.write('\toption dns-server ' + db.get('dongle_mleid') + '\n') file_.write('\tpreference 255\n') file_.write('\tclass {\n') file_.write('\t\tT1 0\n') file_.write('\t\tT2 0\n') file_.write('\t\tpreferred-lifetime 1500\n') file_.write('\t\tvalid-lifetime 1800\n') file_.write('\t\tpool ' + db.get('prefix') + '\n') file_.write('\t}\n') #file_.write('\tclient duid ' + db.get('dongle_mac') + ' {\n') #file_.write('\t\taddress ' + db.get('dhcp_server') + '\n') # file_.write('\t}\n') file_.write('}\n') # Allow for the file to be stored sleep(0.2) # Start DHCP daemon bash(DHCP_DAEMON + ' start')
def handle_bagent_fwd(ext_addr, int_addr, enable=True): '''Enable or disable Border Agent traffic forwarding between one exterior address and the NCP, using Jool for IPv6 and iptables for IPv6''' # Get parameters try: ipaddress.IPv4Address(ext_addr) is_ipv4 = True except: is_ipv4 = False jool_action = 'add' if enable else 'remove' ipt_action = 'I' if enable else 'D' ipt_bin = IPTM if is_ipv4 else IP6TM ext_ifame = db.get('exterior_ifname') ext_port = db.get('exterior_port_mc') int_port = db.get('bagent_port') brdg_mark = db.get('bridging_mark') # NAT 4 -> 6 if is_ipv4: params = (jool_action, ext_addr, ext_port, int_addr, int_port) bash('jool bib %s %s#%s %s#%s --udp' % params) # NAT 6 -> 6 else: params = (IP6TN, ipt_action, ext_ifame, ext_addr, ext_port, int_addr, int_port) bash( '%s -%s PREROUTING -i %s -d %s -p udp --dport %d -j DNAT --to [%s]:%d' % params) # Mark MC packets before they are translated, # so they are not consumed by Linux but by the NCP params = (ipt_bin, ipt_action, ext_ifame, ext_addr, ext_port, brdg_mark) bash( '%s -%s PREROUTING -i %s -d %s -p udp --dport %d -j MARK --set-mark %s' % params) logging.info('Border Agent forwarding updated.')
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') params = (IPTF, action, db.get('exterior_ifname')) bash('%s -%s INPUT -i %s -p icmp -j ACCEPT' % (params)) bash('%s -%s INPUT -i %s -p udp --dport mdns -j ACCEPT' % (params)) bash('%s -%s INPUT -i %s -p udp --dport dhcpv6-client -j ACCEPT' % (params)) bash('%s -%s INPUT -i %s -m state --state ESTABLISHED,RELATED -j ACCEPT' % (params)) bash('%s -%s INPUT -i %s -j DROP' % (params))
def handle_ipv6(action): '''handle_ipv6('A') --> Add the rules handle_ipv6('D') --> Delete the rules''' if action is 'A': logging.info('Adding ip6tables general rules.') # This should not be needed if KiBRA was closed correctly bash('ip6tables -F -t mangle') bash('ip6tables -F -t nat') bash('ip6tables -F -t filter') elif action is 'D': logging.info('Deleting ip6tables general rules.') else: return interior_ifname = db.get('interior_ifname') prefix = db.get('prefix') # INPUT # Disallow incoming multicast ping requests bash( '%s -%s INPUT -i %s -d ff00::/8 -p icmpv6 --icmpv6-type echo-request -j DROP' % (IP6TF, action, db.get('exterior_ifname'))) # OUTPUT # Prevent fragmentation bash('%s -%s OUTPUT -o %s -m length --length 1281:0xffff -j REJECT' % (IP6TF, action, interior_ifname)) # Allow some ICMPv6 traffic towards the Thread interface bash( '%s -%s OUTPUT -o %s -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT' % (IP6TF, action, interior_ifname)) bash('%s -%s OUTPUT -o %s -p icmpv6 --icmpv6-type echo-request -j ACCEPT' % (IP6TF, action, interior_ifname)) # Allow CoAP bash('%s -%s OUTPUT -o %s -p udp --sport %s -j ACCEPT' % (IP6TF, action, interior_ifname, DEFS.PORT_COAP)) bash('%s -%s OUTPUT -o %s -p udp --dport %s -j ACCEPT' % (IP6TF, action, interior_ifname, DEFS.PORT_COAP)) bash('%s -%s OUTPUT -o %s -p udp --sport %s -j ACCEPT' % (IP6TF, action, interior_ifname, DEFS.PORT_MM)) bash('%s -%s OUTPUT -o %s -p udp --dport %s -j ACCEPT' % (IP6TF, action, interior_ifname, DEFS.PORT_MM)) # Allow DHCPv6 server bash('%s -%s OUTPUT -o %s -p udp --dport dhcpv6-client -j ACCEPT' % (IP6TF, action, interior_ifname)) # Allow NTP server bash('%s -%s OUTPUT -o %s -p udp --sport 123 -j ACCEPT' % (IP6TF, action, interior_ifname)) # Allow DNS server bash('%s -%s OUTPUT -o %s -p udp --sport 53 -j ACCEPT' % (IP6TF, action, interior_ifname)) # Block all other outgoing traffic to the Thread interface bash('%s -%s OUTPUT -o %s -j DROP' % (IP6TF, action, interior_ifname)) # Block Thread traffic on the Ethernet interface if not db.get('prefix_dua'): bash('%s -%s OUTPUT -o %s -p ipv6 -d %s -j DROP' % (IP6TF, action, db.get('exterior_ifname'), prefix)) # FORWARD # Prevent fragmentation bash('%s -%s FORWARD -o %s -m length --length 1281:0xffff -j REJECT' % (IP6TF, action, interior_ifname)) # Forward marked packets for PBR bash('%s -%s FORWARD -m mark --mark "%s" -j ACCEPT' % (IP6TF, action, db.get('bridging_mark'))) # Reflective session state (9.2.7_13) bash('%s -%s FORWARD -p udp -m state --state ESTABLISHED -j ACCEPT' % (IP6TF, action)) bash( '%s -%s FORWARD -p icmpv6 -m state --state ESTABLISHED,RELATED -j ACCEPT' % (IP6TF, action)) # Forward all multicast (filtering is made by mcrouter) bash('%s -%s FORWARD -d ff00::/8 -j ACCEPT' % (IP6TF, action)) # Forward announced prefix bash('%s -%s FORWARD -d %s -j ACCEPT' % (IP6TF, action, prefix)) bash('%s -%s FORWARD -s %s -j ACCEPT' % (IP6TF, action, prefix)) # Block all other forwarding bash('%s -%s FORWARD -j DROP' % (IP6TF, action))
def kstop(self): # Disable service logging.info('Removing Avahi service.') bash('rm /etc/avahi/services/%s.service' % db.get('ncp_name')) bash('service avahi-daemon restart')
def _nat_disable(): bash('/sbin/modprobe -r jool') logging.info('NAT64 engine stopped.')
def _ifup(): # Make sure forwarding is enabled bash('echo 1 > /proc/sys/net/ipv4/conf/all/forwarding') bash('echo 1 > /proc/sys/net/ipv6/conf/all/forwarding') logging.info('Forwarding has been enabled.') # Disable duplicate address detection for the interior interface bash('echo 0 > /proc/sys/net/ipv6/conf/%s/accept_dad' % db.get('interior_ifname')) logging.info('DAD has been disabled for %s.', db.get('interior_ifname')) # Enable a bigger number of multicast groups # https://www.kernel.org/doc/Documentation/sysctl/net.txt bash('echo 65536 > /proc/sys/net/core/optmem_max') # Bring interior interface up idx = db.get('interior_ifnumber') # First bring it down to remove old invalid addresses IPR.link('set', index=idx, state='down') IPR.link('set', index=idx, state='up', txqlen=5000) # Add inside IPv6 addresses logging.info('Configuring interior interface %s with address %s.', db.get('interior_ifname'), db.get('dongle_rloc')) IPR.addr('add', index=idx, address=db.get('dongle_rloc'), prefixlen=64) logging.info('Configuring interior interface %s with address %s.', db.get('interior_ifname'), db.get('dongle_mleid')) IPR.addr('add', index=idx, address=db.get('dongle_mleid'), prefixlen=64) # Add dongle neighbour IPR.neigh('replace', family=AF_INET6, dst=db.get('dongle_ll'), lladdr=db.get('dongle_mac'), ifindex=idx, nud='permanent') IPR.neigh('replace', family=AF_INET6, dst=db.get('dongle_rloc'), lladdr=db.get('dongle_mac'), ifindex=idx, nud='permanent') IPR.neigh('replace', family=AF_INET6, dst=db.get('dongle_mleid'), lladdr=db.get('dongle_mac'), ifindex=idx, nud='permanent') # Add custom routing table rt_tables = _get_rt_tables() if not db.get('bridging_table') in rt_tables: _rt_add_table(db.get('bridging_table'), BR_TABLE_NR) # Add default route to custom table IPR.route('replace', family=AF_INET6, dst='default', table=BR_TABLE_NR, oif=idx) rules = IPR.get_rules(family=AF_INET6) # Make marked packets use the custom table # TODO: different priorities for different dongles if str(db.get('bridging_mark')) not in str(rules): IPR.rule('add', family=AF_INET6, table=BR_TABLE_NR, priority=100, fwmark=int(db.get('bridging_mark'))) # Set priority of local table lower than custom table's for rule in rules: if rule.get('table') == rt_tables.get('local'): IPR.rule('delete', family=AF_INET6, table=rule.get('table'), priority=rule.get_attr('FRA_PRIORITY') or 0) IPR.rule('add', family=AF_INET6, table=rt_tables.get('local'), priority=1000) '''
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')))
def netmap(old_dst, new_dst): logging.info('Redirecting traffic from %s to %s.' % (old_dst, new_dst)) # TODO: make this work properly bash('ip6tables -t nat -A PREROUTING -i %s -d %s -j NETMAP --to %s' % (db.get('interior_ifname'), old_dst, new_dst))
def new_external_addresses(): '''Be notified about new addresses in the external interface''' # Restart Avahi to make it use the new addresses logging.info('Restarting Avahi service.') bash('service avahi-daemon restart')
def do_GET(self): binary = False if self.path == '/': self.path = '/index.html' file_path = '%s%s' % (PUBLIC_DIR, self.path.replace('/assets', '')) mime_type = 'text/json' try: # Parse URL fields req = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query) # Different actions data = 'OK' if self.path == '/logs': # TODO: fancy colourfull autorefresh logs page with open(db.LOG_FILE, 'r') as file_: data = file_.read() mime_type = 'text/plain' elif self.path == '/db/cfg': data = db.dump() elif self.path == '/db/nodes': data = json.dumps(DIAGS_DB, indent=2) elif self.path == '/db/leases': data = json.dumps(_get_leases(), indent=2) elif os.path.isfile(file_path): if self.path.endswith(".html"): mime_type = 'text/html' if self.path.endswith(".png"): mime_type = 'image/png' binary = True if self.path.endswith(".js"): mime_type = 'application/javascript' if self.path.endswith(".css"): mime_type = 'text/css' with open(file_path, 'rb' if binary else 'r') as file_: data = file_.read() elif kibra.__harness__ and self.path.startswith('/api'): for key in req.keys(): if not key in db.modifiable_keys(): self.send_response(http.HTTPStatus.BAD_REQUEST) return # Apply incoming changes modif_keys = set() for key, value in req.items(): if str(db.get(key)) != value[0]: db.set(key, value[0]) modif_keys.add(key) # Special actions if not set(['mlr_timeout', 'rereg_delay' ]).isdisjoint(modif_keys): bbr_dataset_update() elif kibra.__harness__ and self.path.startswith('/ksh'): cmd = req.get('c', None) if cmd: data = '\n'.join(send_cmd(cmd[0])) else: return elif kibra.__harness__ and self.path.startswith('/ping'): dst = req.get('dst', ['0100::'])[0] size = req.get('sz', ['0'])[0] hl = req.get('hl', ['255'])[0] iface = db.get('exterior_ifname') port = req.get('port', [''])[0] tout = req.get('tout', ['0'])[0] if port: # UDP cmd = 'nping -6 --udp' cmd += ' --source-port %s --dest-port %s' % (port, port) cmd += ' --no-capture --count 1' cmd += ' --interface %s' % iface cmd += ' --dest-ip %s' % dst cmd += ' --source-mac %s' % db.get('exterior_mac') # TODO: https://en.wikipedia.org/wiki/Multicast_address#Ethernet cmd += ' --dest-mac ff:ff:ff:ff:ff:ff' cmd += ' --hop-limit %s' % hl # TODO: use DUA as source cmd += ' --source-ip %s' % db.get('exterior_ipv6_ll') cmd += ' --data-length %s' % size else: # ICMP cmd = 'ping -6 -c1' cmd += ' -W%s -s%s -t%s -I%s %s' % (tout, size, hl, iface, dst) try: data = bash(cmd) except Exception as e: logging.error(e) data = 'ping error' elif kibra.__harness__ and self.path.startswith('/radvd'): off = req.get('off') backhaul = req.get('bh') domain = req.get('dm') if off: bash('service radvd stop') elif backhaul and domain: if not db.get('exterior_ifname'): NETWORK.set_ext_iface() with open('/etc/radvd.conf', 'w') as file_: file_.write('interface %s {\n' % db.get('exterior_ifname')) file_.write(' AdvSendAdvert on;\n') file_.write(' prefix %s { AdvAutonomous on; };\n' % backhaul[0]) file_.write(' prefix %s { AdvAutonomous off; };\n' % domain[0]) file_.write('};\n') bash('echo 1 > /proc/sys/net/ipv6/conf/all/forwarding') bash('ip -6 neighbor flush all') bash('service radvd restart') else: return elif kibra.__harness__ and self.path.startswith('/mdnsqry'): bash('dig -p 5353 @ff02::fb _meshcop._udp.local ptr') elif kibra.__harness__ and self.path.startswith('/duastatus'): db.set('dua_next_status', req.get('sta')[0]) db.set('dua_next_status_eid', req.get('eid')[0]) elif kibra.__harness__ and self.path.startswith('/mlrstatus'): db.set('mlr_next_status', req.get('sta')[0]) elif kibra.__harness__ and self.path.startswith('/sendudp'): NETWORK.send_udp( req.get('dst')[0], req.get('prt')[0], req.get('pld')[0]) elif kibra.__harness__ and self.path.startswith('/ipneigh'): bash(req.get('cmd')) else: self.send_response(http.HTTPStatus.NOT_FOUND) return except: self.send_response(http.HTTPStatus.INTERNAL_SERVER_ERROR) return self.send_response(http.HTTPStatus.OK) self.send_header('Access-Control-Allow-Origin', '*') self.send_header('Content-type', mime_type) self.end_headers() if not binary: data = data.encode() self.wfile.write(data)
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 _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'))
def _ifup(): # For the Thread Harness, remove old neighbors if kibra.__harness__: bash('ip -6 neigh flush all') ifname = db.get('interior_ifname') # Make sure forwarding is enabled bash('echo 1 > /proc/sys/net/ipv4/conf/all/forwarding') bash('echo 1 > /proc/sys/net/ipv6/conf/all/forwarding') logging.info('Forwarding has been enabled.') # Disable duplicate address detection for the interior interface bash('echo 0 > /proc/sys/net/ipv6/conf/%s/accept_dad' % ifname) logging.info('DAD has been disabled for %s.', ifname) # Enable a bigger number of multicast groups # https://www.kernel.org/doc/Documentation/sysctl/net.txt bash('echo 65536 > /proc/sys/net/core/optmem_max') # Bring interior interface up idx = db.get('interior_ifnumber') # First bring it down to remove old invalid addresses IPR.link('set', index=idx, state='down') IPR.link('set', index=idx, state='up', txqlen=5000) # Add custom routing table rt_tables = _get_rt_tables() if not db.get('bridging_table') in rt_tables: _rt_add_table(db.get('bridging_table'), BR_TABLE_NR) # Add default route to custom table IPR.route('replace', family=socket.AF_INET6, dst='default', table=BR_TABLE_NR, oif=idx) rules = IPR.get_rules(family=socket.AF_INET6) # Make marked packets use the custom table # TODO: different priorities for different NCPs if str(db.get('bridging_mark')) not in str(rules): IPR.rule( 'add', family=socket.AF_INET6, table=BR_TABLE_NR, priority=100, fwmark=int(db.get('bridging_mark')), ) # Set priority of local table lower than custom table's for rule in rules: if rule.get('table') == rt_tables.get('local'): IPR.rule( 'delete', family=socket.AF_INET6, table=rule.get('table'), priority=rule.get_attr('FRA_PRIORITY') or 0, ) IPR.rule('add', family=socket.AF_INET6, table=rt_tables.get('local'), priority=1000) # Rate limit traffic to the interface, 125 kbps (maximum data rate in the # air) logging.info('Traffic rate limit established to %s on interface %s.', '125 kbps', ifname) bash('tc qdisc add dev %s root handle 1: cbq avpkt 1000 bandwidth 12mbit' % ifname) bash( 'tc class add dev %s parent 1: classid 1:1 cbq rate 125kbit allot 1500 prio 5 bounded isolated' % ifname) bash( 'tc filter add dev %s parent 1: protocol ipv6 prio 16 u32 match ip6 dst ::/0 flowid 1:1' % ifname)