]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nsresource: add client-side wrapper for creating tap links
authorLennart Poettering <lennart@poettering.net>
Mon, 10 Mar 2025 10:36:05 +0000 (11:36 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 17 Mar 2025 15:03:18 +0000 (16:03 +0100)
src/nspawn/nspawn.c
src/shared/nsresource.c
src/shared/nsresource.h

index e3c5d6b732700c6cb08c6a193619843a2d01fd11..87cae525ca870d1a93b06a2999294e3658b0d422 100644 (file)
@@ -5459,7 +5459,7 @@ static int run_container(
                         } else {
                                 _cleanup_free_ char *host_ifname = NULL;
 
-                                r = nsresource_add_netif(userns_fd, child_netns_fd, /* namespace_ifname= */ NULL, &host_ifname, /* ret_namespace_ifname= */ NULL);
+                                r = nsresource_add_netif_veth(userns_fd, child_netns_fd, /* namespace_ifname= */ NULL, &host_ifname, /* ret_namespace_ifname= */ NULL);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to add network interface to container: %m");
 
index 5c6792507e9346411f4a079c3f247fe73f16e3a8..2652d2a62458e2cc7adadf550559906c3cf83ddc 100644 (file)
@@ -257,6 +257,7 @@ int nsresource_add_cgroup(int userns_fd, int cgroup_fd) {
 typedef struct InterfaceParams {
         char *host_interface_name;
         char *namespace_interface_name;
+        unsigned interface_fd_index;
 } InterfaceParams;
 
 static void interface_params_done(InterfaceParams *p) {
@@ -266,7 +267,7 @@ static void interface_params_done(InterfaceParams *p) {
         free(p->namespace_interface_name);
 }
 
-int nsresource_add_netif(
+int nsresource_add_netif_veth(
                 int userns_fd,
                 int netns_fd,
                 const char *namespace_ifname,
@@ -330,8 +331,8 @@ int nsresource_add_netif(
                 return log_debug_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to add network to user namespace: %s", error_id);
 
         static const sd_json_dispatch_field dispatch_table[] = {
-                { "hostInterfaceName",      SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, host_interface_name),      0 },
-                { "namespaceInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, namespace_interface_name), 0 },
+                { "hostInterfaceName",      SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, host_interface_name),      SD_JSON_MANDATORY },
+                { "namespaceInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, namespace_interface_name), SD_JSON_MANDATORY },
         };
 
         _cleanup_(interface_params_done) InterfaceParams p = {};
@@ -346,3 +347,69 @@ int nsresource_add_netif(
 
         return 1;
 }
+
+int nsresource_add_netif_tap(
+                int userns_fd,
+                char **ret_host_ifname) {
+
+        _cleanup_close_ int _userns_fd = -EBADF;
+        _cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
+        int r, userns_fd_idx;
+        const char *error_id;
+
+        if (userns_fd < 0) {
+                _userns_fd = namespace_open_by_type(NAMESPACE_USER);
+                if (_userns_fd < 0)
+                        return _userns_fd;
+
+                userns_fd = _userns_fd;
+        }
+
+        r = sd_varlink_connect_address(&vl, "/run/systemd/io.systemd.NamespaceResource");
+        if (r < 0)
+                return log_debug_errno(r, "Failed to connect to namespace resource manager: %m");
+
+        r = sd_varlink_set_allow_fd_passing_output(vl, true);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to enable varlink fd passing for write: %m");
+
+        r = sd_varlink_set_allow_fd_passing_input(vl, true);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to enable varlink fd passing for read: %m");
+
+        userns_fd_idx = sd_varlink_push_dup_fd(vl, userns_fd);
+        if (userns_fd_idx < 0)
+                return log_debug_errno(userns_fd_idx, "Failed to push userns fd into varlink connection: %m");
+
+        sd_json_variant *reply = NULL;
+        r = sd_varlink_callbo(
+                        vl,
+                        "io.systemd.NamespaceResource.AddNetworkToUserNamespace",
+                        &reply,
+                        &error_id,
+                        SD_JSON_BUILD_PAIR("userNamespaceFileDescriptor", SD_JSON_BUILD_UNSIGNED(userns_fd_idx)),
+                        SD_JSON_BUILD_PAIR("mode", JSON_BUILD_CONST_STRING("tap")));
+        if (r < 0)
+                return log_debug_errno(r, "Failed to call AddNetworkToUserNamespace() varlink call: %m");
+        if (error_id)
+                return log_debug_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to add network to user namespace: %s", error_id);
+
+        static const sd_json_dispatch_field dispatch_table[] = {
+                { "hostInterfaceName",       SD_JSON_VARIANT_STRING,        sd_json_dispatch_string, offsetof(InterfaceParams, host_interface_name),      SD_JSON_MANDATORY },
+                { "interfaceFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint,   offsetof(InterfaceParams, namespace_interface_name), SD_JSON_MANDATORY },
+        };
+
+        _cleanup_(interface_params_done) InterfaceParams p = {};
+        r = sd_json_dispatch(reply, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
+        if (r < 0)
+                return r;
+
+        _cleanup_close_ int tap_fd = sd_varlink_take_fd(vl, p.interface_fd_index);
+        if (tap_fd < 0)
+                return tap_fd;
+
+        if (ret_host_ifname)
+                *ret_host_ifname = TAKE_PTR(p.host_interface_name);
+
+        return TAKE_FD(tap_fd);
+}
index 6b807b327bfff351bea4d398d850117d93be8813..48274fd1a53ca19ed4ceba168c990287c1f7ebb2 100644 (file)
@@ -7,4 +7,5 @@ int nsresource_allocate_userns(const char *name, uint64_t size);
 int nsresource_register_userns(const char *name, int userns_fd);
 int nsresource_add_mount(int userns_fd, int mount_fd);
 int nsresource_add_cgroup(int userns_fd, int cgroup_fd);
-int nsresource_add_netif(int userns_fd, int netns_fd, const char *namespace_ifname, char **ret_host_ifname, char **ret_namespace_ifname);
+int nsresource_add_netif_veth(int userns_fd, int netns_fd, const char *namespace_ifname, char **ret_host_ifname, char **ret_namespace_ifname);
+int nsresource_add_netif_tap(int userns_fd, char **ret_host_ifname);