Skip to content

Commit 6a6e469

Browse files
committed
add --ipv6-random flag: rootless-containers#259
Signed-off-by: fassl <[email protected]>
1 parent fcb7f2e commit 6a6e469

File tree

4 files changed

+102
-30
lines changed

4 files changed

+102
-30
lines changed

Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ AM_CFLAGS = @GLIB_CFLAGS@ @SLIRP_CFLAGS@ @LIBCAP_CFLAGS@ @LIBSECCOMP_CFLAGS@
55
noinst_LIBRARIES = libparson.a
66

77
AM_TESTS_ENVIRONMENT = PATH="$(abs_top_builddir):$(PATH)"
8-
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
8+
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
99

1010
EXTRA_DIST = \
1111
slirp4netns.1.md \

main.c

+24-25
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
// + 100 .
4444
#define NETWORK_PREFIX_MAX (25)
4545
#define NETWORK_PREFIX_MIN6 (8)
46-
#define NETWORK_PREFIX_MAX6 (64)
46+
#define NETWORK_PREFIX_MAX6 (128)
4747

4848
static int nsenter(pid_t target_pid, char *netns, char *userns,
4949
bool only_userns)
@@ -241,7 +241,6 @@ static const char *pseudo_random_global_id(const char *device)
241241
ifr.ifr_flags = IFF_UP | IFF_RUNNING;
242242

243243
if (device == NULL) {
244-
/* TODO: which device should we get the mac address from? */
245244
device = "lo";
246245
}
247246
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1);
@@ -312,7 +311,7 @@ static const char *pseudo_random_global_id(const char *device)
312311
* ID to create a Local IPv6 address prefix.
313312
*/
314313

315-
sprintf(id, "fd00:%s::", tmp);
314+
sprintf(id, "fd00:%s::/64", tmp);
316315

