From 6a6e4694968ea2385ade9dcfdb5d87dc2ef118a7 Mon Sep 17 00:00:00 2001 From: fassl Date: Sat, 11 Sep 2021 14:31:35 +0200 Subject: [PATCH] add --ipv6-random flag: #259 Signed-off-by: fassl --- Makefile.am | 2 +- main.c | 49 ++++++++++++----------- tests/test-slirp4netns-cidr6.sh | 69 +++++++++++++++++++++++++++++++++ tests/test-slirp4netns-ipv6.sh | 12 ++++-- 4 files changed, 102 insertions(+), 30 deletions(-) create mode 100755 tests/test-slirp4netns-cidr6.sh diff --git a/Makefile.am b/Makefile.am index eb95e5e..84554bb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ AM_CFLAGS = @GLIB_CFLAGS@ @SLIRP_CFLAGS@ @LIBCAP_CFLAGS@ @LIBSECCOMP_CFLAGS@ noinst_LIBRARIES = libparson.a AM_TESTS_ENVIRONMENT = PATH="$(abs_top_builddir):$(PATH)" -TESTS = tests/test-slirp4netns.sh tests/test-slirp4netns-configure.sh tests/test-slirp4netns-exit-fd.sh tests/test-slirp4netns-ready-fd.sh tests/test-slirp4netns-api-socket.sh tests/test-slirp4netns-disable-host-loopback.sh tests/test-slirp4netns-cidr.sh tests/test-slirp4netns-outbound-addr.sh tests/test-slirp4netns-disable-dns.sh tests/test-slirp4netns-seccomp.sh tests/test-slirp4netns-macaddress.sh tests/test-slirp4netns-ipv6.sh tests/test-slirp4netns-hostfwd4.sh tests/test-slirp4netns-hostfwd6.sh tests/test-slirp4netns-hostfwd.sh +TESTS = tests/test-slirp4netns.sh tests/test-slirp4netns-configure.sh tests/test-slirp4netns-exit-fd.sh tests/test-slirp4netns-ready-fd.sh tests/test-slirp4netns-api-socket.sh tests/test-slirp4netns-disable-host-loopback.sh tests/test-slirp4netns-cidr.sh tests/test-slirp4netns-cidr6.sh tests/test-slirp4netns-outbound-addr.sh tests/test-slirp4netns-disable-dns.sh tests/test-slirp4netns-seccomp.sh tests/test-slirp4netns-macaddress.sh tests/test-slirp4netns-ipv6.sh tests/test-slirp4netns-hostfwd4.sh tests/test-slirp4netns-hostfwd6.sh tests/test-slirp4netns-hostfwd.sh EXTRA_DIST = \ slirp4netns.1.md \ diff --git a/main.c b/main.c index c7cc343..ae09444 100644 --- a/main.c +++ b/main.c @@ -43,7 +43,7 @@ // + 100 . #define NETWORK_PREFIX_MAX (25) #define NETWORK_PREFIX_MIN6 (8) -#define NETWORK_PREFIX_MAX6 (64) +#define NETWORK_PREFIX_MAX6 (128) static int nsenter(pid_t target_pid, char *netns, char *userns, bool only_userns) @@ -241,7 +241,6 @@ static const char *pseudo_random_global_id(const char *device) ifr.ifr_flags = IFF_UP | IFF_RUNNING; if (device == NULL) { - /* TODO: which device should we get the mac address from? */ device = "lo"; } strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1); @@ -312,7 +311,7 @@ static const char *pseudo_random_global_id(const char *device) * ID to create a Local IPv6 address prefix. */ - sprintf(id, "fd00:%s::", tmp); + sprintf(id, "fd00:%s::/64", tmp); return id; } @@ -591,6 +590,7 @@ struct options { bool do_config_network; // -c bool disable_host_loopback; // --disable-host-loopback bool enable_ipv6; // -6 + bool ipv6_random; // --ipv6-random bool enable_sandbox; // --enable-sandbox bool enable_seccomp; // --enable-seccomp bool disable_dns; // --disable-dns @@ -663,8 +663,9 @@ static void parse_args(int argc, char *const argv[], struct options *options) char *optarg_outbound_addr = NULL; char *optarg_outbound_addr6 = NULL; char *optarg_macaddress = NULL; -#define CIDR -41 -#define CIDR6 -42 +#define CIDR -40 +#define CIDR6 -41 +#define IPV6_RANDOM -42 #define DISABLE_HOST_LOOPBACK -43 #define NETNS_TYPE -44 #define USERNS_PATH -45 @@ -691,6 +692,7 @@ static void parse_args(int argc, char *const argv[], struct options *options) { "userns-path", required_argument, NULL, USERNS_PATH }, { "api-socket", required_argument, NULL, 'a' }, { "enable-ipv6", no_argument, NULL, '6' }, + { "ipv6-random", no_argument, NULL, IPV6_RANDOM }, { "enable-sandbox", no_argument, NULL, ENABLE_SANDBOX }, { "create-sandbox", no_argument, NULL, _DEPRECATED_CREATE_SANDBOX }, { "enable-seccomp", no_argument, NULL, ENABLE_SECCOMP }, @@ -783,6 +785,9 @@ static void parse_args(int argc, char *const argv[], struct options *options) options->enable_ipv6 = true; printf("WARNING: Support for IPv6 is experimental\n"); break; + case IPV6_RANDOM: + options->ipv6_random = true; + break; case 'h': usage(argv[0]); exit(EXIT_SUCCESS); @@ -982,29 +987,12 @@ static int parse_cidr6(struct in6_addr *network, struct in6_addr *netmask, fprintf(stderr, "invalid CIDR: %s\n", cidr); goto finish; } - rc = from_regmatch(snetwork_end, sizeof(snetwork_end), matches[2], cidr); - if (rc < 0) { - fprintf(stderr, "invalid CIDR: %s\n", cidr); - goto finish; - } rc = from_regmatch(sprefix, sizeof(sprefix), matches[4], cidr); if (rc < 0) { fprintf(stderr, "invalid CIDR: %s\n", cidr); goto finish; } - if (strcmp(snetwork, snetwork_end) == 0) { - random = pseudo_random_global_id(NULL); - if (random == NULL) { - fprintf(stderr, "cannot create pseudo random global id\n"); - rc = -1; - goto finish; - } - strcpy(snetwork, random); - strcat(snetwork, "0"); - } else { - strcat(snetwork, ":0"); - } - + strcat(snetwork, ":"); if (inet_pton(AF_INET6, snetwork, network) != 1) { fprintf(stderr, "invalid network address: %s\n", snetwork); rc = -1; @@ -1179,8 +1167,19 @@ static int slirp4netns_config_from_options(struct slirp4netns_config *cfg, cfg->enable_seccomp = opt->enable_seccomp; if (cfg->enable_ipv6) { - rc = slirp4netns_config_from_cidr6(cfg, opt->cidr6 == NULL ? DEFAULT_CIDR6 : - opt->cidr6); + const char *cidr = opt->cidr6; + if (cidr == NULL) { + cidr = DEFAULT_CIDR6; + if (opt->ipv6_random) { + cidr = pseudo_random_global_id("lo"); + if (cidr == NULL) { + fprintf(stderr, "cannot create pseudo random global id\n"); + rc = -1; + goto finish; + } + } + } + rc = slirp4netns_config_from_cidr6(cfg, cidr); if (rc < 0) { goto finish; } diff --git a/tests/test-slirp4netns-cidr6.sh b/tests/test-slirp4netns-cidr6.sh new file mode 100755 index 0000000..0cd99c0 --- /dev/null +++ b/tests/test-slirp4netns-cidr6.sh @@ -0,0 +1,69 @@ +#!/bin/bash +set -xeuo pipefail + +. $(dirname $0)/common.sh + +unshare -r -n sleep infinity & +child=$! + +wait_for_network_namespace $child + +set +e +result=$(slirp4netns -c --enable-ipv6 --cidr6 64 $child tun11 2>&1) +set -e +echo $result | grep "invalid CIDR" + +set +e +result=$(slirp4netns -c --enable-ipv6 --cidr6 foo $child tun11 2>&1) +set -e +echo $result | grep "invalid CIDR" + +set +e +result=$(slirp4netns -c --enable-ipv6 --cidr6 fd00::2 $child tun11 2>&1) +set -e +echo $result | grep "invalid CIDR" + +set +e +result=$(slirp4netns -c --enable-ipv6 --cidr6 fd00::/129 $child tun11 2>&1) +set -e +echo $result | grep "prefix length needs to be 8-128" + +cidr=fd00:a1e1:1724:1a +slirp4netns -c $child --enable-ipv6 --cidr6 $cidr::/64 tun11 & +slirp_pid=$! + +wait_for_network_device $child tun11 + +function cleanup { + kill -9 $child $slirp_pid +} +trap cleanup EXIT + +result="$(nsenter --preserve-credentials -U -n --target=$child ip a show dev tun11)" +echo "$result" | grep -o '^\s*inet6 .*/..' | grep -F $cidr::100/64 + +cleanup + +unshare -r -n sleep infinity & +child=$! + +slirp4netns -c $child --enable-ipv6 tun11 & +slirp_pid=$! + +wait_for_network_device $child tun11 + +result="$(nsenter --preserve-credentials -U -n --target=$child ip a show dev tun11)" +echo "$result" | grep -o '^\s*inet6 .*/..' | grep -F fd00::100/64 + +cleanup + +unshare -r -n sleep infinity & +child=$! + +slirp4netns -c $child --enable-ipv6 --ipv6-random tun11 & +slirp_pid=$! + +wait_for_network_device $child tun11 + +result="$(nsenter --preserve-credentials -U -n --target=$child ip a show dev tun11)" +echo "$result" | grep -o '^\s*inet6 .*/..' | grep -vF fd00::100/64 diff --git a/tests/test-slirp4netns-ipv6.sh b/tests/test-slirp4netns-ipv6.sh index 60f6af3..e110acf 100755 --- a/tests/test-slirp4netns-ipv6.sh +++ b/tests/test-slirp4netns-ipv6.sh @@ -3,6 +3,10 @@ set -xeuo pipefail . $(dirname $0)/common.sh +host_port=8080 +guest_port=80 +cidr=fd00:a1e1:1724:1a + unshare -r -n sleep infinity & child=$! @@ -11,7 +15,7 @@ wait_for_network_namespace $child tmpdir=$(mktemp -d /tmp/slirp4netns-bench.XXXXXXXXXX) apisocket=${tmpdir}/slirp4netns.sock -slirp4netns -c $child --enable-ipv6 --cidr6=fd00:fb14:63ee:b::/64 --api-socket $apisocket tun11 & +slirp4netns -c $child --enable-ipv6 --cidr6=$cidr::/64 --api-socket $apisocket tun11 & slirp_pid=$! wait_for_network_device $child tun11 @@ -39,10 +43,10 @@ result=$(echo '{"execute": "list_hostfwd"}' | ncat -U $apisocket) [[ $(echo $result | jq .entries[0].proto) == '"tcp"' ]] [[ $(echo $result | jq .entries[0].host_addr) == '"0.0.0.0"' ]] [[ $(echo $result | jq .entries[0].host_addr6) == '"::"' ]] -[[ $(echo $result | jq .entries[0].host_port) == 8080 ]] +[[ $(echo $result | jq .entries[0].host_port) == $host_port ]] [[ $(echo $result | jq .entries[0].guest_addr) == '"10.0.2.100"' ]] -[[ $(echo $result | jq .entries[0].guest_addr6) == '"fd00:fb14:63ee:b::100"' ]] -[[ $(echo $result | jq .entries[0].guest_port) == 80 ]] +[[ $(echo $result | jq .entries[0].guest_addr6) == '"'$cidr'::100"' ]] +[[ $(echo $result | jq .entries[0].guest_port) == $guest_port ]] result=$(echo '{"execute": "remove_hostfwd", "arguments":{"id": 1}}' | ncat -U $apisocket) [[ $(echo $result | jq .error) == null ]]