From 346fb19c08c52c669f1db559a6310107fc556267 Mon Sep 17 00:00:00 2001 From: fassl Date: Sat, 11 Sep 2021 21:29:03 +0200 Subject: [PATCH] IPv6: #259 #253 - skip ipv6 tests on old libslirp versions - install openssl-devel on centos box - use *hostfwd functions on old libslirp versions Signed-off-by: fassl --- Vagrantfile | 2 +- api.c | 97 +++++++++++++++++++++--------- main.c | 43 +++++++------ tests/test-slirp4netns-hostfwd.sh | 7 +++ tests/test-slirp4netns-hostfwd4.sh | 5 ++ tests/test-slirp4netns-hostfwd6.sh | 5 ++ tests/test-slirp4netns-ipv6.sh | 5 ++ 7 files changed, 113 insertions(+), 51 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 9a4c089..5964516 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -20,7 +20,7 @@ Vagrant.configure("2") do |config| yum install -y \ autoconf automake make gcc gperf libtool \ git-core meson ninja-build \ - glib2-devel libcap-devel \ + glib2-devel libcap-devel openssl-devel \ git-core libtool iproute iputils iperf3 nmap jq # TODO: install udhcpc (required by test-slirp4netns-dhcp.sh) diff --git a/api.c b/api.c index 9a98c8a..8d8fb19 100644 --- a/api.c +++ b/api.c @@ -123,13 +123,14 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx, free(fwd); goto finish; } +#if SLIRP_CONFIG_VERSION_MAX >= 3 int flags = (fwd->is_udp ? SLIRP_HOSTFWD_UDP : 0); +#endif if (host_addr_s == NULL || host_addr_s[0] == '\0') { host_addr_s = "0.0.0.0"; } - if (strcmp("0.0.0.0", host_addr_s) == 0 || - strcmp("::", host_addr_s) == 0 || + if (strcmp("0.0.0.0", host_addr_s) == 0 || strcmp("::", host_addr_s) == 0 || strcmp("::0", host_addr_s) == 0) { fwd->is_ipv4 = 1; fwd->is_ipv6 = ctx->cfg->enable_ipv6; @@ -137,8 +138,7 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx, } else { if (strchr(host_addr_s, '.')) { fwd->is_ipv4 = 1; - } - else if (strchr(host_addr_s, ':')) { + } else if (strchr(host_addr_s, ':')) { if (!ctx->cfg->enable_ipv6) { const char *err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: " @@ -201,9 +201,11 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx, fwd->guest.sin_port = htons(fwd->guest_port); if (guest_addr_s == NULL || guest_addr_s[0] == '\0') { fwd->guest.sin_addr = ctx->cfg->recommended_vguest; - } else if (inet_pton(AF_INET, guest_addr_s, &fwd->guest.sin_addr) != 1) { - const char *err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: " - "bad arguments.guest_addr\"}}"; + } else if (inet_pton(AF_INET, guest_addr_s, &fwd->guest.sin_addr) != + 1) { + const char *err = + "{\"error\":{\"desc\":\"bad request: add_hostfwd: " + "bad arguments.guest_addr\"}}"; wrc = write(fd, err, strlen(err)); free(fwd); goto finish; @@ -216,9 +218,11 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx, free(fwd); goto finish; } - if (slirp_add_hostxfwd(slirp, - (const struct sockaddr*)&fwd->host, sizeof(fwd->host), - (const struct sockaddr*)&fwd->guest, sizeof(fwd->guest), flags) < 0) { +#if SLIRP_CONFIG_VERSION_MAX >= 3 + if (slirp_add_hostxfwd(slirp, (const struct sockaddr *)&fwd->host, + sizeof(fwd->host), + (const struct sockaddr *)&fwd->guest, + sizeof(fwd->guest), flags) < 0) { const char *err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: " "slirp_add_hostxfwd failed\"}}"; @@ -226,8 +230,21 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx, free(fwd); goto finish; } +#else + if (slirp_add_hostfwd(slirp, fwd->is_udp, fwd->host.sin_addr, + fwd->host_port, fwd->guest.sin_addr, + fwd->guest_port) < 0) { + const char *err = + "{\"error\":{\"desc\":\"bad request: add_hostfwd: " + "slirp_add_hostxfwd failed\"}}"; + wrc = write(fd, err, strlen(err)); + free(fwd); + goto finish; + } +#endif } +#if SLIRP_CONFIG_VERSION_MAX >= 3 if (fwd->is_ipv6) { fwd->host6.sin6_family = AF_INET6; fwd->guest6.sin6_family = AF_INET6; @@ -235,9 +252,11 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx, fwd->guest6.sin6_port = htons(fwd->guest_port); if (guest_addr_s == NULL || guest_addr_s[0] == '\0') { fwd->guest6.sin6_addr = ctx->cfg->recommended_vguest6; - } else if (inet_pton(AF_INET6, guest_addr_s, &fwd->guest6.sin6_addr) != 1) { - const char *err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: " - "bad arguments.guest_addr\"}}"; + } else if (inet_pton(AF_INET6, guest_addr_s, &fwd->guest6.sin6_addr) != + 1) { + const char *err = + "{\"error\":{\"desc\":\"bad request: add_hostfwd: " + "bad arguments.guest_addr\"}}"; wrc = write(fd, err, strlen(err)); free(fwd); goto finish; @@ -254,9 +273,10 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx, goto finish; } flags |= SLIRP_HOSTFWD_V6ONLY; - if (slirp_add_hostxfwd(slirp, - (const struct sockaddr*)&fwd->host6, sizeof(fwd->host6), - (const struct sockaddr*)&fwd->guest6, sizeof(fwd->guest6), flags) < 0) { + if (slirp_add_hostxfwd(slirp, (const struct sockaddr *)&fwd->host6, + sizeof(fwd->host6), + (const struct sockaddr *)&fwd->guest6, + sizeof(fwd->guest6), flags) < 0) { const char *err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: " "slirp_add_hostxfwd failed\"}}"; @@ -265,6 +285,7 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx, goto finish; } } +#endif fwd->id = ctx->hostfwds_nextid; ctx->hostfwds_nextid++; ctx->hostfwds = g_list_append(ctx->hostfwds, fwd); @@ -288,25 +309,25 @@ static void api_handle_req_list_hostfwd_foreach(gpointer data, char host_addr[INET_ADDRSTRLEN], guest_addr[INET_ADDRSTRLEN]; char host_addr6[INET6_ADDRSTRLEN], guest_addr6[INET6_ADDRSTRLEN]; if (fwd->is_ipv4) { - if (inet_ntop(AF_INET, &fwd->host.sin_addr, host_addr, sizeof(host_addr)) == - NULL) { + if (inet_ntop(AF_INET, &fwd->host.sin_addr, host_addr, + sizeof(host_addr)) == NULL) { perror("fatal: inet_ntop"); exit(EXIT_FAILURE); } - if (inet_ntop(AF_INET, &fwd->guest.sin_addr, guest_addr, sizeof(guest_addr)) == - NULL) { + if (inet_ntop(AF_INET, &fwd->guest.sin_addr, guest_addr, + sizeof(guest_addr)) == NULL) { perror("fatal: inet_ntop"); exit(EXIT_FAILURE); } } if (fwd->is_ipv6) { - if (inet_ntop(AF_INET6, &fwd->host6.sin6_addr, host_addr6, sizeof(host_addr6)) == - NULL) { + if (inet_ntop(AF_INET6, &fwd->host6.sin6_addr, host_addr6, + sizeof(host_addr6)) == NULL) { perror("fatal: inet_ntop"); exit(EXIT_FAILURE); } - if (inet_ntop(AF_INET6, &fwd->guest6.sin6_addr, guest_addr6, sizeof(guest_addr6)) == - NULL) { + if (inet_ntop(AF_INET6, &fwd->guest6.sin6_addr, guest_addr6, + sizeof(guest_addr6)) == NULL) { perror("fatal: inet_ntop"); exit(EXIT_FAILURE); } @@ -384,21 +405,37 @@ static int api_handle_req_remove_hostfwd(Slirp *slirp, int fd, struct api_hostfwd *fwd = found->data; const char *api_ok = "{\"return\":{}}"; if (fwd->is_ipv4) { +#if SLIRP_CONFIG_VERSION_MAX >= 3 if (slirp_remove_hostxfwd(slirp, - (const struct sockaddr*)&fwd->host, sizeof(fwd->host), 0) < 0) { - const char *err = "{\"error\":{\"desc\":\"bad request: " - "remove_hostfwd: slirp_remove_hostxfwd failed\"}}"; + (const struct sockaddr *)&fwd->host, + sizeof(fwd->host), 0) < 0) { + const char *err = + "{\"error\":{\"desc\":\"bad request: " + "remove_hostfwd: slirp_remove_hostxfwd failed\"}}"; return write(fd, err, strlen(err)); } +#else + if (slirp_remove_hostfwd(slirp, fwd->is_udp, fwd->host.sin_addr, + fwd->host_port) < 0) { + const char *err = + "{\"error\":{\"desc\":\"bad request: " + "remove_hostfwd: slirp_remove_hostfwd failed\"}}"; + return write(fd, err, strlen(err)); + } +#endif } +#if SLIRP_CONFIG_VERSION_MAX >= 3 if (fwd->is_ipv6) { if (slirp_remove_hostxfwd(slirp, - (const struct sockaddr*)&fwd->host6, sizeof(fwd->host6), 0) < 0) { - const char *err = "{\"error\":{\"desc\":\"bad request: " - "remove_hostfwd: slirp_remove_hostxfwd failed\"}}"; + (const struct sockaddr *)&fwd->host6, + sizeof(fwd->host6), 0) < 0) { + const char *err = + "{\"error\":{\"desc\":\"bad request: " + "remove_hostfwd: slirp_remove_hostxfwd failed\"}}"; return write(fd, err, strlen(err)); } } +#endif ctx->hostfwds = g_list_remove(ctx->hostfwds, fwd); g_free(fwd); wrc = write(fd, api_ok, strlen(api_ok)); diff --git a/main.c b/main.c index 6ea6df9..519caad 100644 --- a/main.c +++ b/main.c @@ -261,9 +261,9 @@ static const char *pseudo_random_global_id(const char *device) return NULL; } close(rand); - } - else { - strncpy(mac, ifr.ifr_ifru.ifru_addr.sa_data, sizeof(mac)); + } else { + strncpy((char *)mac, (const char *)ifr.ifr_ifru.ifru_addr.sa_data, + sizeof(mac)); } /* https://tools.ietf.org/html/rfc4193 @@ -988,9 +988,8 @@ static int parse_cidr6(struct in6_addr *network, struct in6_addr *netmask, regmatch_t matches[5]; size_t nmatch = sizeof(matches) / sizeof(matches[0]); const char *cidr_regex = "^((([a-fA-F0-9]{1,4}):){1,4}):/([0-9]{1,3})"; - char snetwork[INET6_ADDRSTRLEN], - snetwork_end[INET6_ADDRSTRLEN], - sprefix[INET6_ADDRSTRLEN]; + char snetwork[INET6_ADDRSTRLEN], snetwork_end[INET6_ADDRSTRLEN], + sprefix[INET6_ADDRSTRLEN]; int prefix; const char *random; rc = regcomp(&r, cidr_regex, REG_EXTENDED); @@ -1015,7 +1014,7 @@ static int parse_cidr6(struct in6_addr *network, struct in6_addr *netmask, fprintf(stderr, "invalid CIDR: %s\n", cidr); goto finish; } - strcat(snetwork, ":"); + strncat(snetwork, ":", 2); if (inet_pton(AF_INET6, snetwork, network) != 1) { fprintf(stderr, "invalid network address: %s\n", snetwork); rc = -1; @@ -1029,8 +1028,8 @@ static int parse_cidr6(struct in6_addr *network, struct in6_addr *netmask, goto finish; } if (prefix < NETWORK_PREFIX_MIN6 || prefix > NETWORK_PREFIX_MAX6) { - fprintf(stderr, "prefix length needs to be %d-%d\n", NETWORK_PREFIX_MIN6, - NETWORK_PREFIX_MAX6); + fprintf(stderr, "prefix length needs to be %d-%d\n", + NETWORK_PREFIX_MIN6, NETWORK_PREFIX_MAX6); rc = -1; goto finish; } @@ -1085,32 +1084,36 @@ static int slirp4netns_config_from_cidr6(struct slirp4netns_config *cfg, return -1; } -#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) strncpy(tmp, net, sizeof(tmp)); - strncat(tmp, DEFAULT_VHOST_OFFSET6, - MAX(0, INET6_ADDRSTRLEN - strlen(tmp) - strlen(DEFAULT_VHOST_OFFSET6))); + strncat( + tmp, DEFAULT_VHOST_OFFSET6, + MAX(0, INET6_ADDRSTRLEN - strlen(tmp) - strlen(DEFAULT_VHOST_OFFSET6))); if (inet_pton(AF_INET6, tmp, &cfg->vhost6) != 1) { return -1; } strncpy(tmp, net, sizeof(tmp)); strncat(tmp, DEFAULT_VDHCPSTART_OFFSET6, - MAX(0, INET6_ADDRSTRLEN - strlen(tmp) - strlen(DEFAULT_VDHCPSTART_OFFSET6))); + MAX(0, INET6_ADDRSTRLEN - strlen(tmp) - + strlen(DEFAULT_VDHCPSTART_OFFSET6))); if (inet_pton(AF_INET6, tmp, &cfg->vdhcp_start6) != 1) { return -1; } strncpy(tmp, net, sizeof(tmp)); strncat(tmp, DEFAULT_VNAMESERVER_OFFSET6, - MAX(0, INET6_ADDRSTRLEN - strlen(tmp) - strlen(DEFAULT_VNAMESERVER_OFFSET6))); + MAX(0, INET6_ADDRSTRLEN - strlen(tmp) - + strlen(DEFAULT_VNAMESERVER_OFFSET6))); if (inet_pton(AF_INET6, tmp, &cfg->vnameserver6) != 1) { return -1; } strncpy(tmp, net, sizeof(tmp)); strncat(tmp, DEFAULT_RECOMMENDED_VGUEST_OFFSET6, - MAX(0, INET6_ADDRSTRLEN - strlen(tmp) - strlen(DEFAULT_RECOMMENDED_VGUEST_OFFSET6))); + MAX(0, INET6_ADDRSTRLEN - strlen(tmp) - + strlen(DEFAULT_RECOMMENDED_VGUEST_OFFSET6))); if (inet_pton(AF_INET6, tmp, &cfg->recommended_vguest6) != 1) { return -1; } @@ -1196,9 +1199,9 @@ static int slirp4netns_config_from_options(struct slirp4netns_config *cfg, cfg->enable_seccomp = opt->enable_seccomp; if (cfg->enable_ipv6) { - const char *cidr = opt->cidr6; - if (cidr == NULL) { - cidr = DEFAULT_CIDR6; + const char *cidr = opt->cidr6; + if (cidr == NULL) { + cidr = DEFAULT_CIDR6; if (opt->ipv6_random) { cidr = pseudo_random_global_id("tap0"); if (cidr == NULL) { @@ -1206,8 +1209,8 @@ static int slirp4netns_config_from_options(struct slirp4netns_config *cfg, rc = -1; goto finish; } - } - } + } + } rc = slirp4netns_config_from_cidr6(cfg, cidr); if (rc < 0) { goto finish; diff --git a/tests/test-slirp4netns-hostfwd.sh b/tests/test-slirp4netns-hostfwd.sh index 20302d2..d5187a3 100755 --- a/tests/test-slirp4netns-hostfwd.sh +++ b/tests/test-slirp4netns-hostfwd.sh @@ -3,6 +3,13 @@ set -xeuo pipefail . $(dirname $0)/common.sh +SLIRP_CONFIG_VERSION_MAX=$(slirp4netns -v | grep "SLIRP_CONFIG_VERSION_MAX: " | sed 's#SLIRP_CONFIG_VERSION_MAX: \(\)##') + +if [ "${SLIRP_CONFIG_VERSION_MAX:-0}" -lt 3 ]; then + printf "forwarding test requires SLIRP_CONFIG_VERSION_MAX 3 or newer. Test skipped..." + exit "$TEST_EXIT_CODE_SKIP" +fi + host_port=8080 guest_port=1080 cidr=fd00:a1e1:1724:1a diff --git a/tests/test-slirp4netns-hostfwd4.sh b/tests/test-slirp4netns-hostfwd4.sh index 86504f2..791c436 100755 --- a/tests/test-slirp4netns-hostfwd4.sh +++ b/tests/test-slirp4netns-hostfwd4.sh @@ -3,6 +3,11 @@ set -xeuo pipefail . $(dirname $0)/common.sh +if [ "${SLIRP_CONFIG_VERSION_MAX:-0}" -lt 3 ]; then + printf "forwarding test requires SLIRP_CONFIG_VERSION_MAX 3 or newer. Test skipped..." + exit "$TEST_EXIT_CODE_SKIP" +fi + host_port=8080 guest_port=1080 diff --git a/tests/test-slirp4netns-hostfwd6.sh b/tests/test-slirp4netns-hostfwd6.sh index f5b86b4..283949c 100755 --- a/tests/test-slirp4netns-hostfwd6.sh +++ b/tests/test-slirp4netns-hostfwd6.sh @@ -3,6 +3,11 @@ set -xeuo pipefail . $(dirname $0)/common.sh +if [ "${SLIRP_CONFIG_VERSION_MAX:-0}" -lt 3 ]; then + printf "forwarding test requires SLIRP_CONFIG_VERSION_MAX 3 or newer. Test skipped..." + exit "$TEST_EXIT_CODE_SKIP" +fi + host_port=8080 guest_port=1080 cidr=fd00:a1e1:1724:1a diff --git a/tests/test-slirp4netns-ipv6.sh b/tests/test-slirp4netns-ipv6.sh index e110acf..8fc2e9d 100755 --- a/tests/test-slirp4netns-ipv6.sh +++ b/tests/test-slirp4netns-ipv6.sh @@ -3,6 +3,11 @@ set -xeuo pipefail . $(dirname $0)/common.sh +if [ "${SLIRP_CONFIG_VERSION_MAX:-0}" -lt 3 ]; then + printf "ipv6 test requires SLIRP_CONFIG_VERSION_MAX 3 or newer. Test skipped..." + exit "$TEST_EXIT_CODE_SKIP" +fi + host_port=8080 guest_port=80 cidr=fd00:a1e1:1724:1a