]>
git.proxmox.com Git - mirror_iproute2.git/blob - ip/ipnetns.c
1 /* SPDX-License-Identifier: GPL-2.0 */
6 #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"
25 #include "json_print.h"
27 static int usage(void)
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 fprintf(stderr
, "NETNSID := auto | POSITIVE-INT\n");
42 /* This socket is used to get nsid */
43 static struct rtnl_handle rtnsh
= { .fd
= -1 };
45 static int have_rtnl_getnsid
= -1;
47 static int ipnetns_accept_msg(struct rtnl_ctrl_data
*ctrl
,
48 struct nlmsghdr
*n
, void *arg
)
50 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(n
);
52 if (n
->nlmsg_type
== NLMSG_ERROR
&&
53 (err
->error
== -EOPNOTSUPP
|| err
->error
== -EINVAL
))
54 have_rtnl_getnsid
= 0;
56 have_rtnl_getnsid
= 1;
60 static int ipnetns_have_nsid(void)
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
,
74 if (have_rtnl_getnsid
< 0) {
75 fd
= open("/proc/self/ns/net", O_RDONLY
);
77 have_rtnl_getnsid
= 0;
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 int get_netnsid_from_name(const char *name
)
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
,
106 struct nlmsghdr
*answer
;
107 struct rtattr
*tb
[NETNSA_MAX
+ 1];
108 struct rtgenmsg
*rthdr
;
111 netns_nsid_socket_init();
113 fd
= netns_get_fd(name
);
117 addattr32(&req
.n
, 1024, NETNSA_FD
, fd
);
118 if (rtnl_talk(&rtnsh
, &req
.n
, &answer
) < 0) {
124 /* Validate message and parse attributes */
125 if (answer
->nlmsg_type
== NLMSG_ERROR
)
128 rthdr
= NLMSG_DATA(answer
);
129 len
= answer
->nlmsg_len
- NLMSG_SPACE(sizeof(*rthdr
));
133 parse_rtattr(tb
, NETNSA_MAX
, NETNS_RTA(rthdr
), len
);
135 if (tb
[NETNSA_NSID
]) {
137 return rta_getattr_u32(tb
[NETNSA_NSID
]);
146 struct hlist_node nsid_hash
;
147 struct hlist_node name_hash
;
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))
156 static struct hlist_head nsid_head
[NSIDMAP_SIZE
];
157 static struct hlist_head name_head
[NSIDMAP_SIZE
];
159 static struct nsid_cache
*netns_map_get_by_nsid(int nsid
)
161 uint32_t h
= NSID_HASH_NSID(nsid
);
162 struct hlist_node
*n
;
164 hlist_for_each(n
, &nsid_head
[h
]) {
165 struct nsid_cache
*c
= container_of(n
, struct nsid_cache
,
174 char *get_name_from_nsid(int nsid
)
176 struct nsid_cache
*c
;
178 netns_nsid_socket_init();
181 c
= netns_map_get_by_nsid(nsid
);
188 static int netns_map_add(int nsid
, const char *name
)
190 struct nsid_cache
*c
;
193 if (netns_map_get_by_nsid(nsid
) != NULL
)
196 c
= malloc(sizeof(*c
) + strlen(name
) + 1);
202 strcpy(c
->name
, name
);
204 h
= NSID_HASH_NSID(nsid
);
205 hlist_add_head(&c
->nsid_hash
, &nsid_head
[h
]);
207 h
= NSID_HASH_NAME(name
);
208 hlist_add_head(&c
->name_hash
, &name_head
[h
]);
213 static void netns_map_del(struct nsid_cache
*c
)
215 hlist_del(&c
->name_hash
);
216 hlist_del(&c
->nsid_hash
);
220 void netns_nsid_socket_init(void)
222 if (rtnsh
.fd
> -1 || !ipnetns_have_nsid())
225 if (rtnl_open(&rtnsh
, 0) < 0) {
226 fprintf(stderr
, "Cannot open rtnetlink\n");
232 void netns_map_init(void)
234 static int initialized
;
235 struct dirent
*entry
;
239 if (initialized
|| !ipnetns_have_nsid())
242 dir
= opendir(NETNS_RUN_DIR
);
246 while ((entry
= readdir(dir
)) != NULL
) {
247 if (strcmp(entry
->d_name
, ".") == 0)
249 if (strcmp(entry
->d_name
, "..") == 0)
251 nsid
= get_netnsid_from_name(entry
->d_name
);
254 netns_map_add(nsid
, entry
->d_name
);
260 static int netns_get_name(int nsid
, char *name
)
262 struct dirent
*entry
;
266 dir
= opendir(NETNS_RUN_DIR
);
270 while ((entry
= readdir(dir
)) != NULL
) {
271 if (strcmp(entry
->d_name
, ".") == 0)
273 if (strcmp(entry
->d_name
, "..") == 0)
275 id
= get_netnsid_from_name(entry
->d_name
);
278 strcpy(name
, entry
->d_name
);
287 int print_nsid(struct nlmsghdr
*n
, void *arg
)
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
;
297 if (n
->nlmsg_type
!= RTM_NEWNSID
&& n
->nlmsg_type
!= RTM_DELNSID
)
300 len
-= NLMSG_SPACE(sizeof(*rthdr
));
302 fprintf(stderr
, "BUG: wrong nlmsg len %d in %s\n", len
,
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__
);
313 open_json_object(NULL
);
314 if (n
->nlmsg_type
== RTM_DELNSID
)
315 print_bool(PRINT_ANY
, "deleted", "Deleted ", true);
317 nsid
= rta_getattr_u32(tb
[NETNSA_NSID
]);
318 print_uint(PRINT_ANY
, "nsid", "nsid %u ", nsid
);
320 c
= netns_map_get_by_nsid(nsid
);
322 print_string(PRINT_ANY
, "name",
323 "(iproute2 netns name: %s)", c
->name
);
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
);
335 print_string(PRINT_FP
, NULL
, "\n", NULL
);
341 static int netns_list_id(int argc
, char **argv
)
343 if (!ipnetns_have_nsid()) {
345 "RTM_GETNSID is not supported by the kernel.\n");
349 if (rtnl_nsiddump_req(&rth
, AF_UNSPEC
) < 0) {
350 perror("Cannot send dump request");
355 if (rtnl_dump_filter(&rth
, print_nsid
, stdout
) < 0) {
357 fprintf(stderr
, "Dump terminated\n");
364 static int netns_list(int argc
, char **argv
)
366 struct dirent
*entry
;
370 dir
= opendir(NETNS_RUN_DIR
);
375 while ((entry
= readdir(dir
)) != NULL
) {
376 if (strcmp(entry
->d_name
, ".") == 0)
378 if (strcmp(entry
->d_name
, "..") == 0)
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
);
387 print_uint(PRINT_ANY
, "id",
390 print_string(PRINT_FP
, NULL
, "\n", NULL
);
398 static int on_netns_exec(char *nsname
, void *arg
)
402 cmd_exec(argv
[1], argv
+ 1, true);
406 static int netns_exec(int argc
, char **argv
)
408 /* Setup the proper environment for apps that are not netns
409 * aware, and execute a program in that environment.
413 if (argc
< 1 && !do_all
) {
414 fprintf(stderr
, "No netns name specified\n");
417 if ((argc
< 2 && !do_all
) || (argc
< 1 && do_all
)) {
418 fprintf(stderr
, "No command specified\n");
423 return do_each_netns(on_netns_exec
, --argv
, 1);
425 if (netns_switch(argv
[0]))
428 /* we just changed namespaces. clear any vrf association
429 * with prior namespace before exec'ing command
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.
438 return -cmd_exec(cmd
, argv
+ 1, !!batch_mode
);
441 static int is_pid(const char *str
)
445 for (; (ch
= *str
); str
++) {
452 static int netns_pids(int argc
, char **argv
)
455 char net_path
[PATH_MAX
];
459 struct dirent
*entry
;
462 fprintf(stderr
, "No netns name specified\n");
466 fprintf(stderr
, "extra arguments specified\n");
471 snprintf(net_path
, sizeof(net_path
), "%s/%s", NETNS_RUN_DIR
, name
);
472 netns
= open(net_path
, O_RDONLY
);
474 fprintf(stderr
, "Cannot open network namespace: %s\n",
478 if (fstat(netns
, &netst
) < 0) {
479 fprintf(stderr
, "Stat of netns failed: %s\n",
483 dir
= opendir("/proc/");
485 fprintf(stderr
, "Open of /proc failed: %s\n",
489 while ((entry
= readdir(dir
))) {
490 char pid_net_path
[PATH_MAX
];
493 if (!is_pid(entry
->d_name
))
495 snprintf(pid_net_path
, sizeof(pid_net_path
), "/proc/%s/ns/net",
497 if (stat(pid_net_path
, &st
) != 0)
499 if ((st
.st_dev
== netst
.st_dev
) &&
500 (st
.st_ino
== netst
.st_ino
)) {
501 printf("%s\n", entry
->d_name
);
509 int netns_identify_pid(const char *pidstr
, char *name
, int len
)
511 char net_path
[PATH_MAX
];
515 struct dirent
*entry
;
519 snprintf(net_path
, sizeof(net_path
), "/proc/%s/ns/net", pidstr
);
520 netns
= open(net_path
, O_RDONLY
);
522 fprintf(stderr
, "Cannot open network namespace: %s\n",
526 if (fstat(netns
, &netst
) < 0) {
527 fprintf(stderr
, "Stat of netns failed: %s\n",
531 dir
= opendir(NETNS_RUN_DIR
);
533 /* Succeed treat a missing directory as an empty directory */
537 fprintf(stderr
, "Failed to open directory %s:%s\n",
538 NETNS_RUN_DIR
, strerror(errno
));
542 while ((entry
= readdir(dir
))) {
543 char name_path
[PATH_MAX
];
546 if (strcmp(entry
->d_name
, ".") == 0)
548 if (strcmp(entry
->d_name
, "..") == 0)
551 snprintf(name_path
, sizeof(name_path
), "%s/%s", NETNS_RUN_DIR
,
554 if (stat(name_path
, &st
) != 0)
557 if ((st
.st_dev
== netst
.st_dev
) &&
558 (st
.st_ino
== netst
.st_ino
)) {
559 strlcpy(name
, entry
->d_name
, len
);
567 static int netns_identify(int argc
, char **argv
)
575 } else if (argc
> 1) {
576 fprintf(stderr
, "extra arguments specified\n");
580 if (!is_pid(pidstr
)) {
581 fprintf(stderr
, "Specified string '%s' is not a pid\n",
587 rc
= netns_identify_pid(pidstr
, name
, sizeof(name
));
589 printf("%s\n", name
);
594 static int on_netns_del(char *nsname
, void *arg
)
596 char netns_path
[PATH_MAX
];
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
));
608 static int netns_delete(int argc
, char **argv
)
610 if (argc
< 1 && !do_all
) {
611 fprintf(stderr
, "No netns name specified\n");
616 return netns_foreach(on_netns_del
, NULL
);
618 return on_netns_del(argv
[0], NULL
);
621 static int create_netns_dir(void)
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
));
635 static int netns_add(int argc
, char **argv
)
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.
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.
645 char netns_path
[PATH_MAX
];
648 int made_netns_run_dir_mount
= 0;
651 fprintf(stderr
, "No netns name specified\n");
656 snprintf(netns_path
, sizeof(netns_path
), "%s/%s", NETNS_RUN_DIR
, name
);
658 if (create_netns_dir())
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
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
));
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
));
681 made_netns_run_dir_mount
= 1;
684 /* Create the filesystem state */
685 fd
= open(netns_path
, O_RDONLY
|O_CREAT
|O_EXCL
, 0);
687 fprintf(stderr
, "Cannot create namespace file \"%s\": %s\n",
688 netns_path
, strerror(errno
));
692 if (unshare(CLONE_NEWNET
) < 0) {
693 fprintf(stderr
, "Failed to create a new network namespace \"%s\": %s\n",
694 name
, strerror(errno
));
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
));
706 netns_delete(argc
, argv
);
710 int set_netnsid_from_name(const char *name
, int nsid
)
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
,
724 netns_nsid_socket_init();
726 fd
= netns_get_fd(name
);
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)
739 static int netns_set(int argc
, char **argv
)
741 char netns_path
[PATH_MAX
];
746 fprintf(stderr
, "No netns name specified\n");
750 fprintf(stderr
, "No nsid specified\n");
754 /* If a negative nsid is specified the kernel will select the nsid. */
755 if (strcmp(argv
[1], "auto") == 0)
757 else if (get_integer(&nsid
, argv
[1], 0))
758 invarg("Invalid \"netnsid\" value\n", argv
[1]);
760 invarg("\"netnsid\" value should be >= 0\n", argv
[1]);
762 snprintf(netns_path
, sizeof(netns_path
), "%s/%s", NETNS_RUN_DIR
, name
);
763 netns
= open(netns_path
, O_RDONLY
| O_CLOEXEC
);
765 fprintf(stderr
, "Cannot open network namespace \"%s\": %s\n",
766 name
, strerror(errno
));
770 return set_netnsid_from_name(name
, nsid
);
773 static int netns_monitor(int argc
, char **argv
)
776 struct inotify_event
*event
;
781 fprintf(stderr
, "inotify_init failed: %s\n",
786 if (create_netns_dir())
789 if (inotify_add_watch(fd
, NETNS_RUN_DIR
, IN_CREATE
| IN_DELETE
) < 0) {
790 fprintf(stderr
, "inotify_add_watch failed: %s\n",
795 ssize_t len
= read(fd
, buf
, sizeof(buf
));
798 fprintf(stderr
, "read failed: %s\n",
802 for (event
= (struct inotify_event
*)buf
;
803 (char *)event
< &buf
[len
];
804 event
= (struct inotify_event
*)((char *)event
+ sizeof(*event
) + event
->len
)) {
805 if (event
->mask
& IN_CREATE
)
806 printf("add %s\n", event
->name
);
807 if (event
->mask
& IN_DELETE
)
808 printf("delete %s\n", event
->name
);
814 static int invalid_name(const char *name
)
816 return !*name
|| strlen(name
) > NAME_MAX
||
817 strchr(name
, '/') || !strcmp(name
, ".") || !strcmp(name
, "..");
820 int do_netns(int argc
, char **argv
)
822 netns_nsid_socket_init();
826 return netns_list(0, NULL
);
829 if (argc
> 1 && invalid_name(argv
[1])) {
830 fprintf(stderr
, "Invalid netns name \"%s\"\n", argv
[1]);
834 if ((matches(*argv
, "list") == 0) || (matches(*argv
, "show") == 0) ||
835 (matches(*argv
, "lst") == 0)) {
837 return netns_list(argc
-1, argv
+1);
840 if ((matches(*argv
, "list-id") == 0)) {
842 return netns_list_id(argc
-1, argv
+1);
845 if (matches(*argv
, "help") == 0)
848 if (matches(*argv
, "add") == 0)
849 return netns_add(argc
-1, argv
+1);
851 if (matches(*argv
, "set") == 0)
852 return netns_set(argc
-1, argv
+1);
854 if (matches(*argv
, "delete") == 0)
855 return netns_delete(argc
-1, argv
+1);
857 if (matches(*argv
, "identify") == 0)
858 return netns_identify(argc
-1, argv
+1);
860 if (matches(*argv
, "pids") == 0)
861 return netns_pids(argc
-1, argv
+1);
863 if (matches(*argv
, "exec") == 0)
864 return netns_exec(argc
-1, argv
+1);
866 if (matches(*argv
, "monitor") == 0)
867 return netns_monitor(argc
-1, argv
+1);
869 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv
);