Skip to content

Commit

Permalink
IPv6 test ref rootless-containers#253
Browse files Browse the repository at this point in the history
Signed-off-by: fassl <[email protected]>
  • Loading branch information
jasmin authored and pfandl committed Sep 11, 2021
1 parent b156cc5 commit e1d49fb
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 28 deletions.
141 changes: 113 additions & 28 deletions api.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ int api_bindlisten(const char *api_socket)
struct api_hostfwd {
int id;
int is_udp;
int is_ipv4;
int is_ipv6;
struct in_addr host_addr;
struct in6_addr host_addr6;
int host_port;
struct in_addr guest_addr;
struct in6_addr guest_addr6;
int guest_port;
};

Expand Down Expand Up @@ -99,17 +103,19 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx,
const char *proto_s = json_object_dotget_string(jo, "arguments.proto");
const char *host_addr_s =
json_object_dotget_string(jo, "arguments.host_addr");
char *host_addr6_s = NULL;
const char *guest_addr_s =
json_object_dotget_string(jo, "arguments.guest_addr");
char *guest_addr6_s = NULL;
struct api_hostfwd *fwd = g_malloc0(sizeof(*fwd));
if (fwd == NULL) {
perror("fatal: malloc");
exit(EXIT_FAILURE);
}
fwd->is_udp = -1; /* TODO: support SCTP */
if (strcmp(proto_s, "udp") == 0) {
if (strncmp(proto_s, "udp", 3) == 0) {
fwd->is_udp = 1;
} else if (strcmp(proto_s, "tcp") == 0) {
} else if (strncmp(proto_s, "tcp", 3) == 0) {
fwd->is_udp = 0;
}
if (fwd->is_udp == -1) {
Expand All @@ -119,16 +125,26 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx,
free(fwd);
goto finish;
}
if (host_addr_s == NULL || host_addr_s[0] == '\0') {
host_addr_s = "0.0.0.0";
}
if (inet_pton(AF_INET, host_addr_s, &fwd->host_addr) != 1) {
const char *err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
"bad arguments.host_addr\"}}";
wrc = write(fd, err, strlen(err));
free(fwd);
goto finish;
int flags = (fwd->is_udp ? SLIRP_HOSTFWD_UDP : 0);

if (strlen(proto_s) == 4) {
if (proto_s[3] == '4') {
fwd->is_ipv4 = 1;
} else if (proto_s[3] == '6') {
fwd->is_ipv6 = 1;
} else {
const char *err =
"{\"error\":{\"desc\":\"bad request: add_hostfwd: "
"bad arguments.proto\"}}";
wrc = write(fd, err, strlen(err));
free(fwd);
goto finish;
}
} else {
fwd->is_ipv4 = 1;
fwd->is_ipv6 = 1;
}

fwd->host_port = (int)json_object_dotget_number(jo, "arguments.host_port");
if (fwd->host_port == 0) {
const char *err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
Expand All @@ -137,16 +153,6 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx,
free(fwd);
goto finish;
}

if (guest_addr_s == NULL || guest_addr_s[0] == '\0') {
fwd->guest_addr = ctx->cfg->recommended_vguest;
} else if (inet_pton(AF_INET, guest_addr_s, &fwd->guest_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;
}
fwd->guest_port =
(int)json_object_dotget_number(jo, "arguments.guest_port");
if (fwd->guest_port == 0) {
Expand All @@ -156,13 +162,92 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx,
free(fwd);
goto finish;
}
if (slirp_add_hostfwd(slirp, fwd->is_udp, fwd->host_addr, fwd->host_port,
fwd->guest_addr, fwd->guest_port) < 0) {
const char *err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
"slirp_add_hostfwd failed\"}}";
wrc = write(fd, err, strlen(err));
free(fwd);
goto finish;

if (fwd->is_ipv4) {
if (guest_addr_s == NULL || guest_addr_s[0] == '\0') {
fwd->guest_addr = ctx->cfg->recommended_vguest;
} else if (inet_pton(AF_INET, guest_addr_s, &fwd->guest_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;
}
if (host_addr_s == NULL || host_addr_s[0] == '\0') {
host_addr_s = "0.0.0.0";
}
if (inet_pton(AF_INET, host_addr_s, &fwd->host_addr) != 1) {
const char *err =
"{\"error\":{\"desc\":\"bad request: add_hostfwd: "
"bad arguments.host_addr\"}}";
wrc = write(fd, err, strlen(err));
free(fwd);
goto finish;
}
struct sockaddr_in host;
memset(&host, 0, sizeof(host));
host.sin_family = AF_INET;
host.sin_addr.s_addr = fwd->host_addr.s_addr;
host.sin_port = htons(fwd->host_port);
struct sockaddr_in guest;
memset(&guest, 0, sizeof(guest));
guest.sin_family = AF_INET;
guest.sin_addr.s_addr = fwd->guest_addr.s_addr;
guest.sin_port = htons(fwd->guest_port);
if (slirp_add_hostxfwd(slirp,
(const struct sockaddr*)&host, sizeof(host),
(const struct sockaddr*)&guest, sizeof(guest), flags) < 0) {
const char *err =
"{\"error\":{\"desc\":\"bad request: add_hostfwd: "
"slirp_add_hostxfwd failed\"}}";
wrc = write(fd, err, strlen(err));
free(fwd);
goto finish;
}
}
if (fwd->is_ipv6) {
if (guest_addr_s == NULL || guest_addr_s[0] == '\0') {
guest_addr_s = "fd00::100";
}
if (inet_pton(AF_INET6, guest_addr_s, &fwd->guest_addr6) != 1) {
const char *err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
"bad arguments.guest_addr\"}}";
wrc = write(fd, err, strlen(err));
free(fwd);
goto finish;
}
if (host_addr_s == NULL || host_addr_s[0] == '\0' ||
strcmp(host_addr_s, "0.0.0.0") == 0) {
host_addr_s = "::";
}
if (inet_pton(AF_INET6, host_addr_s, &fwd->host_addr6) != 1) {
const char *err =
"{\"error\":{\"desc\":\"bad request: add_hostfwd: "
"bad arguments.host_addr\"}}";
wrc = write(fd, err, strlen(err));
free(fwd);
goto finish;
}
struct sockaddr_in6 host;
memset(&host, 0, sizeof(host));
host.sin6_family = AF_INET6;
host.sin6_addr = fwd->host_addr6;
host.sin6_port = htons(fwd->host_port);
struct sockaddr_in6 guest;
memset(&guest, 0, sizeof(guest));
guest.sin6_family = AF_INET6;
guest.sin6_addr = fwd->guest_addr6;
guest.sin6_port = htons(fwd->guest_port);
if (slirp_add_hostxfwd(slirp,
(const struct sockaddr*)&host, sizeof(host),
(const struct sockaddr*)&guest, sizeof(guest), flags) < 0) {
const char *err =
"{\"error\":{\"desc\":\"bad request: add_hostfwd: "
"slirp_add_hostfwd failed\"}}";
wrc = write(fd, err, strlen(err));
free(fwd);
goto finish;
}
}
fwd->id = ctx->hostfwds_nextid;
ctx->hostfwds_nextid++;
Expand Down
55 changes: 55 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,58 @@ static int configure_network(const char *tapname,
return 0;
}

struct in6_ifreq {
struct in6_addr ifr6_addr;
__u32 ifr6_prefixlen;
unsigned int ifr6_ifindex;
};

static int configure_network6(const char *tapname,
struct slirp4netns_config *cfg)
{
struct rtentry route;
struct ifreq ifr;
struct in6_ifreq ifr6;
struct sockaddr_in6 sai;
int sockfd;

sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("cannot create socket");
return -1;
}

memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_UP | IFF_RUNNING;
strncpy(ifr.ifr_name, tapname, sizeof(ifr.ifr_name) - 1);

if (ioctl(sockfd, SIOGIFINDEX, &ifr) < 0) {
perror("cannot get dev index");
return -1;
}

memset(&sai, 0, sizeof(struct sockaddr));
sai.sin6_family = AF_INET6;
sai.sin6_port = 0;

if (inet_pton(AF_INET6, "fd00::100", &sai.sin6_addr) != 1) {
perror("cannot create device address");
return -1;
}

memcpy((char *)&ifr6.ifr6_addr, &sai.sin6_addr, sizeof(struct in6_addr));

ifr6.ifr6_ifindex = ifr.ifr_ifindex;
ifr6.ifr6_prefixlen = 64;

if (ioctl(sockfd, SIOCSIFADDR, &ifr6) < 0) {
perror("cannot set device address");
return -1;
}

return 0;
}

static int child(int sock, pid_t target_pid, bool do_config_network,
const char *tapname, char *netns_path, char *userns_path,
struct slirp4netns_config *cfg)
Expand All @@ -219,6 +271,9 @@ static int child(int sock, pid_t target_pid, bool do_config_network,
if (do_config_network && configure_network(tapname, cfg) < 0) {
return -1;
}
if (do_config_network && configure_network6(tapname, cfg) < 0) {
return -1;
}
if (sendfd(sock, tapfd) < 0) {
close(tapfd);
close(sock);
Expand Down

0 comments on commit e1d49fb

Please sign in to comment.