typedef struct InterfaceParams {
char *host_interface_name;
char *namespace_interface_name;
+ unsigned interface_fd_index;
} InterfaceParams;
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,
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 = {};
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);
+}