Skip to content

Commit

Permalink
add --ipv6-random flag: rootless-containers#259
Browse files Browse the repository at this point in the history
  • Loading branch information
pfandl committed Sep 11, 2021
1 parent a3ca11a commit e7e38a6
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
49 changes: 24 additions & 25 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 },
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
69 changes: 69 additions & 0 deletions tests/test-slirp4netns-cidr6.sh
Original file line number Diff line number Diff line change
@@ -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
12 changes: 8 additions & 4 deletions tests/test-slirp4netns-ipv6.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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=$!

Expand All @@ -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
Expand Down Expand Up @@ -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 ]]
Expand Down

0 comments on commit e7e38a6

Please sign in to comment.