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

Reply via email to