+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;
+}
+