317316
return id;
318317
}
@@ -591,6 +590,7 @@ struct options {
591590
bool do_config_network; // -c
592591
bool disable_host_loopback; // --disable-host-loopback
593592
bool enable_ipv6; // -6
593+
bool ipv6_random; // --ipv6-random
594594
bool enable_sandbox; // --enable-sandbox
595595
bool enable_seccomp; // --enable-seccomp
596596
bool disable_dns; // --disable-dns
@@ -663,8 +663,9 @@ static void parse_args(int argc, char *const argv[], struct options *options)
663663
char *optarg_outbound_addr = NULL;
664664
char *optarg_outbound_addr6 = NULL;
665665
char *optarg_macaddress = NULL;
666-
#define CIDR -41
667-
#define CIDR6 -42
666+
#define CIDR -40
667+
#define CIDR6 -41
668+
#define IPV6_RANDOM -42
668669
#define DISABLE_HOST_LOOPBACK -43
669670
#define NETNS_TYPE -44
670671
#define USERNS_PATH -45
@@ -691,6 +692,7 @@ static void parse_args(int argc, char *const argv[], struct options *options)
691692
{ "userns-path", required_argument, NULL, USERNS_PATH },
692693
{ "api-socket", required_argument, NULL, 'a' },
693694
{ "enable-ipv6", no_argument, NULL, '6' },
695+
{ "ipv6-random", no_argument, NULL, IPV6_RANDOM },
694696
{ "enable-sandbox", no_argument, NULL, ENABLE_SANDBOX },
695697
{ "create-sandbox", no_argument, NULL, _DEPRECATED_CREATE_SANDBOX },
696698
{ "enable-seccomp", no_argument, NULL, ENABLE_SECCOMP },
@@ -783,6 +785,9 @@ static void parse_args(int argc, char *const argv[], struct options *options)
783785
options->enable_ipv6 = true;
784786
printf("WARNING: Support for IPv6 is experimental\n");
785787
break;
788+
case IPV6_RANDOM:
789+
options->ipv6_random = true;
790+
break;
786791
case 'h':
787792
usage(argv[0]);
788793
exit(EXIT_SUCCESS);
@@ -982,29 +987,12 @@ static int parse_cidr6(struct in6_addr *network, struct in6_addr *netmask,
982987
fprintf(stderr, "invalid CIDR: %s\n", cidr);
983988
goto finish;
984989
}
985-
rc = from_regmatch(snetwork_end, sizeof(snetwork_end), matches[2], cidr);
986-
if (rc < 0) {
987-
fprintf(stderr, "invalid CIDR: %s\n", cidr);
988-
goto finish;
989-
}
990990
rc = from_regmatch(sprefix, sizeof(sprefix), matches[4], cidr);
991991
if (rc < 0) {
992992
fprintf(stderr, "invalid CIDR: %s\n", cidr);
993993
goto finish;
994994
}
995-
if (strcmp(snetwork, snetwork_end) == 0) {
996-
random = pseudo_random_global_id(NULL);
997-
if (random == NULL) {
998-
fprintf(stderr, "cannot create pseudo random global id\n");
999-
rc = -1;
1000-
goto finish;
1001-
}
1002-
strcpy(snetwork, random);
1003-
strcat(snetwork, "0");
1004-
} else {
1005-
strcat(snetwork, ":0");
1006-
}
1007-
995+
strcat(snetwork, ":");
1008996
if (inet_pton(AF_INET6, snetwork, network) != 1) {
1009997
fprintf(stderr, "invalid network address: %s\n", snetwork);
1010998
rc = -1;
@@ -1179,8 +1167,19 @@ static int slirp4netns_config_from_options(struct slirp4netns_config *cfg,
11791167
cfg->enable_seccomp = opt->enable_seccomp;
11801168

11811169
if (cfg->enable_ipv6) {
1182-
rc = slirp4netns_config_from_cidr6(cfg, opt->cidr6 == NULL ? DEFAULT_CIDR6 :
1183-
opt->cidr6);
1170+
const char *cidr = opt->cidr6;
1171+
if (cidr == NULL) {
1172+
cidr = DEFAULT_CIDR6;
1173+
if (opt->ipv6_random) {
1174+
cidr = pseudo_random_global_id("lo");
1175+
if (cidr == NULL) {
1176+
fprintf(stderr, "cannot create pseudo random global id\n");
1177+
rc = -1;
1178+
goto finish;
1179+
}
1180+
}
1181+
}
1182+
rc = slirp4netns_config_from_cidr6(cfg, cidr);
11841183
if (rc < 0) {
11851184
goto finish;
11861185
}

tests/test-slirp4netns-cidr6.sh

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/bin/bash
2+
set -xeuo pipefail
3+
4+
. $(dirname $0)/common.sh
5+
6+
unshare -r -n sleep infinity &
7+
child=$!
8+
9+
wait_for_network_namespace $child
10+
11+
set +e
12+
result=$(slirp4netns -c --enable-ipv6 --cidr6 64 $child tun11 2>&1)
13+
set -e
14+
echo $result | grep "invalid CIDR"
15+
16+
set +e
17+
result=$(slirp4netns -c --enable-ipv6 --cidr6 foo $child tun11 2>&1)
18+
set -e
19+
echo $result | grep "invalid CIDR"
20+
21+
set +e
22+
result=$(slirp4netns -c --enable-ipv6 --cidr6 fd00::2 $child tun11 2>&1)
23+
set -e
24+
echo $result | grep "invalid CIDR"
25+
26+
set +e
27+
result=$(slirp4netns -c --enable-ipv6 --cidr6 fd00::/129 $child tun11 2>&1)
28+
set -e
29+
echo $result | grep "prefix length needs to be 8-128"
30+
31+
cidr=fd00:a1e1:1724:1a
32+
slirp4netns -c $child --enable-ipv6 --cidr6 $cidr::/64 tun11 &
33+
slirp_pid=$!
34+
35+
wait_for_network_device $child tun11
36+
37+
function cleanup {
38+
kill -9 $child $slirp_pid
39+
}
40+
trap cleanup EXIT
41+
42+
result="$(nsenter --preserve-credentials -U -n --target=$child ip a show dev tun11)"
43+
echo "$result" | grep -o '^\s*inet6 .*/..' | grep -F $cidr::100/64
44+
45+
cleanup
46+
47+
unshare -r -n sleep infinity &
48+
child=$!
49+
50+
slirp4netns -c $child --enable-ipv6 tun11 &
51+
slirp_pid=$!
52+
53+
wait_for_network_device $child tun11
54+
55+
result="$(nsenter --preserve-credentials -U -n --target=$child ip a show dev tun11)"
56+
echo "$result" | grep -o '^\s*inet6 .*/..' | grep -F fd00::100/64
57+
58+
cleanup
59+
60+
unshare -r -n sleep infinity &
61+
child=$!
62+
63+
slirp4netns -c $child --enable-ipv6 --ipv6-random tun11 &
64+
slirp_pid=$!
65+
66+
wait_for_network_device $child tun11
67+
68+
result="$(nsenter --preserve-credentials -U -n --target=$child ip a show dev tun11)"
69+
echo "$result" | grep -o '^\s*inet6 .*/..' | grep -vF fd00::100/64

tests/test-slirp4netns-ipv6.sh

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ set -xeuo pipefail
33

44
. $(dirname $0)/common.sh
55

6+
host_port=8080
7+
guest_port=80
8+
cidr=fd00:a1e1:1724:1a
9+
610
unshare -r -n sleep infinity &
711
child=$!
812

@@ -11,7 +15,7 @@ wait_for_network_namespace $child
1115
tmpdir=$(mktemp -d /tmp/slirp4netns-bench.XXXXXXXXXX)
1216
apisocket=${tmpdir}/slirp4netns.sock
1317

14-
slirp4netns -c $child --enable-ipv6 --cidr6=fd00:fb14:63ee:b::/64 --api-socket $apisocket tun11 &
18+
slirp4netns -c $child --enable-ipv6 --cidr6=$cidr::/64 --api-socket $apisocket tun11 &
1519
slirp_pid=$!
1620

1721
wait_for_network_device $child tun11
@@ -39,10 +43,10 @@ result=$(echo '{"execute": "list_hostfwd"}' | ncat -U $apisocket)
3943
[[ $(echo $result | jq .entries[0].proto) == '"tcp"' ]]
4044
[[ $(echo $result | jq .entries[0].host_addr) == '"0.0.0.0"' ]]
4145
[[ $(echo $result | jq .entries[0].host_addr6) == '"::"' ]]
42-
[[ $(echo $result | jq .entries[0].host_port) == 8080 ]]
46+
[[ $(echo $result | jq .entries[0].host_port) == $host_port ]]
4347
[[ $(echo $result | jq .entries[0].guest_addr) == '"10.0.2.100"' ]]
44-
[[ $(echo $result | jq .entries[0].guest_addr6) == '"fd00:fb14:63ee:b::100"' ]]
45-
[[ $(echo $result | jq .entries[0].guest_port) == 80 ]]
48+
[[ $(echo $result | jq .entries[0].guest_addr6) == '"'$cidr'::100"' ]]
49+
[[ $(echo $result | jq .entries[0].guest_port) == $guest_port ]]
4650

4751
result=$(echo '{"execute": "remove_hostfwd", "arguments":{"id": 1}}' | ncat -U $apisocket)
4852
[[ $(echo $result | jq .error) == null ]]

0 commit comments

Comments
 (0)