Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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);
}