summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2023-05-20 21:42:08 +0200
committerBen Hutchings <ben@decadent.org.uk>2023-05-21 21:51:00 +0200
commitb70cb5ddaeadc887c9645f61441b701392f10758 (patch)
tree4d1f0c7f410601bc6fb7be98515a81d93b81f522
parent81c93ed662cd8b3f38871bc002582f5abee9b99f (diff)
downloadklibc-maint-b70cb5ddaeadc887c9645f61441b701392f10758.tar.gz
Add script for testing ipconfigHEADmaster
-rwxr-xr-xtest-ipconfig120
1 files changed, 120 insertions, 0 deletions
diff --git a/test-ipconfig b/test-ipconfig
new file mode 100755
index 0000000..378c269
--- /dev/null
+++ b/test-ipconfig
@@ -0,0 +1,120 @@
+#!/usr/bin/python3
+
+import argparse
+import ipaddress
+import json
+import subprocess
+import sys
+import tempfile
+
+
+class NetNamespace:
+ def __init__(self, name):
+ self._name = name
+
+ def __enter__(self):
+ subprocess.check_call(['ip', 'netns', 'add', self._name])
+
+ def __exit__(self, *_):
+ subprocess.run(['ip', 'netns', 'del', self._name])
+
+
+class VethNetwork:
+ def __init__(self, ipv4_network, ipv6_network, local_iface,
+ other_ns, other_iface):
+ self._ip_networks = [ipv4_network, ipv6_network]
+ self._local_iface = local_iface
+ self._other_ns = other_ns
+ self._other_iface = other_iface
+
+ def __enter__(self):
+ subprocess.check_call(
+ ['ip', 'link', 'add', self._local_iface, 'type', 'veth',
+ 'peer', 'name', self._other_iface])
+ try:
+ subprocess.check_call(
+ ['ip', 'link', 'set', self._local_iface, 'up'])
+ for ip_network in self._ip_networks:
+ subprocess.check_call(
+ ['ip', 'addr', 'add', 'dev', self._local_iface,
+ f'{ ip_network[1] }/{ ip_network.prefixlen }'])
+ subprocess.check_call(
+ ['ip', 'link', 'set', self._other_iface,
+ 'netns', self._other_ns])
+ except:
+ subprocess.run(['ip', 'link', 'del', self._local_iface])
+ raise
+
+ def __exit__(self, *_):
+ subprocess.run(['ip', 'link', 'del', self._local_iface])
+
+
+class DnsmasqRunning:
+ def __init__(self, ipv4_network, ipv6_network, iface):
+ self._iface = iface
+ self._ipv4_network = ipv4_network
+ self._ipv6_network = ipv6_network
+ assert self._ipv6_network.prefixlen == 64 # for SLAAC
+
+ def __enter__(self):
+ config = tempfile.NamedTemporaryFile(mode='w')
+ try:
+ config_text = f'''\
+interface={ self._iface }
+bind-interfaces
+enable-ra
+dhcp-range={ self._ipv4_network[2] },{ self._ipv4_network[-2] }
+synth-domain=dhcp.example.com,{ self._ipv4_network[0] }/{ self._ipv4_network.prefixlen }
+dhcp-option=option6:nis-domain,nisexample
+dhcp-option=option6:domain-search,a.example.com,b.example.com
+dhcp-option=option6:bootfile-url,tftp://boot.example.com/example
+dhcp-range={ self._ipv6_network[2] },{ self._ipv6_network[-2] },slaac,64
+synth-domain=dhcpv6.example.com,{ self._ipv6_network[0] }/{ self._ipv6_network.prefixlen }
+'''
+ print('dnsmasq config:')
+ print(config_text)
+ config.write(config_text)
+ config.flush()
+
+ self._dnsmasq_proc = subprocess.Popen(
+ ['dnsmasq', '-d', '-C', config.name, '--bootp-dynamic'],
+ stderr=sys.stderr)
+ self._config_file = config
+ except:
+ config.close()
+ raise
+
+ def __exit__(self, *_):
+ self._dnsmasq_proc.terminate()
+ self._dnsmasq_proc.wait()
+ self._config_file.close()
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('command', nargs='+')
+ parser.add_argument('--ipv4-network', default='192.168.234.0/24')
+ parser.add_argument('--ipv6-network', default='fc00:c001:d00d:cafe::/64')
+ parser.add_argument('--server-iface', default='veth-dnsmasq')
+ parser.add_argument('--net-namespace', default='test-ipconfig')
+ parser.add_argument('--client-iface', default='veth-ipconfig')
+ args = parser.parse_args()
+
+ ipv4_network = ipaddress.IPv4Network(args.ipv4_network)
+ ipv6_network = ipaddress.IPv6Network(args.ipv6_network)
+ with NetNamespace(args.net_namespace), \
+ VethNetwork(ipv4_network, ipv6_network, args.server_iface,
+ args.net_namespace, args.client_iface), \
+ DnsmasqRunning(ipv4_network, ipv6_network, args.server_iface):
+ subprocess.check_call(
+ ['ip', 'netns', 'exec', args.net_namespace] + args.command)
+ net_conf_name = f'/run/net-{ args.client_iface }.conf'
+ print(f'{net_conf_name}:')
+ subprocess.run(['cat', net_conf_name])
+ print(f'ip addr:')
+ subprocess.check_call(
+ ['ip', 'netns', 'exec', args.net_namespace, 'ip', 'addr'])
+
+
+if __name__ == '__main__':
+ main()