Control: tags -1 + pending On Thu, Mar 27, 2025 at 08:23:20AM +0100, Helmut Grohne wrote: > Alternatively, how about cherry-picking the relevant upstream commit? > > Would you object to me doing a NMU achieving the latter?
I went ahead and uploaded the attached debdiff. Helmut
diff --minimal -Nru slirp4netns-1.2.1/debian/changelog slirp4netns-1.2.1/debian/changelog --- slirp4netns-1.2.1/debian/changelog 2023-09-08 23:53:07.000000000 +0200 +++ slirp4netns-1.2.1/debian/changelog 2025-04-11 21:20:36.000000000 +0200 @@ -1,3 +1,10 @@ +slirp4netns (1.2.1-1.1) unstable; urgency=medium + + * Non-maintainer upload. + * Cherry-pick --netns-type=tapfd from upstream (Closes: #1056192) + + -- Helmut Grohne <hel...@subdivi.de> Fri, 11 Apr 2025 21:20:36 +0200 + slirp4netns (1.2.1-1) unstable; urgency=medium * New upstream version diff --minimal -Nru slirp4netns-1.2.1/debian/patches/netns_type_tapfd.patch slirp4netns-1.2.1/debian/patches/netns_type_tapfd.patch --- slirp4netns-1.2.1/debian/patches/netns_type_tapfd.patch 1970-01-01 01:00:00.000000000 +0100 +++ slirp4netns-1.2.1/debian/patches/netns_type_tapfd.patch 2025-04-11 21:12:07.000000000 +0200 @@ -0,0 +1,251 @@ +From 436755d05ec7bc16562df2f9098391fbde569da1 Mon Sep 17 00:00:00 2001 +From: Helmut Grohne <hel...@subdivi.de> +Date: Mon, 25 Mar 2024 07:32:37 +0100 +Subject: [PATCH] Support new --netns-type=tapfd + +The new value tapfd enables removing slirp4netns features. Rather than +having it figure out where to create a tap network, the opened tap file +descriptor can now be inherited to slirp4netns and used as is. This +removes the need for forking and attaching a namespace as well as +readiness communication, but it also removes the ability to choose the +name of the network interface or configuring it. + +Signed-off-by: Helmut Grohne <hel...@subdivi.de> +--- + main.c | 114 +++++++++++++++++++++++++++++++------------------- + slirp4netns.1 | 7 +++- + 2 files changed, 76 insertions(+), 45 deletions(-) + +diff --git a/main.c b/main.c +index a089560..6469e8f 100644 +--- a/main.c ++++ b/main.c +@@ -355,11 +355,11 @@ static int recvfd(int sock) + return fd; + } + +-static int parent(int sock, int ready_fd, int exit_fd, const char *api_socket, ++static int parent(int tapfd, int ready_fd, int exit_fd, const char *api_socket, + struct slirp4netns_config *cfg, pid_t target_pid) + { + char str[INET6_ADDRSTRLEN]; +- int rc, tapfd; ++ int rc; + struct in_addr vdhcp_end = { + #define NB_BOOTP_CLIENTS 16 + /* NB_BOOTP_CLIENTS is hard-coded to 16 in libslirp: +@@ -367,11 +367,6 @@ static int parent(int sock, int ready_fd, int exit_fd, const char *api_socket, + .s_addr = htonl(ntohl(cfg->vdhcp_start.s_addr) + NB_BOOTP_CLIENTS - 1), + #undef NB_BOOTP_CLIENTS + }; +- if ((tapfd = recvfd(sock)) < 0) { +- return tapfd; +- } +- fprintf(stderr, "received tapfd=%d\n", tapfd); +- close(sock); + printf("Starting slirp\n"); + printf("* MTU: %d\n", cfg->mtu); + printf("* Network: %s\n", +@@ -442,7 +437,7 @@ static int parent(int sock, int ready_fd, int exit_fd, const char *api_socket, + + static void usage(const char *argv0) + { +- printf("Usage: %s [OPTION]... PID|PATH [TAPNAME]\n", argv0); ++ printf("Usage: %s [OPTION]... PID|PATH|FD [TAPNAME]\n", argv0); + printf("User-mode networking for unprivileged network namespaces.\n\n"); + printf("-c, --configure bring up the interface\n"); + printf("-e, --exit-fd=FD specify the FD for terminating " +@@ -461,8 +456,8 @@ static void usage(const char *argv0) + printf("--disable-host-loopback prohibit connecting to 127.0.0.1:* on the " + "host namespace\n"); + /* v0.4.0 */ +- printf("--netns-type=TYPE specify network namespace type ([path|pid], " +- "default=%s)\n", ++ printf("--netns-type=TYPE specify network namespace type " ++ "([path|pid|tapfd], default=%s)\n", + DEFAULT_NETNS_TYPE); + printf("--userns-path=PATH specify user namespace path\n"); + printf( +@@ -532,6 +527,7 @@ struct options { + char *macaddress; // --macaddress + char *target_type; // --target-type + char *bess_socket; // argv[1] (When --target-type="bess") ++ int tapfd; // argv[1] (When --netns-type="tapfd") + }; + + static void options_init(struct options *options) +@@ -539,6 +535,7 @@ static void options_init(struct options *options) + memset(options, 0, sizeof(*options)); + options->exit_fd = options->ready_fd = -1; + options->mtu = DEFAULT_MTU; ++ options->tapfd = -1; + } + + static void options_destroy(struct options *options) +@@ -828,13 +825,9 @@ static void parse_args(int argc, char *const argv[], struct options *options) + fprintf(stderr, "--target-type must be either \"netns\" or \"bess\"\n"); + goto error; + } +- if (argc - optind < 2) { ++ if (argc - optind < 1) { + goto error; + } +- if (argc - optind > 2) { +- // not an error, for preventing potential compatibility issue +- printf("WARNING: too many arguments\n"); +- } + if (!options->netns_type || + strcmp(options->netns_type, DEFAULT_NETNS_TYPE) == 0) { + errno = 0; +@@ -843,6 +836,14 @@ static void parse_args(int argc, char *const argv[], struct options *options) + fprintf(stderr, "PID must be a positive integer\n"); + goto error; + } ++ } else if (options->netns_type && ++ strcmp(options->netns_type, "tapfd") == 0) { ++ errno = 0; ++ options->tapfd = strtol(argv[optind], &strtol_e, 10); ++ if (errno || *strtol_e != '\0' || options->tapfd < 0) { ++ fprintf(stderr, "TAPFD must a file descriptor\n"); ++ goto error; ++ } + } else { + options->netns_path = strdup(argv[optind]); + if (access(options->netns_path, F_OK) == -1) { +@@ -850,7 +851,21 @@ static void parse_args(int argc, char *const argv[], struct options *options) + goto error; + } + } +- options->tapname = strdup(argv[optind + 1]); ++ if (options->tapfd >= 0) { ++ if (argc - optind > 1) { ++ // not an error, for preventing potential compatibility issue ++ printf("WARNING: too many arguments\n"); ++ } ++ } else { ++ if (argc - optind < 2) { ++ goto error; ++ } ++ if (argc - optind > 2) { ++ // not an error, for preventing potential compatibility issue ++ printf("WARNING: too many arguments\n"); ++ } ++ options->tapname = strdup(argv[optind + 1]); ++ } + return; + error: + usage(argv[0]); +@@ -1114,7 +1129,7 @@ static int slirp4netns_config_from_options(struct slirp4netns_config *cfg, + int main(int argc, char *const argv[]) + { + int sv[2]; +- pid_t child_pid; ++ pid_t child_pid = -1; + struct options options; + struct slirp4netns_config slirp4netns_config; + int exit_status = 0; +@@ -1129,11 +1144,12 @@ int main(int argc, char *const argv[]) + exit_status = EXIT_FAILURE; + goto finish; + } +- if ((child_pid = fork()) < 0) { +- perror("fork"); +- exit_status = EXIT_FAILURE; +- goto finish; +- } ++ if (options.tapfd < 0) ++ if ((child_pid = fork()) < 0) { ++ perror("fork"); ++ exit_status = EXIT_FAILURE; ++ goto finish; ++ } + if (child_pid == 0) { + int ret; + if (options.target_type != NULL && +@@ -1149,28 +1165,40 @@ int main(int argc, char *const argv[]) + goto finish; + } + } else { +- int ret, child_wstatus, child_status; +- do +- ret = waitpid(child_pid, &child_wstatus, 0); +- while (ret < 0 && errno == EINTR); +- if (ret < 0) { +- perror("waitpid"); +- exit_status = EXIT_FAILURE; +- goto finish; +- } +- if (!WIFEXITED(child_wstatus)) { +- fprintf(stderr, "child failed(wstatus=%d, !WIFEXITED)\n", +- child_wstatus); +- exit_status = EXIT_FAILURE; +- goto finish; +- } +- child_status = WEXITSTATUS(child_wstatus); +- if (child_status != 0) { +- fprintf(stderr, "child failed(%d)\n", child_status); +- exit_status = child_status; +- goto finish; ++ int tapfd; ++ if (options.tapfd >= 0) { ++ tapfd = options.tapfd; ++ } else { ++ int ret, child_wstatus, child_status; ++ do ++ ret = waitpid(child_pid, &child_wstatus, 0); ++ while (ret < 0 && errno == EINTR); ++ if (ret < 0) { ++ perror("waitpid"); ++ exit_status = EXIT_FAILURE; ++ goto finish; ++ } ++ if (!WIFEXITED(child_wstatus)) { ++ fprintf(stderr, "child failed(wstatus=%d, !WIFEXITED)\n", ++ child_wstatus); ++ exit_status = EXIT_FAILURE; ++ goto finish; ++ } ++ child_status = WEXITSTATUS(child_wstatus); ++ if (child_status != 0) { ++ fprintf(stderr, "child failed(%d)\n", child_status); ++ exit_status = child_status; ++ goto finish; ++ } ++ if ((tapfd = recvfd(sv[0])) < 0) { ++ fprintf(stderr, "failed to receive tapfd from child\n"); ++ exit_status = EXIT_FAILURE; ++ goto finish; ++ } ++ fprintf(stderr, "received tapfd=%d\n", tapfd); ++ close(sv[0]); + } +- if (parent(sv[0], options.ready_fd, options.exit_fd, options.api_socket, ++ if (parent(tapfd, options.ready_fd, options.exit_fd, options.api_socket, + &slirp4netns_config, options.target_pid) < 0) { + fprintf(stderr, "parent failed\n"); + exit_status = EXIT_FAILURE; +diff --git a/slirp4netns.1 b/slirp4netns.1 +index 136a676..1cb2fe5 100644 +--- a/slirp4netns.1 ++++ b/slirp4netns.1 +@@ -8,7 +8,7 @@ slirp4netns \- User\-mode networking for unprivileged network namespaces + + .SH SYNOPSIS + .PP +-slirp4netns [OPTION]... PID|PATH [TAPNAME] ++slirp4netns [OPTION]... PID|PATH|FD [TAPNAME] + + + .SH DESCRIPTION +@@ -84,7 +84,10 @@ prohibit connecting to 127.0.0.1:* on the host namespace + + .PP + \fB\fC\-\-netns\-type=TYPE\fR (since v0.4.0) +-specify network namespace type ([path|pid], default=pid) ++specify network namespace type ([path|pid|tapfd], default=pid) ++ ++If the namespace type is tapfd, the first positional argument is expected to be an inherited file descriptor that corresponds to a \fB\fC/dev/net/tun\fR connection. ++This conflicts with \fB\fC\-\-configure\fR and a \fB\fcTAPNAME\fR is ignored. + + .PP + \fB\fC\-\-userns\-path=PATH\fR (since v0.4.0) diff --minimal -Nru slirp4netns-1.2.1/debian/patches/series slirp4netns-1.2.1/debian/patches/series --- slirp4netns-1.2.1/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ slirp4netns-1.2.1/debian/patches/series 2025-04-11 21:12:07.000000000 +0200 @@ -0,0 +1 @@ +netns_type_tapfd.patch