nsresource: add client-side wrapper for creating tap links

This commit is contained in:
Lennart Poettering
2025-03-17 16:03:18 +01:00
parent 19ac01efef
commit 716bf93c4b
3 changed files with 73 additions and 5 deletions
+1 -1
View 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");
+70 -3
View 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);
}
+2 -1
View 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);