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