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