]>
git.proxmox.com Git - mirror_iproute2.git/blob - ip/ipnetns.c
5 #include <sys/inotify.h>
8 #include <sys/syscall.h>
17 #include <linux/limits.h>
19 #include <linux/net_namespace.h>
23 #include "ip_common.h"
24 #include "namespace.h"
26 static int usage(void)
28 fprintf(stderr
, "Usage: ip netns list\n");
29 fprintf(stderr
, " ip netns add NAME\n");
30 fprintf(stderr
, " ip netns set NAME NETNSID\n");
31 fprintf(stderr
, " ip [-all] netns delete [NAME]\n");
32 fprintf(stderr
, " ip netns identify [PID]\n");
33 fprintf(stderr
, " ip netns pids NAME\n");
34 fprintf(stderr
, " ip [-all] netns exec [NAME] cmd ...\n");
35 fprintf(stderr
, " ip netns monitor\n");
36 fprintf(stderr
, " ip netns list-id\n");
40 /* This socket is used to get nsid */
41 static struct rtnl_handle rtnsh
= { .fd
= -1 };
43 static int have_rtnl_getnsid
= -1;
45 static int ipnetns_accept_msg(const struct sockaddr_nl
*who
,
46 struct rtnl_ctrl_data
*ctrl
,
47 struct nlmsghdr
*n
, void *arg
)
49 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(n
);
51 if (n
->nlmsg_type
== NLMSG_ERROR
&&
52 (err
->error
== -EOPNOTSUPP
|| err
->error
== -EINVAL
))
53 have_rtnl_getnsid
= 0;
55 have_rtnl_getnsid
= 1;
59 static int ipnetns_have_nsid(void)
68 if (have_rtnl_getnsid
< 0) {
69 memset(&req
, 0, sizeof(req
));
70 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct rtgenmsg
));
71 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
72 req
.n
.nlmsg_type
= RTM_GETNSID
;
73 req
.g
.rtgen_family
= AF_UNSPEC
;
75 fd
= open("/proc/self/ns/net", O_RDONLY
);
77 perror("open(\"/proc/self/ns/net\")");
81 addattr32(&req
.n
, 1024, NETNSA_FD
, fd
);
83 if (rtnl_send(&rth
, &req
.n
, req
.n
.nlmsg_len
) < 0) {
84 perror("request send failed");
87 rtnl_listen(&rth
, ipnetns_accept_msg
, NULL
);
91 return have_rtnl_getnsid
;
94 static int get_netnsid_from_name(const char *name
)
101 struct rtattr
*tb
[NETNSA_MAX
+ 1];
102 struct rtgenmsg
*rthdr
;
105 memset(&req
, 0, sizeof(req
));
106 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct rtgenmsg
));
107 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
108 req
.n
.nlmsg_type
= RTM_GETNSID
;
109 req
.g
.rtgen_family
= AF_UNSPEC
;
111 fd
= netns_get_fd(name
);
115 addattr32(&req
.n
, 1024, NETNSA_FD
, fd
);
116 if (rtnl_talk(&rtnsh
, &req
.n
, &answer
.n
, sizeof(answer
)) < 0) {
122 /* Validate message and parse attributes */
123 if (answer
.n
.nlmsg_type
== NLMSG_ERROR
)
126 rthdr
= NLMSG_DATA(&answer
.n
);
127 len
= answer
.n
.nlmsg_len
- NLMSG_SPACE(sizeof(*rthdr
));
131 parse_rtattr(tb
, NETNSA_MAX
, NETNS_RTA(rthdr
), len
);
134 return rta_getattr_u32(tb
[NETNSA_NSID
]);
140 struct hlist_node nsid_hash
;
141 struct hlist_node name_hash
;
146 #define NSIDMAP_SIZE 128
147 #define NSID_HASH_NSID(nsid) (nsid & (NSIDMAP_SIZE - 1))
148 #define NSID_HASH_NAME(name) (namehash(name) & (NSIDMAP_SIZE - 1))
150 static struct hlist_head nsid_head
[NSIDMAP_SIZE
];
151 static struct hlist_head name_head
[NSIDMAP_SIZE
];
153 static struct nsid_cache
*netns_map_get_by_nsid(int nsid
)
155 uint32_t h
= NSID_HASH_NSID(nsid
);
156 struct hlist_node
*n
;
158 hlist_for_each(n
, &nsid_head
[h
]) {
159 struct nsid_cache
*c
= container_of(n
, struct nsid_cache
,
168 static int netns_map_add(int nsid
, char *name
)
170 struct nsid_cache
*c
;
173 if (netns_map_get_by_nsid(nsid
) != NULL
)
176 c
= malloc(sizeof(*c
));
182 strcpy(c
->name
, name
);
184 h
= NSID_HASH_NSID(nsid
);
185 hlist_add_head(&c
->nsid_hash
, &nsid_head
[h
]);
187 h
= NSID_HASH_NAME(name
);
188 hlist_add_head(&c
->name_hash
, &name_head
[h
]);
193 static void netns_map_del(struct nsid_cache
*c
)
195 hlist_del(&c
->name_hash
);
196 hlist_del(&c
->nsid_hash
);
200 void netns_map_init(void)
202 static int initialized
;
203 struct dirent
*entry
;
207 if (initialized
|| !ipnetns_have_nsid())
210 if (rtnl_open(&rtnsh
, 0) < 0) {
211 fprintf(stderr
, "Cannot open rtnetlink\n");
215 dir
= opendir(NETNS_RUN_DIR
);
219 while ((entry
= readdir(dir
)) != NULL
) {
220 if (strcmp(entry
->d_name
, ".") == 0)
222 if (strcmp(entry
->d_name
, "..") == 0)
224 nsid
= get_netnsid_from_name(entry
->d_name
);
227 netns_map_add(nsid
, entry
->d_name
);
233 static int netns_get_name(int nsid
, char *name
)
235 struct dirent
*entry
;
239 dir
= opendir(NETNS_RUN_DIR
);
243 while ((entry
= readdir(dir
)) != NULL
) {
244 if (strcmp(entry
->d_name
, ".") == 0)
246 if (strcmp(entry
->d_name
, "..") == 0)
248 id
= get_netnsid_from_name(entry
->d_name
);
251 strcpy(name
, entry
->d_name
);
260 int print_nsid(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
, void *arg
)
262 struct rtgenmsg
*rthdr
= NLMSG_DATA(n
);
263 struct rtattr
*tb
[NETNSA_MAX
+1];
264 int len
= n
->nlmsg_len
;
265 FILE *fp
= (FILE *)arg
;
266 struct nsid_cache
*c
;
270 if (n
->nlmsg_type
!= RTM_NEWNSID
&& n
->nlmsg_type
!= RTM_DELNSID
)
273 len
-= NLMSG_SPACE(sizeof(*rthdr
));
275 fprintf(stderr
, "BUG: wrong nlmsg len %d in %s\n", len
,
280 parse_rtattr(tb
, NETNSA_MAX
, NETNS_RTA(rthdr
), len
);
281 if (tb
[NETNSA_NSID
] == NULL
) {
282 fprintf(stderr
, "BUG: NETNSA_NSID is missing %s\n", __func__
);
286 if (n
->nlmsg_type
== RTM_DELNSID
)
287 fprintf(fp
, "Deleted ");
289 nsid
= rta_getattr_u32(tb
[NETNSA_NSID
]);
290 fprintf(fp
, "nsid %u ", nsid
);
292 c
= netns_map_get_by_nsid(nsid
);
294 fprintf(fp
, "(iproute2 netns name: %s)", c
->name
);
298 /* During 'ip monitor nsid', no chance to have new nsid in cache. */
299 if (c
== NULL
&& n
->nlmsg_type
== RTM_NEWNSID
)
300 if (netns_get_name(nsid
, name
) == 0) {
301 fprintf(fp
, "(iproute2 netns name: %s)", name
);
302 netns_map_add(nsid
, name
);
310 static int netns_list_id(int argc
, char **argv
)
312 if (!ipnetns_have_nsid()) {
314 "RTM_GETNSID is not supported by the kernel.\n");
318 if (rtnl_wilddump_request(&rth
, AF_UNSPEC
, RTM_GETNSID
) < 0) {
319 perror("Cannot send dump request");
322 if (rtnl_dump_filter(&rth
, print_nsid
, stdout
) < 0) {
323 fprintf(stderr
, "Dump terminated\n");
329 static int netns_list(int argc
, char **argv
)
331 struct dirent
*entry
;
335 dir
= opendir(NETNS_RUN_DIR
);
339 while ((entry
= readdir(dir
)) != NULL
) {
340 if (strcmp(entry
->d_name
, ".") == 0)
342 if (strcmp(entry
->d_name
, "..") == 0)
344 printf("%s", entry
->d_name
);
345 if (ipnetns_have_nsid()) {
346 id
= get_netnsid_from_name(entry
->d_name
);
348 printf(" (id: %d)", id
);
356 static int cmd_exec(const char *cmd
, char **argv
, bool do_fork
)
371 if (waitpid(pid
, &status
, 0) < 0) {
376 if (WIFEXITED(status
)) {
377 return WEXITSTATUS(status
);
384 if (execvp(cmd
, argv
) < 0)
385 fprintf(stderr
, "exec of \"%s\" failed: %s\n",
386 cmd
, strerror(errno
));
390 static int on_netns_exec(char *nsname
, void *arg
)
393 cmd_exec(argv
[1], argv
+ 1, true);
397 static int netns_exec(int argc
, char **argv
)
399 /* Setup the proper environment for apps that are not netns
400 * aware, and execute a program in that environment.
404 if (argc
< 1 && !do_all
) {
405 fprintf(stderr
, "No netns name specified\n");
408 if ((argc
< 2 && !do_all
) || (argc
< 1 && do_all
)) {
409 fprintf(stderr
, "No command specified\n");
414 return do_each_netns(on_netns_exec
, --argv
, 1);
416 if (netns_switch(argv
[0]))
419 /* ip must return the status of the child,
420 * but do_cmd() will add a minus to this,
421 * so let's add another one here to cancel it.
424 return -cmd_exec(cmd
, argv
+ 1, !!batch_mode
);
427 static int is_pid(const char *str
)
430 for (; (ch
= *str
); str
++) {
437 static int netns_pids(int argc
, char **argv
)
440 char net_path
[MAXPATHLEN
];
444 struct dirent
*entry
;
447 fprintf(stderr
, "No netns name specified\n");
451 fprintf(stderr
, "extra arguments specified\n");
456 snprintf(net_path
, sizeof(net_path
), "%s/%s", NETNS_RUN_DIR
, name
);
457 netns
= open(net_path
, O_RDONLY
);
459 fprintf(stderr
, "Cannot open network namespace: %s\n",
463 if (fstat(netns
, &netst
) < 0) {
464 fprintf(stderr
, "Stat of netns failed: %s\n",
468 dir
= opendir("/proc/");
470 fprintf(stderr
, "Open of /proc failed: %s\n",
474 while((entry
= readdir(dir
))) {
475 char pid_net_path
[MAXPATHLEN
];
477 if (!is_pid(entry
->d_name
))
479 snprintf(pid_net_path
, sizeof(pid_net_path
), "/proc/%s/ns/net",
481 if (stat(pid_net_path
, &st
) != 0)
483 if ((st
.st_dev
== netst
.st_dev
) &&
484 (st
.st_ino
== netst
.st_ino
)) {
485 printf("%s\n", entry
->d_name
);
493 static int netns_identify(int argc
, char **argv
)
496 char net_path
[MAXPATHLEN
];
500 struct dirent
*entry
;
504 } else if (argc
> 1) {
505 fprintf(stderr
, "extra arguments specified\n");
509 if (!is_pid(pidstr
)) {
510 fprintf(stderr
, "Specified string '%s' is not a pid\n",
516 snprintf(net_path
, sizeof(net_path
), "/proc/%s/ns/net", pidstr
);
517 netns
= open(net_path
, O_RDONLY
);
519 fprintf(stderr
, "Cannot open network namespace: %s\n",
523 if (fstat(netns
, &netst
) < 0) {
524 fprintf(stderr
, "Stat of netns failed: %s\n",
528 dir
= opendir(NETNS_RUN_DIR
);
530 /* Succeed treat a missing directory as an empty directory */
534 fprintf(stderr
, "Failed to open directory %s:%s\n",
535 NETNS_RUN_DIR
, strerror(errno
));
539 while((entry
= readdir(dir
))) {
540 char name_path
[MAXPATHLEN
];
543 if (strcmp(entry
->d_name
, ".") == 0)
545 if (strcmp(entry
->d_name
, "..") == 0)
548 snprintf(name_path
, sizeof(name_path
), "%s/%s", NETNS_RUN_DIR
,
551 if (stat(name_path
, &st
) != 0)
554 if ((st
.st_dev
== netst
.st_dev
) &&
555 (st
.st_ino
== netst
.st_ino
)) {
556 printf("%s\n", entry
->d_name
);
564 static int on_netns_del(char *nsname
, void *arg
)
566 char netns_path
[MAXPATHLEN
];
568 snprintf(netns_path
, sizeof(netns_path
), "%s/%s", NETNS_RUN_DIR
, nsname
);
569 umount2(netns_path
, MNT_DETACH
);
570 if (unlink(netns_path
) < 0) {
571 fprintf(stderr
, "Cannot remove namespace file \"%s\": %s\n",
572 netns_path
, strerror(errno
));
578 static int netns_delete(int argc
, char **argv
)
580 if (argc
< 1 && !do_all
) {
581 fprintf(stderr
, "No netns name specified\n");
586 return netns_foreach(on_netns_del
, NULL
);
588 return on_netns_del(argv
[0], NULL
);
591 static int create_netns_dir(void)
593 /* Create the base netns directory if it doesn't exist */
594 if (mkdir(NETNS_RUN_DIR
, S_IRWXU
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
)) {
595 if (errno
!= EEXIST
) {
596 fprintf(stderr
, "mkdir %s failed: %s\n",
597 NETNS_RUN_DIR
, strerror(errno
));
605 static int netns_add(int argc
, char **argv
)
607 /* This function creates a new network namespace and
608 * a new mount namespace and bind them into a well known
609 * location in the filesystem based on the name provided.
611 * The mount namespace is created so that any necessary
612 * userspace tweaks like remounting /sys, or bind mounting
613 * a new /etc/resolv.conf can be shared between uers.
615 char netns_path
[MAXPATHLEN
];
618 int made_netns_run_dir_mount
= 0;
621 fprintf(stderr
, "No netns name specified\n");
626 snprintf(netns_path
, sizeof(netns_path
), "%s/%s", NETNS_RUN_DIR
, name
);
628 if (create_netns_dir())
631 /* Make it possible for network namespace mounts to propagate between
632 * mount namespaces. This makes it likely that a unmounting a network
633 * namespace file in one namespace will unmount the network namespace
634 * file in all namespaces allowing the network namespace to be freed
637 while (mount("", NETNS_RUN_DIR
, "none", MS_SHARED
| MS_REC
, NULL
)) {
638 /* Fail unless we need to make the mount point */
639 if (errno
!= EINVAL
|| made_netns_run_dir_mount
) {
640 fprintf(stderr
, "mount --make-shared %s failed: %s\n",
641 NETNS_RUN_DIR
, strerror(errno
));
645 /* Upgrade NETNS_RUN_DIR to a mount point */
646 if (mount(NETNS_RUN_DIR
, NETNS_RUN_DIR
, "none", MS_BIND
, NULL
)) {
647 fprintf(stderr
, "mount --bind %s %s failed: %s\n",
648 NETNS_RUN_DIR
, NETNS_RUN_DIR
, strerror(errno
));
651 made_netns_run_dir_mount
= 1;
654 /* Create the filesystem state */
655 fd
= open(netns_path
, O_RDONLY
|O_CREAT
|O_EXCL
, 0);
657 fprintf(stderr
, "Cannot create namespace file \"%s\": %s\n",
658 netns_path
, strerror(errno
));
662 if (unshare(CLONE_NEWNET
) < 0) {
663 fprintf(stderr
, "Failed to create a new network namespace \"%s\": %s\n",
664 name
, strerror(errno
));
668 /* Bind the netns last so I can watch for it */
669 if (mount("/proc/self/ns/net", netns_path
, "none", MS_BIND
, NULL
) < 0) {
670 fprintf(stderr
, "Bind /proc/self/ns/net -> %s failed: %s\n",
671 netns_path
, strerror(errno
));
676 netns_delete(argc
, argv
);
680 static int set_netnsid_from_name(const char *name
, int nsid
)
689 memset(&req
, 0, sizeof(req
));
690 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct rtgenmsg
));
691 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
692 req
.n
.nlmsg_type
= RTM_NEWNSID
;
693 req
.g
.rtgen_family
= AF_UNSPEC
;
695 fd
= netns_get_fd(name
);
699 addattr32(&req
.n
, 1024, NETNSA_FD
, fd
);
700 addattr32(&req
.n
, 1024, NETNSA_NSID
, nsid
);
701 if (rtnl_talk(&rth
, &req
.n
, NULL
, 0) < 0)
708 static int netns_set(int argc
, char **argv
)
710 char netns_path
[MAXPATHLEN
];
715 fprintf(stderr
, "No netns name specified\n");
719 fprintf(stderr
, "No nsid specified\n");
723 nsid
= atoi(argv
[1]);
725 snprintf(netns_path
, sizeof(netns_path
), "%s/%s", NETNS_RUN_DIR
, name
);
726 netns
= open(netns_path
, O_RDONLY
| O_CLOEXEC
);
728 fprintf(stderr
, "Cannot open network namespace \"%s\": %s\n",
729 name
, strerror(errno
));
733 return set_netnsid_from_name(name
, nsid
);
736 static int netns_monitor(int argc
, char **argv
)
739 struct inotify_event
*event
;
743 fprintf(stderr
, "inotify_init failed: %s\n",
748 if (create_netns_dir())
751 if (inotify_add_watch(fd
, NETNS_RUN_DIR
, IN_CREATE
| IN_DELETE
) < 0) {
752 fprintf(stderr
, "inotify_add_watch failed: %s\n",
757 ssize_t len
= read(fd
, buf
, sizeof(buf
));
759 fprintf(stderr
, "read failed: %s\n",
763 for (event
= (struct inotify_event
*)buf
;
764 (char *)event
< &buf
[len
];
765 event
= (struct inotify_event
*)((char *)event
+ sizeof(*event
) + event
->len
)) {
766 if (event
->mask
& IN_CREATE
)
767 printf("add %s\n", event
->name
);
768 if (event
->mask
& IN_DELETE
)
769 printf("delete %s\n", event
->name
);
775 int do_netns(int argc
, char **argv
)
780 return netns_list(0, NULL
);
782 if ((matches(*argv
, "list") == 0) || (matches(*argv
, "show") == 0) ||
783 (matches(*argv
, "lst") == 0))
784 return netns_list(argc
-1, argv
+1);
786 if ((matches(*argv
, "list-id") == 0))
787 return netns_list_id(argc
-1, argv
+1);
789 if (matches(*argv
, "help") == 0)
792 if (matches(*argv
, "add") == 0)
793 return netns_add(argc
-1, argv
+1);
795 if (matches(*argv
, "set") == 0)
796 return netns_set(argc
-1, argv
+1);
798 if (matches(*argv
, "delete") == 0)
799 return netns_delete(argc
-1, argv
+1);
801 if (matches(*argv
, "identify") == 0)
802 return netns_identify(argc
-1, argv
+1);
804 if (matches(*argv
, "pids") == 0)
805 return netns_pids(argc
-1, argv
+1);
807 if (matches(*argv
, "exec") == 0)
808 return netns_exec(argc
-1, argv
+1);
810 if (matches(*argv
, "monitor") == 0)
811 return netns_monitor(argc
-1, argv
+1);
813 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv
);