Home | History | Annotate | Download | only in ip
      1 #define _ATFILE_SOURCE
      2 #include <sys/types.h>
      3 #include <sys/stat.h>
      4 #include <sys/wait.h>
      5 #include <sys/inotify.h>
      6 #include <sys/mount.h>
      7 #include <sys/syscall.h>
      8 #include <stdio.h>
      9 #include <string.h>
     10 #include <sched.h>
     11 #include <fcntl.h>
     12 #include <dirent.h>
     13 #include <errno.h>
     14 #include <unistd.h>
     15 #include <ctype.h>
     16 #include <linux/limits.h>
     17 
     18 #include <linux/net_namespace.h>
     19 
     20 #include "utils.h"
     21 #include "hlist.h"
     22 #include "ip_common.h"
     23 #include "namespace.h"
     24 
     25 static int usage(void)
     26 {
     27 	fprintf(stderr, "Usage: ip netns list\n");
     28 	fprintf(stderr, "       ip netns add NAME\n");
     29 	fprintf(stderr, "       ip netns set NAME NETNSID\n");
     30 	fprintf(stderr, "       ip [-all] netns delete [NAME]\n");
     31 	fprintf(stderr, "       ip netns identify [PID]\n");
     32 	fprintf(stderr, "       ip netns pids NAME\n");
     33 	fprintf(stderr, "       ip [-all] netns exec [NAME] cmd ...\n");
     34 	fprintf(stderr, "       ip netns monitor\n");
     35 	fprintf(stderr, "       ip netns list-id\n");
     36 	exit(-1);
     37 }
     38 
     39 /* This socket is used to get nsid */
     40 static struct rtnl_handle rtnsh = { .fd = -1 };
     41 
     42 static int have_rtnl_getnsid = -1;
     43 
     44 static int ipnetns_accept_msg(const struct sockaddr_nl *who,
     45 			      struct rtnl_ctrl_data *ctrl,
     46 			      struct nlmsghdr *n, void *arg)
     47 {
     48 	struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
     49 
     50 	if (n->nlmsg_type == NLMSG_ERROR &&
     51 	    (err->error == -EOPNOTSUPP || err->error == -EINVAL))
     52 		have_rtnl_getnsid = 0;
     53 	else
     54 		have_rtnl_getnsid = 1;
     55 	return -1;
     56 }
     57 
     58 static int ipnetns_have_nsid(void)
     59 {
     60 	struct {
     61 		struct nlmsghdr n;
     62 		struct rtgenmsg g;
     63 		char            buf[1024];
     64 	} req;
     65 	int fd;
     66 
     67 	if (have_rtnl_getnsid < 0) {
     68 		memset(&req, 0, sizeof(req));
     69 		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
     70 		req.n.nlmsg_flags = NLM_F_REQUEST;
     71 		req.n.nlmsg_type = RTM_GETNSID;
     72 		req.g.rtgen_family = AF_UNSPEC;
     73 
     74 		fd = open("/proc/self/ns/net", O_RDONLY);
     75 		if (fd < 0) {
     76 			perror("open(\"/proc/self/ns/net\")");
     77 			exit(1);
     78 		}
     79 
     80 		addattr32(&req.n, 1024, NETNSA_FD, fd);
     81 
     82 		if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
     83 			perror("request send failed");
     84 			exit(1);
     85 		}
     86 		rtnl_listen(&rth, ipnetns_accept_msg, NULL);
     87 		close(fd);
     88 	}
     89 
     90 	return have_rtnl_getnsid;
     91 }
     92 
     93 static int get_netnsid_from_name(const char *name)
     94 {
     95 	struct {
     96 		struct nlmsghdr n;
     97 		struct rtgenmsg g;
     98 		char            buf[1024];
     99 	} req, answer;
    100 	struct rtattr *tb[NETNSA_MAX + 1];
    101 	struct rtgenmsg *rthdr;
    102 	int len, fd;
    103 
    104 	memset(&req, 0, sizeof(req));
    105 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
    106 	req.n.nlmsg_flags = NLM_F_REQUEST;
    107 	req.n.nlmsg_type = RTM_GETNSID;
    108 	req.g.rtgen_family = AF_UNSPEC;
    109 
    110 	fd = netns_get_fd(name);
    111 	if (fd < 0)
    112 		return fd;
    113 
    114 	addattr32(&req.n, 1024, NETNSA_FD, fd);
    115 	if (rtnl_talk(&rtnsh, &req.n, &answer.n, sizeof(answer)) < 0) {
    116 		close(fd);
    117 		return -2;
    118 	}
    119 	close(fd);
    120 
    121 	/* Validate message and parse attributes */
    122 	if (answer.n.nlmsg_type == NLMSG_ERROR)
    123 		return -1;
    124 
    125 	rthdr = NLMSG_DATA(&answer.n);
    126 	len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr));
    127 	if (len < 0)
    128 		return -1;
    129 
    130 	parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
    131 
    132 	if (tb[NETNSA_NSID])
    133 		return rta_getattr_u32(tb[NETNSA_NSID]);
    134 
    135 	return -1;
    136 }
    137 
    138 struct nsid_cache {
    139 	struct hlist_node	nsid_hash;
    140 	struct hlist_node	name_hash;
    141 	int			nsid;
    142 	char			name[0];
    143 };
    144 
    145 #define NSIDMAP_SIZE		128
    146 #define NSID_HASH_NSID(nsid)	(nsid & (NSIDMAP_SIZE - 1))
    147 #define NSID_HASH_NAME(name)	(namehash(name) & (NSIDMAP_SIZE - 1))
    148 
    149 static struct hlist_head	nsid_head[NSIDMAP_SIZE];
    150 static struct hlist_head	name_head[NSIDMAP_SIZE];
    151 
    152 static struct nsid_cache *netns_map_get_by_nsid(int nsid)
    153 {
    154 	uint32_t h = NSID_HASH_NSID(nsid);
    155 	struct hlist_node *n;
    156 
    157 	hlist_for_each(n, &nsid_head[h]) {
    158 		struct nsid_cache *c = container_of(n, struct nsid_cache,
    159 						    nsid_hash);
    160 		if (c->nsid == nsid)
    161 			return c;
    162 	}
    163 
    164 	return NULL;
    165 }
    166 
    167 static int netns_map_add(int nsid, const char *name)
    168 {
    169 	struct nsid_cache *c;
    170 	uint32_t h;
    171 
    172 	if (netns_map_get_by_nsid(nsid) != NULL)
    173 		return -EEXIST;
    174 
    175 	c = malloc(sizeof(*c) + strlen(name));
    176 	if (c == NULL) {
    177 		perror("malloc");
    178 		return -ENOMEM;
    179 	}
    180 	c->nsid = nsid;
    181 	strcpy(c->name, name);
    182 
    183 	h = NSID_HASH_NSID(nsid);
    184 	hlist_add_head(&c->nsid_hash, &nsid_head[h]);
    185 
    186 	h = NSID_HASH_NAME(name);
    187 	hlist_add_head(&c->name_hash, &name_head[h]);
    188 
    189 	return 0;
    190 }
    191 
    192 static void netns_map_del(struct nsid_cache *c)
    193 {
    194 	hlist_del(&c->name_hash);
    195 	hlist_del(&c->nsid_hash);
    196 	free(c);
    197 }
    198 
    199 void netns_map_init(void)
    200 {
    201 	static int initialized;
    202 	struct dirent *entry;
    203 	DIR *dir;
    204 	int nsid;
    205 
    206 	if (initialized || !ipnetns_have_nsid())
    207 		return;
    208 
    209 	if (rtnl_open(&rtnsh, 0) < 0) {
    210 		fprintf(stderr, "Cannot open rtnetlink\n");
    211 		exit(1);
    212 	}
    213 
    214 	dir = opendir(NETNS_RUN_DIR);
    215 	if (!dir)
    216 		return;
    217 
    218 	while ((entry = readdir(dir)) != NULL) {
    219 		if (strcmp(entry->d_name, ".") == 0)
    220 			continue;
    221 		if (strcmp(entry->d_name, "..") == 0)
    222 			continue;
    223 		nsid = get_netnsid_from_name(entry->d_name);
    224 
    225 		if (nsid >= 0)
    226 			netns_map_add(nsid, entry->d_name);
    227 	}
    228 	closedir(dir);
    229 	initialized = 1;
    230 }
    231 
    232 static int netns_get_name(int nsid, char *name)
    233 {
    234 	struct dirent *entry;
    235 	DIR *dir;
    236 	int id;
    237 
    238 	dir = opendir(NETNS_RUN_DIR);
    239 	if (!dir)
    240 		return -ENOENT;
    241 
    242 	while ((entry = readdir(dir)) != NULL) {
    243 		if (strcmp(entry->d_name, ".") == 0)
    244 			continue;
    245 		if (strcmp(entry->d_name, "..") == 0)
    246 			continue;
    247 		id = get_netnsid_from_name(entry->d_name);
    248 
    249 		if (nsid == id) {
    250 			strcpy(name, entry->d_name);
    251 			closedir(dir);
    252 			return 0;
    253 		}
    254 	}
    255 	closedir(dir);
    256 	return -ENOENT;
    257 }
    258 
    259 int print_nsid(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
    260 {
    261 	struct rtgenmsg *rthdr = NLMSG_DATA(n);
    262 	struct rtattr *tb[NETNSA_MAX+1];
    263 	int len = n->nlmsg_len;
    264 	FILE *fp = (FILE *)arg;
    265 	struct nsid_cache *c;
    266 	char name[NAME_MAX];
    267 	int nsid;
    268 
    269 	if (n->nlmsg_type != RTM_NEWNSID && n->nlmsg_type != RTM_DELNSID)
    270 		return 0;
    271 
    272 	len -= NLMSG_SPACE(sizeof(*rthdr));
    273 	if (len < 0) {
    274 		fprintf(stderr, "BUG: wrong nlmsg len %d in %s\n", len,
    275 			__func__);
    276 		return -1;
    277 	}
    278 
    279 	parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
    280 	if (tb[NETNSA_NSID] == NULL) {
    281 		fprintf(stderr, "BUG: NETNSA_NSID is missing %s\n", __func__);
    282 		return -1;
    283 	}
    284 
    285 	if (n->nlmsg_type == RTM_DELNSID)
    286 		fprintf(fp, "Deleted ");
    287 
    288 	nsid = rta_getattr_u32(tb[NETNSA_NSID]);
    289 	fprintf(fp, "nsid %u ", nsid);
    290 
    291 	c = netns_map_get_by_nsid(nsid);
    292 	if (c != NULL) {
    293 		fprintf(fp, "(iproute2 netns name: %s)", c->name);
    294 		netns_map_del(c);
    295 	}
    296 
    297 	/* During 'ip monitor nsid', no chance to have new nsid in cache. */
    298 	if (c == NULL && n->nlmsg_type == RTM_NEWNSID)
    299 		if (netns_get_name(nsid, name) == 0) {
    300 			fprintf(fp, "(iproute2 netns name: %s)", name);
    301 			netns_map_add(nsid, name);
    302 		}
    303 
    304 	fprintf(fp, "\n");
    305 	fflush(fp);
    306 	return 0;
    307 }
    308 
    309 static int netns_list_id(int argc, char **argv)
    310 {
    311 	if (!ipnetns_have_nsid()) {
    312 		fprintf(stderr,
    313 			"RTM_GETNSID is not supported by the kernel.\n");
    314 		return -ENOTSUP;
    315 	}
    316 
    317 	if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETNSID) < 0) {
    318 		perror("Cannot send dump request");
    319 		exit(1);
    320 	}
    321 	if (rtnl_dump_filter(&rth, print_nsid, stdout) < 0) {
    322 		fprintf(stderr, "Dump terminated\n");
    323 		exit(1);
    324 	}
    325 	return 0;
    326 }
    327 
    328 static int netns_list(int argc, char **argv)
    329 {
    330 	struct dirent *entry;
    331 	DIR *dir;
    332 	int id;
    333 
    334 	dir = opendir(NETNS_RUN_DIR);
    335 	if (!dir)
    336 		return 0;
    337 
    338 	while ((entry = readdir(dir)) != NULL) {
    339 		if (strcmp(entry->d_name, ".") == 0)
    340 			continue;
    341 		if (strcmp(entry->d_name, "..") == 0)
    342 			continue;
    343 		printf("%s", entry->d_name);
    344 		if (ipnetns_have_nsid()) {
    345 			id = get_netnsid_from_name(entry->d_name);
    346 			if (id >= 0)
    347 				printf(" (id: %d)", id);
    348 		}
    349 		printf("\n");
    350 	}
    351 	closedir(dir);
    352 	return 0;
    353 }
    354 
    355 static int cmd_exec(const char *cmd, char **argv, bool do_fork)
    356 {
    357 	fflush(stdout);
    358 	if (do_fork) {
    359 		int status;
    360 		pid_t pid;
    361 
    362 		pid = fork();
    363 		if (pid < 0) {
    364 			perror("fork");
    365 			exit(1);
    366 		}
    367 
    368 		if (pid != 0) {
    369 			/* Parent  */
    370 			if (waitpid(pid, &status, 0) < 0) {
    371 				perror("waitpid");
    372 				exit(1);
    373 			}
    374 
    375 			if (WIFEXITED(status)) {
    376 				return WEXITSTATUS(status);
    377 			}
    378 
    379 			exit(1);
    380 		}
    381 	}
    382 
    383 	if (execvp(cmd, argv)  < 0)
    384 		fprintf(stderr, "exec of \"%s\" failed: %s\n",
    385 				cmd, strerror(errno));
    386 	_exit(1);
    387 }
    388 
    389 static int on_netns_exec(char *nsname, void *arg)
    390 {
    391 	char **argv = arg;
    392 	cmd_exec(argv[1], argv + 1, true);
    393 	return 0;
    394 }
    395 
    396 static int netns_exec(int argc, char **argv)
    397 {
    398 	/* Setup the proper environment for apps that are not netns
    399 	 * aware, and execute a program in that environment.
    400 	 */
    401 	const char *cmd;
    402 
    403 	if (argc < 1 && !do_all) {
    404 		fprintf(stderr, "No netns name specified\n");
    405 		return -1;
    406 	}
    407 	if ((argc < 2 && !do_all) || (argc < 1 && do_all)) {
    408 		fprintf(stderr, "No command specified\n");
    409 		return -1;
    410 	}
    411 
    412 	if (do_all)
    413 		return do_each_netns(on_netns_exec, --argv, 1);
    414 
    415 	if (netns_switch(argv[0]))
    416 		return -1;
    417 
    418 	/* ip must return the status of the child,
    419 	 * but do_cmd() will add a minus to this,
    420 	 * so let's add another one here to cancel it.
    421 	 */
    422 	cmd = argv[1];
    423 	return -cmd_exec(cmd, argv + 1, !!batch_mode);
    424 }
    425 
    426 static int is_pid(const char *str)
    427 {
    428 	int ch;
    429 	for (; (ch = *str); str++) {
    430 		if (!isdigit(ch))
    431 			return 0;
    432 	}
    433 	return 1;
    434 }
    435 
    436 static int netns_pids(int argc, char **argv)
    437 {
    438 	const char *name;
    439 	char net_path[PATH_MAX];
    440 	int netns;
    441 	struct stat netst;
    442 	DIR *dir;
    443 	struct dirent *entry;
    444 
    445 	if (argc < 1) {
    446 		fprintf(stderr, "No netns name specified\n");
    447 		return -1;
    448 	}
    449 	if (argc > 1) {
    450 		fprintf(stderr, "extra arguments specified\n");
    451 		return -1;
    452 	}
    453 
    454 	name = argv[0];
    455 	snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
    456 	netns = open(net_path, O_RDONLY);
    457 	if (netns < 0) {
    458 		fprintf(stderr, "Cannot open network namespace: %s\n",
    459 			strerror(errno));
    460 		return -1;
    461 	}
    462 	if (fstat(netns, &netst) < 0) {
    463 		fprintf(stderr, "Stat of netns failed: %s\n",
    464 			strerror(errno));
    465 		return -1;
    466 	}
    467 	dir = opendir("/proc/");
    468 	if (!dir) {
    469 		fprintf(stderr, "Open of /proc failed: %s\n",
    470 			strerror(errno));
    471 		return -1;
    472 	}
    473 	while((entry = readdir(dir))) {
    474 		char pid_net_path[PATH_MAX];
    475 		struct stat st;
    476 		if (!is_pid(entry->d_name))
    477 			continue;
    478 		snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%s/ns/net",
    479 			entry->d_name);
    480 		if (stat(pid_net_path, &st) != 0)
    481 			continue;
    482 		if ((st.st_dev == netst.st_dev) &&
    483 		    (st.st_ino == netst.st_ino)) {
    484 			printf("%s\n", entry->d_name);
    485 		}
    486 	}
    487 	closedir(dir);
    488 	return 0;
    489 
    490 }
    491 
    492 static int netns_identify(int argc, char **argv)
    493 {
    494 	const char *pidstr;
    495 	char net_path[PATH_MAX];
    496 	int netns;
    497 	struct stat netst;
    498 	DIR *dir;
    499 	struct dirent *entry;
    500 
    501 	if (argc < 1) {
    502 		pidstr = "self";
    503 	} else if (argc > 1) {
    504 		fprintf(stderr, "extra arguments specified\n");
    505 		return -1;
    506 	} else {
    507 		pidstr = argv[0];
    508 		if (!is_pid(pidstr)) {
    509 			fprintf(stderr, "Specified string '%s' is not a pid\n",
    510 					pidstr);
    511 			return -1;
    512 		}
    513 	}
    514 
    515 	snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr);
    516 	netns = open(net_path, O_RDONLY);
    517 	if (netns < 0) {
    518 		fprintf(stderr, "Cannot open network namespace: %s\n",
    519 			strerror(errno));
    520 		return -1;
    521 	}
    522 	if (fstat(netns, &netst) < 0) {
    523 		fprintf(stderr, "Stat of netns failed: %s\n",
    524 			strerror(errno));
    525 		return -1;
    526 	}
    527 	dir = opendir(NETNS_RUN_DIR);
    528 	if (!dir) {
    529 		/* Succeed treat a missing directory as an empty directory */
    530 		if (errno == ENOENT)
    531 			return 0;
    532 
    533 		fprintf(stderr, "Failed to open directory %s:%s\n",
    534 			NETNS_RUN_DIR, strerror(errno));
    535 		return -1;
    536 	}
    537 
    538 	while((entry = readdir(dir))) {
    539 		char name_path[PATH_MAX];
    540 		struct stat st;
    541 
    542 		if (strcmp(entry->d_name, ".") == 0)
    543 			continue;
    544 		if (strcmp(entry->d_name, "..") == 0)
    545 			continue;
    546 
    547 		snprintf(name_path, sizeof(name_path), "%s/%s",	NETNS_RUN_DIR,
    548 			entry->d_name);
    549 
    550 		if (stat(name_path, &st) != 0)
    551 			continue;
    552 
    553 		if ((st.st_dev == netst.st_dev) &&
    554 		    (st.st_ino == netst.st_ino)) {
    555 			printf("%s\n", entry->d_name);
    556 		}
    557 	}
    558 	closedir(dir);
    559 	return 0;
    560 
    561 }
    562 
    563 static int on_netns_del(char *nsname, void *arg)
    564 {
    565 	char netns_path[PATH_MAX];
    566 
    567 	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, nsname);
    568 	umount2(netns_path, MNT_DETACH);
    569 	if (unlink(netns_path) < 0) {
    570 		fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
    571 			netns_path, strerror(errno));
    572 		return -1;
    573 	}
    574 	return 0;
    575 }
    576 
    577 static int netns_delete(int argc, char **argv)
    578 {
    579 	if (argc < 1 && !do_all) {
    580 		fprintf(stderr, "No netns name specified\n");
    581 		return -1;
    582 	}
    583 
    584 	if (do_all)
    585 		return netns_foreach(on_netns_del, NULL);
    586 
    587 	return on_netns_del(argv[0], NULL);
    588 }
    589 
    590 static int create_netns_dir(void)
    591 {
    592 	/* Create the base netns directory if it doesn't exist */
    593 	if (mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
    594 		if (errno != EEXIST) {
    595 			fprintf(stderr, "mkdir %s failed: %s\n",
    596 				NETNS_RUN_DIR, strerror(errno));
    597 			return -1;
    598 		}
    599 	}
    600 
    601 	return 0;
    602 }
    603 
    604 static int netns_add(int argc, char **argv)
    605 {
    606 	/* This function creates a new network namespace and
    607 	 * a new mount namespace and bind them into a well known
    608 	 * location in the filesystem based on the name provided.
    609 	 *
    610 	 * The mount namespace is created so that any necessary
    611 	 * userspace tweaks like remounting /sys, or bind mounting
    612 	 * a new /etc/resolv.conf can be shared between uers.
    613 	 */
    614 	char netns_path[PATH_MAX];
    615 	const char *name;
    616 	int fd;
    617 	int made_netns_run_dir_mount = 0;
    618 
    619 	if (argc < 1) {
    620 		fprintf(stderr, "No netns name specified\n");
    621 		return -1;
    622 	}
    623 	name = argv[0];
    624 
    625 	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
    626 
    627 	if (create_netns_dir())
    628 		return -1;
    629 
    630 	/* Make it possible for network namespace mounts to propagate between
    631 	 * mount namespaces.  This makes it likely that a unmounting a network
    632 	 * namespace file in one namespace will unmount the network namespace
    633 	 * file in all namespaces allowing the network namespace to be freed
    634 	 * sooner.
    635 	 */
    636 	while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) {
    637 		/* Fail unless we need to make the mount point */
    638 		if (errno != EINVAL || made_netns_run_dir_mount) {
    639 			fprintf(stderr, "mount --make-shared %s failed: %s\n",
    640 				NETNS_RUN_DIR, strerror(errno));
    641 			return -1;
    642 		}
    643 
    644 		/* Upgrade NETNS_RUN_DIR to a mount point */
    645 		if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND, NULL)) {
    646 			fprintf(stderr, "mount --bind %s %s failed: %s\n",
    647 				NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
    648 			return -1;
    649 		}
    650 		made_netns_run_dir_mount = 1;
    651 	}
    652 
    653 	/* Create the filesystem state */
    654 	fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
    655 	if (fd < 0) {
    656 		fprintf(stderr, "Cannot create namespace file \"%s\": %s\n",
    657 			netns_path, strerror(errno));
    658 		return -1;
    659 	}
    660 	close(fd);
    661 	if (unshare(CLONE_NEWNET) < 0) {
    662 		fprintf(stderr, "Failed to create a new network namespace \"%s\": %s\n",
    663 			name, strerror(errno));
    664 		goto out_delete;
    665 	}
    666 
    667 	/* Bind the netns last so I can watch for it */
    668 	if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0) {
    669 		fprintf(stderr, "Bind /proc/self/ns/net -> %s failed: %s\n",
    670 			netns_path, strerror(errno));
    671 		goto out_delete;
    672 	}
    673 	return 0;
    674 out_delete:
    675 	netns_delete(argc, argv);
    676 	return -1;
    677 }
    678 
    679 static int set_netnsid_from_name(const char *name, int nsid)
    680 {
    681 	struct {
    682 		struct nlmsghdr n;
    683 		struct rtgenmsg g;
    684 		char            buf[1024];
    685 	} req;
    686 	int fd, err = 0;
    687 
    688 	memset(&req, 0, sizeof(req));
    689 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
    690 	req.n.nlmsg_flags = NLM_F_REQUEST;
    691 	req.n.nlmsg_type = RTM_NEWNSID;
    692 	req.g.rtgen_family = AF_UNSPEC;
    693 
    694 	fd = netns_get_fd(name);
    695 	if (fd < 0)
    696 		return fd;
    697 
    698 	addattr32(&req.n, 1024, NETNSA_FD, fd);
    699 	addattr32(&req.n, 1024, NETNSA_NSID, nsid);
    700 	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
    701 		err = -2;
    702 
    703 	close(fd);
    704 	return err;
    705 }
    706 
    707 static int netns_set(int argc, char **argv)
    708 {
    709 	char netns_path[PATH_MAX];
    710 	const char *name;
    711 	int netns, nsid;
    712 
    713 	if (argc < 1) {
    714 		fprintf(stderr, "No netns name specified\n");
    715 		return -1;
    716 	}
    717 	if (argc < 2) {
    718 		fprintf(stderr, "No nsid specified\n");
    719 		return -1;
    720 	}
    721 	name = argv[0];
    722 	nsid = atoi(argv[1]);
    723 
    724 	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
    725 	netns = open(netns_path, O_RDONLY | O_CLOEXEC);
    726 	if (netns < 0) {
    727 		fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
    728 			name, strerror(errno));
    729 		return -1;
    730 	}
    731 
    732 	return set_netnsid_from_name(name, nsid);
    733 }
    734 
    735 static int netns_monitor(int argc, char **argv)
    736 {
    737 	char buf[4096];
    738 	struct inotify_event *event;
    739 	int fd;
    740 	fd = inotify_init();
    741 	if (fd < 0) {
    742 		fprintf(stderr, "inotify_init failed: %s\n",
    743 			strerror(errno));
    744 		return -1;
    745 	}
    746 
    747 	if (create_netns_dir())
    748 		return -1;
    749 
    750 	if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) {
    751 		fprintf(stderr, "inotify_add_watch failed: %s\n",
    752 			strerror(errno));
    753 		return -1;
    754 	}
    755 	for(;;) {
    756 		ssize_t len = read(fd, buf, sizeof(buf));
    757 		if (len < 0) {
    758 			fprintf(stderr, "read failed: %s\n",
    759 				strerror(errno));
    760 			return -1;
    761 		}
    762 		for (event = (struct inotify_event *)buf;
    763 		     (char *)event < &buf[len];
    764 		     event = (struct inotify_event *)((char *)event + sizeof(*event) + event->len)) {
    765 			if (event->mask & IN_CREATE)
    766 				printf("add %s\n", event->name);
    767 			if (event->mask & IN_DELETE)
    768 				printf("delete %s\n", event->name);
    769 		}
    770 	}
    771 	return 0;
    772 }
    773 
    774 int do_netns(int argc, char **argv)
    775 {
    776 	netns_map_init();
    777 
    778 	if (argc < 1)
    779 		return netns_list(0, NULL);
    780 
    781 	if ((matches(*argv, "list") == 0) || (matches(*argv, "show") == 0) ||
    782 	    (matches(*argv, "lst") == 0))
    783 		return netns_list(argc-1, argv+1);
    784 
    785 	if ((matches(*argv, "list-id") == 0))
    786 		return netns_list_id(argc-1, argv+1);
    787 
    788 	if (matches(*argv, "help") == 0)
    789 		return usage();
    790 
    791 	if (matches(*argv, "add") == 0)
    792 		return netns_add(argc-1, argv+1);
    793 
    794 	if (matches(*argv, "set") == 0)
    795 		return netns_set(argc-1, argv+1);
    796 
    797 	if (matches(*argv, "delete") == 0)
    798 		return netns_delete(argc-1, argv+1);
    799 
    800 	if (matches(*argv, "identify") == 0)
    801 		return netns_identify(argc-1, argv+1);
    802 
    803 	if (matches(*argv, "pids") == 0)
    804 		return netns_pids(argc-1, argv+1);
    805 
    806 	if (matches(*argv, "exec") == 0)
    807 		return netns_exec(argc-1, argv+1);
    808 
    809 	if (matches(*argv, "monitor") == 0)
    810 		return netns_monitor(argc-1, argv+1);
    811 
    812 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv);
    813 	exit(-1);
    814 }
    815