+static int setup_veth(int netns_fd) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+ _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
+ char iface_name[IFNAMSIZ] = "ve-";
+ int r;
+
+ if (!arg_private_network)
+ return 0;
+
+ if (!arg_network_veth)
+ return 0;
+
+ strncpy(iface_name+3, arg_machine, sizeof(iface_name) - 3);
+
+ r = sd_rtnl_open(0, &rtnl);
+ if (r < 0) {
+ log_error("Failed to connect to netlink: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_new_link(RTM_NEWLINK, 0, &m);
+ if (r < 0) {
+ log_error("Failed to allocate netlink message: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_string(m, IFLA_IFNAME, "host0");
+ if (r < 0) {
+ log_error("Failed to append netlink kind: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_open_container(m, IFLA_LINKINFO, 0);
+ if (r < 0) {
+ log_error("Failed to open netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "veth");
+ if (r < 0) {
+ log_error("Failed to append netlink kind: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_open_container(m, IFLA_INFO_DATA, 0);
+ if (r < 0) {
+ log_error("Failed to open netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_open_container(m, VETH_INFO_PEER, sizeof(struct ifinfomsg));
+ if (r < 0) {
+ log_error("z Failed to open netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_string(m, IFLA_IFNAME, iface_name);
+ if (r < 0) {
+ log_error("Failed to append netlink kind: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_u32(m, IFLA_NET_NS_FD, netns_fd);
+ if (r < 0) {
+ log_error("Failed to add netlink namespace field: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_close_container(m);
+ if (r < 0) {
+ log_error("Failed to close netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_close_container(m);
+ if (r < 0) {
+ log_error("Failed to close netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_close_container(m);
+ if (r < 0) {
+ log_error("Failed to close netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_call(rtnl, m, 0, NULL);
+ if (r < 0) {
+ log_error("Failed to add new veth interfaces: %s", strerror(-r));
+ return r;
+ }
+
+ return 0;
+}
+
+static int move_network_interfaces(pid_t pid) {
+ _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
+ char **i;
+ int r;
+
+ if (!arg_private_network)
+ return 0;
+
+ if (strv_isempty(arg_network_interfaces))
+ return 0;
+
+ r = sd_rtnl_open(0, &rtnl);
+ if (r < 0) {
+ log_error("Failed to connect to netlink: %s", strerror(-r));
+ return r;
+ }
+
+ udev = udev_new();
+ if (!udev) {
+ log_error("Failed to connect to udev.");
+ return -ENOMEM;
+ }
+
+ STRV_FOREACH(i, arg_network_interfaces) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ char ifi_str[2 + DECIMAL_STR_MAX(int)];
+ int ifi;
+
+ ifi = (int) if_nametoindex(*i);
+ if (ifi <= 0) {
+ log_error("Failed to resolve interface %s: %m", *i);
+ return -errno;
+ }
+
+ sprintf(ifi_str, "n%i", ifi);
+ d = udev_device_new_from_device_id(udev, ifi_str);
+ if (!d) {
+ log_error("Failed to get udev device for interface %s: %m", *i);
+ return -errno;
+ }
+
+ if (udev_device_get_is_initialized(d) <= 0) {
+ log_error("Network interface %s is not initialized yet.", *i);
+ return -EBUSY;
+ }
+
+ r = sd_rtnl_message_new_link(RTM_NEWLINK, ifi, &m);
+ if (r < 0) {
+ log_error("Failed to allocate netlink message: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_u32(m, IFLA_NET_NS_PID, pid);
+ if (r < 0) {
+ log_error("Failed to append namespace PID to netlink message: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_call(rtnl, m, 0, NULL);
+ if (r < 0) {
+ log_error("Failed to move interface %s to namespace: %s", *i, strerror(-r));
+ return r;
+ }
+ }
+
+ return 0;
+}
+