]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn-network: split out move_back_network_interfaces()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 17 Jan 2024 00:28:31 +0000 (09:28 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 19 Jan 2024 10:05:25 +0000 (19:05 +0900)
No functional change, just refactoring and preparation for later
commits.

src/nspawn/nspawn-network.c
src/nspawn/nspawn-network.h
src/nspawn/nspawn.c

index 369d8742b60f0be1da0a9041d2ea29b4171ed0ea..de21c68a6db7172f698a18657b121577bb3d8d7e 100644 (file)
 
 #include "alloc-util.h"
 #include "ether-addr-util.h"
+#include "fd-util.h"
 #include "hexdecoct.h"
 #include "lock-util.h"
 #include "missing_network.h"
+#include "namespace-util.h"
 #include "netif-naming-scheme.h"
 #include "netlink-util.h"
 #include "nspawn-network.h"
 #include "parse-util.h"
+#include "process-util.h"
 #include "siphash24.h"
 #include "socket-netlink.h"
 #include "socket-util.h"
@@ -503,6 +506,58 @@ int test_network_interfaces_initialized(char **iface_pairs) {
         return 0;
 }
 
+static int netns_child_begin(int netns_fd, int *ret_original_netns_fd) {
+        _cleanup_close_ int original_netns_fd = -EBADF;
+        int r;
+
+        assert(netns_fd >= 0);
+
+        if (ret_original_netns_fd) {
+                r = namespace_open(0,
+                                   /* ret_pidns_fd = */ NULL,
+                                   /* ret_mntns_fd = */ NULL,
+                                   &original_netns_fd,
+                                   /* ret_userns_fd = */ NULL,
+                                   /* ret_root_fd = */ NULL);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to open original network namespace: %m");
+        }
+
+        r = namespace_enter(/* pidns_fd = */ -EBADF,
+                            /* mntns_fd = */ -EBADF,
+                            netns_fd,
+                            /* userns_fd = */ -EBADF,
+                            /* root_fd = */ -EBADF);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enter child network namespace: %m");
+
+        if (ret_original_netns_fd)
+                *ret_original_netns_fd = TAKE_FD(original_netns_fd);
+
+        return 0;
+}
+
+static int netns_fork_and_wait(int netns_fd, int *ret_original_netns_fd) {
+        int r;
+
+        assert(netns_fd >= 0);
+
+        r = safe_fork("(sd-netns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to fork process (sd-netns): %m");
+        if (r == 0) {
+                if (netns_child_begin(netns_fd, ret_original_netns_fd) < 0)
+                        _exit(EXIT_FAILURE);
+
+                return 0;
+        }
+
+        if (ret_original_netns_fd)
+                *ret_original_netns_fd = -EBADF;
+
+        return 1;
+}
+
 int move_network_interfaces(int netns_fd, char **iface_pairs) {
         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         int r;
@@ -544,6 +599,30 @@ int move_network_interfaces(int netns_fd, char **iface_pairs) {
         return 0;
 }
 
+int move_back_network_interfaces(int child_netns_fd, char **interface_pairs) {
+        _cleanup_close_ int parent_netns_fd = -EBADF;
+        int r;
+
+        assert(child_netns_fd >= 0);
+
+        if (strv_isempty(interface_pairs))
+                return 0;
+
+        r = netns_fork_and_wait(child_netns_fd, &parent_netns_fd);
+        if (r < 0)
+                return r;
+        if (r == 0) {
+                /* Reverse network interfaces pair list so that interfaces get their initial name back.
+                 * This is about ensuring interfaces get their old name back when being moved back. */
+                interface_pairs = strv_reverse(interface_pairs);
+
+                r = move_network_interfaces(parent_netns_fd, interface_pairs);
+                _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+        }
+
+        return 0;
+}
+
 int setup_macvlan(const char *machine_name, pid_t pid, char **iface_pairs) {
         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         unsigned idx = 0;
index a785f8ea42ffc9f81c9c88f626481eef4fe685bb..9729b6e37e799fd8a75954c451233ce8e60139bd 100644 (file)
@@ -19,6 +19,7 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **iface_pairs);
 int setup_ipvlan(const char *machine_name, pid_t pid, char **iface_pairs);
 
 int move_network_interfaces(int netns_fd, char **iface_pairs);
+int move_back_network_interfaces(int child_netns_fd, char **interface_pairs);
 
 int veth_extra_parse(char ***l, const char *p);
 
index 5dd3ff5549e4bf9c952c0339faa45ae011be1a96..445d85da6f071d682a0188a9c1b664ca57952438 100644 (file)
@@ -5377,46 +5377,9 @@ static int run_container(
         fd_kmsg_fifo = safe_close(fd_kmsg_fifo);
 
         if (arg_private_network) {
-                /* Move network interfaces back to the parent network namespace. We use `safe_fork`
-                 * to avoid having to move the parent to the child network namespace. */
-                r = safe_fork(NULL, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
+                r = move_back_network_interfaces(child_netns_fd, arg_network_interfaces);
                 if (r < 0)
                         return r;
-
-                if (r == 0) {
-                        _cleanup_close_ int parent_netns_fd = -EBADF;
-
-                        r = namespace_open(0,
-                                           /* ret_pidns_fd = */ NULL,
-                                           /* ret_mntns_fd = */ NULL,
-                                           &parent_netns_fd,
-                                           /* ret_userns_fd = */ NULL,
-                                           /* ret_root_fd = */ NULL);
-                        if (r < 0) {
-                                log_error_errno(r, "Failed to open parent network namespace: %m");
-                                _exit(EXIT_FAILURE);
-                        }
-
-                        r = namespace_enter(/* pidns_fd = */ -EBADF,
-                                            /* mntns_fd = */ -EBADF,
-                                            child_netns_fd,
-                                            /* userns_fd = */ -EBADF,
-                                            /* root_fd = */ -EBADF);
-                        if (r < 0) {
-                                log_error_errno(r, "Failed to enter child network namespace: %m");
-                                _exit(EXIT_FAILURE);
-                        }
-
-                        /* Reverse network interfaces pair list so that interfaces get their initial name back.
-                         * This is about ensuring interfaces get their old name back when being moved back. */
-                        arg_network_interfaces = strv_reverse(arg_network_interfaces);
-
-                        r = move_network_interfaces(parent_netns_fd, arg_network_interfaces);
-                        if (r < 0)
-                                log_error_errno(r, "Failed to move network interfaces back to parent network namespace: %m");
-
-                        _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
-                }
         }
 
         r = wait_for_container(TAKE_PID(*pid), &container_status);