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