static bool create_nic(char *nic, char *br, int pid, char **cnic) { char *veth1buf, *veth2buf; veth1buf = alloca(IFNAMSIZ); veth2buf = alloca(IFNAMSIZ); int ret, mtu; ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic); if (ret < 0 || ret >= IFNAMSIZ) { fprintf(stderr, "host nic name too long\n"); return false; } /* create the nics */ if (instantiate_veth(veth1buf, &veth2buf) < 0) { fprintf(stderr, "Error creating veth tunnel\n"); return false; } if (strcmp(br, "none") != 0) { /* copy the bridge's mtu to both ends */ mtu = get_mtu(br); if (mtu != -1) { if (lxc_netdev_set_mtu(veth1buf, mtu) < 0 || lxc_netdev_set_mtu(veth2buf, mtu) < 0) { fprintf(stderr, "Failed setting mtu\n"); goto out_del; } } /* attach veth1 to bridge */ if (lxc_bridge_attach(lxcpath, lxcname, br, veth1buf) < 0) { fprintf(stderr, "Error attaching %s to %s\n", veth1buf, br); goto out_del; } } /* pass veth2 to target netns */ ret = lxc_netdev_move_by_name(veth2buf, pid, NULL); if (ret < 0) { fprintf(stderr, "Error moving %s to netns %d\n", veth2buf, pid); goto out_del; } *cnic = strdup(veth2buf); return true; out_del: lxc_netdev_delete_by_name(veth1buf); return false; }
static bool create_nic(char *nic, char *br, int pid, char **cnic) { char *veth1buf, *veth2buf; veth1buf = alloca(IFNAMSIZ); veth2buf = alloca(IFNAMSIZ); int ret; ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic); if (ret < 0 || ret >= IFNAMSIZ) { fprintf(stderr, "host nic name too long\n"); return false; } /* create the nics */ if (instanciate_veth(veth1buf, &veth2buf) < 0) { fprintf(stderr, "Error creating veth tunnel\n"); return false; } /* attach veth1 to bridge */ if (lxc_bridge_attach(br, veth1buf) < 0) { fprintf(stderr, "Error attaching %s to %s\n", veth1buf, br); goto out_del; } /* pass veth2 to target netns */ ret = lxc_netdev_move_by_name(veth2buf, pid); if (ret < 0) { fprintf(stderr, "Error moving %s to netns %d\n", veth2buf, pid); goto out_del; } *cnic = strdup(veth2buf); return true; out_del: lxc_netdev_delete_by_name(veth1buf); return false; }
static int create_nic(char *nic, char *br, int pid, char **cnic) { char veth1buf[IFNAMSIZ], veth2buf[IFNAMSIZ]; int mtu, ret; ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic); if (ret < 0 || ret >= IFNAMSIZ) { usernic_error("%s", "Could not create nic name\n"); return -1; } ret = snprintf(veth2buf, IFNAMSIZ, "%sp", veth1buf); if (ret < 0 || ret >= IFNAMSIZ) { usernic_error("%s\n", "Could not create nic name"); return -1; } /* create the nics */ ret = instantiate_veth(veth1buf, veth2buf); if (ret < 0) { usernic_error("%s", "Error creating veth tunnel\n"); return -1; } if (strcmp(br, "none")) { /* copy the bridge's mtu to both ends */ mtu = get_mtu(br); if (mtu > 0) { ret = lxc_netdev_set_mtu(veth1buf, mtu); if (ret < 0) { usernic_error("Failed to set mtu to %d on %s\n", mtu, veth1buf); goto out_del; } ret = lxc_netdev_set_mtu(veth2buf, mtu); if (ret < 0) { usernic_error("Failed to set mtu to %d on %s\n", mtu, veth2buf); goto out_del; } } /* attach veth1 to bridge */ ret = lxc_bridge_attach(br, veth1buf); if (ret < 0) { usernic_error("Error attaching %s to %s\n", veth1buf, br); goto out_del; } } /* pass veth2 to target netns */ ret = lxc_netdev_move_by_name(veth2buf, pid, NULL); if (ret < 0) { usernic_error("Error moving %s to network namespace of %d\n", veth2buf, pid); goto out_del; } *cnic = strdup(veth2buf); if (!*cnic) { usernic_error("Failed to copy string \"%s\"\n", veth2buf); return -1; } return 0; out_del: lxc_netdev_delete_by_name(veth1buf); return -1; }
int main(int argc, char *argv[]) { int opt, status; int ret; char *namespaces = NULL; char **args; int flags = 0; int daemonize = 0; uid_t uid = 0; /* valid only if (flags & CLONE_NEWUSER) */ pid_t pid; struct my_iflist *tmpif, *my_iflist = NULL; struct start_arg start_arg = { .args = &args, .uid = &uid, .setuid = false, .flags = &flags, .want_hostname = NULL, .want_default_mounts = 0, }; while ((opt = getopt(argc, argv, "s:u:hH:i:dM")) != -1) { switch (opt) { case 's': namespaces = optarg; break; case 'i': if (!(tmpif = malloc(sizeof(*tmpif)))) { perror("malloc"); exit(1); } tmpif->mi_ifname = optarg; tmpif->mi_next = my_iflist; my_iflist = tmpif; break; case 'd': daemonize = 1; break; case 'M': start_arg.want_default_mounts = 1; break; case 'H': start_arg.want_hostname = optarg; break; case 'h': usage(argv[0]); break; case 'u': if (!lookup_user(optarg, &uid)) return 1; start_arg.setuid = true; } } if (argv[optind] == NULL) { ERROR("a command to execute in the new namespace is required"); return 1; } args = &argv[optind]; ret = lxc_caps_init(); if (ret) return 1; ret = lxc_fill_namespace_flags(namespaces, &flags); if (ret) usage(argv[0]); if (!(flags & CLONE_NEWNET) && my_iflist) { ERROR("-i <interfacename> needs -s NETWORK option"); return 1; } if (!(flags & CLONE_NEWUTS) && start_arg.want_hostname) { ERROR("-H <hostname> needs -s UTSNAME option"); return 1; } if (!(flags & CLONE_NEWNS) && start_arg.want_default_mounts) { ERROR("-M needs -s MOUNT option"); return 1; } pid = lxc_clone(do_start, &start_arg, flags); if (pid < 0) { ERROR("failed to clone"); return 1; } if (my_iflist) { for (tmpif = my_iflist; tmpif; tmpif = tmpif->mi_next) { if (lxc_netdev_move_by_name(tmpif->mi_ifname, pid) < 0) fprintf(stderr,"Could not move interface %s into container %d: %s\n", tmpif->mi_ifname, pid, strerror(errno)); } } if (daemonize) exit(0); if (waitpid(pid, &status, 0) < 0) { ERROR("failed to wait for '%d'", pid); return 1; } return lxc_error_set_and_log(pid, status); }