10dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#define _ATFILE_SOURCE 20dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <sys/types.h> 30dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <sys/stat.h> 40dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <sys/wait.h> 50dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <sys/inotify.h> 60dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <sys/mount.h> 70dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <sys/syscall.h> 80dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <stdio.h> 90dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <string.h> 100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <sched.h> 110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <fcntl.h> 120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <dirent.h> 130dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <errno.h> 140dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <unistd.h> 159a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman#include <ctype.h> 16d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel#include <linux/limits.h> 170dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 18d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel#include <linux/net_namespace.h> 19d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 200dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include "utils.h" 21d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel#include "hlist.h" 220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include "ip_common.h" 23eb67e4498aec35eb16eaf894329f85b6316dabe8Vadim Kochan#include "namespace.h" 240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 258e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biedermanstatic int usage(void) 260dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 270dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Usage: ip netns list\n"); 280dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, " ip netns add NAME\n"); 29d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel fprintf(stderr, " ip netns set NAME NETNSID\n"); 3033724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan fprintf(stderr, " ip [-all] netns delete [NAME]\n"); 310948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk fprintf(stderr, " ip netns identify [PID]\n"); 329a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, " ip netns pids NAME\n"); 33b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan fprintf(stderr, " ip [-all] netns exec [NAME] cmd ...\n"); 340dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, " ip netns monitor\n"); 35d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(stderr, " ip netns list-id\n"); 36a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger exit(-1); 370dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 380dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 39d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel/* This socket is used to get nsid */ 40d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelstatic struct rtnl_handle rtnsh = { .fd = -1 }; 41d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 424c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtelstatic int have_rtnl_getnsid = -1; 434c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel 444c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtelstatic int ipnetns_accept_msg(const struct sockaddr_nl *who, 450628cddd9d5c0cb9ed0e0aba136e50de93487150Nicolas Dichtel struct rtnl_ctrl_data *ctrl, 464c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel struct nlmsghdr *n, void *arg) 474c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel{ 484c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n); 494c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel 504c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel if (n->nlmsg_type == NLMSG_ERROR && 514c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel (err->error == -EOPNOTSUPP || err->error == -EINVAL)) 524c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel have_rtnl_getnsid = 0; 534c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel else 544c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel have_rtnl_getnsid = 1; 554c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel return -1; 564c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel} 574c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel 584c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtelstatic int ipnetns_have_nsid(void) 594c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel{ 604c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel struct { 614c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel struct nlmsghdr n; 624c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel struct rtgenmsg g; 634c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel char buf[1024]; 644c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel } req; 654c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel int fd; 664c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel 674c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel if (have_rtnl_getnsid < 0) { 684c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel memset(&req, 0, sizeof(req)); 694c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); 704c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel req.n.nlmsg_flags = NLM_F_REQUEST; 714c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel req.n.nlmsg_type = RTM_GETNSID; 724c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel req.g.rtgen_family = AF_UNSPEC; 734c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel 744c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel fd = open("/proc/self/ns/net", O_RDONLY); 754c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel if (fd < 0) { 764c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel perror("open(\"/proc/self/ns/net\")"); 774c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel exit(1); 784c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel } 794c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel 804c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel addattr32(&req.n, 1024, NETNSA_FD, fd); 814c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel 824c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) { 834c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel perror("request send failed"); 844c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel exit(1); 854c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel } 864c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel rtnl_listen(&rth, ipnetns_accept_msg, NULL); 874c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel close(fd); 884c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel } 894c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel 904c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel return have_rtnl_getnsid; 914c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel} 924c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel 93d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtelstatic int get_netnsid_from_name(const char *name) 94d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel{ 95d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel struct { 96d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel struct nlmsghdr n; 97d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel struct rtgenmsg g; 98d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel char buf[1024]; 99d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel } req, answer; 100d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel struct rtattr *tb[NETNSA_MAX + 1]; 101d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel struct rtgenmsg *rthdr; 102d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel int len, fd; 103d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 104d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel memset(&req, 0, sizeof(req)); 105d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); 106d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel req.n.nlmsg_flags = NLM_F_REQUEST; 107d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel req.n.nlmsg_type = RTM_GETNSID; 108d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel req.g.rtgen_family = AF_UNSPEC; 109d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 110d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel fd = netns_get_fd(name); 111d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel if (fd < 0) 112d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return fd; 113d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 114d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel addattr32(&req.n, 1024, NETNSA_FD, fd); 115c079e121a73af5eb49e003b13607e8a690331df6Stephen Hemminger if (rtnl_talk(&rtnsh, &req.n, &answer.n, sizeof(answer)) < 0) { 116d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel close(fd); 117d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return -2; 118d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel } 119d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel close(fd); 120d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 121d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel /* Validate message and parse attributes */ 122d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel if (answer.n.nlmsg_type == NLMSG_ERROR) 123d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return -1; 124d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 125d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel rthdr = NLMSG_DATA(&answer.n); 126d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr)); 127d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel if (len < 0) 128d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return -1; 129d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 130d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len); 131d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 132d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel if (tb[NETNSA_NSID]) 133d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return rta_getattr_u32(tb[NETNSA_NSID]); 134d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 135d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return -1; 136d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel} 137d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 138d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelstruct nsid_cache { 139d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct hlist_node nsid_hash; 140d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct hlist_node name_hash; 141d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel int nsid; 1422f29d6bb5089271988a820d1f9596f9973ee2e4dStephen Hemminger char name[0]; 143d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel}; 144d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 145d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel#define NSIDMAP_SIZE 128 146d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel#define NSID_HASH_NSID(nsid) (nsid & (NSIDMAP_SIZE - 1)) 147d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel#define NSID_HASH_NAME(name) (namehash(name) & (NSIDMAP_SIZE - 1)) 148d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 149d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelstatic struct hlist_head nsid_head[NSIDMAP_SIZE]; 150d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelstatic struct hlist_head name_head[NSIDMAP_SIZE]; 151d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 152d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelstatic struct nsid_cache *netns_map_get_by_nsid(int nsid) 153d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel{ 154d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel uint32_t h = NSID_HASH_NSID(nsid); 155d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct hlist_node *n; 156d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 157d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel hlist_for_each(n, &nsid_head[h]) { 158d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct nsid_cache *c = container_of(n, struct nsid_cache, 159d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel nsid_hash); 160d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (c->nsid == nsid) 161d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return c; 162d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 163d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 164d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return NULL; 165d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel} 166d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 1672f29d6bb5089271988a820d1f9596f9973ee2e4dStephen Hemmingerstatic int netns_map_add(int nsid, const char *name) 168d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel{ 169d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct nsid_cache *c; 170d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel uint32_t h; 171d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 172d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (netns_map_get_by_nsid(nsid) != NULL) 173d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return -EEXIST; 174d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 1752f29d6bb5089271988a820d1f9596f9973ee2e4dStephen Hemminger c = malloc(sizeof(*c) + strlen(name)); 176d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (c == NULL) { 177d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel perror("malloc"); 178d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return -ENOMEM; 179d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 180d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel c->nsid = nsid; 181d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel strcpy(c->name, name); 182d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 183d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel h = NSID_HASH_NSID(nsid); 184d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel hlist_add_head(&c->nsid_hash, &nsid_head[h]); 185d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 186d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel h = NSID_HASH_NAME(name); 187d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel hlist_add_head(&c->name_hash, &name_head[h]); 188d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 189d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return 0; 190d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel} 191d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 192d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelstatic void netns_map_del(struct nsid_cache *c) 193d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel{ 194d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel hlist_del(&c->name_hash); 195d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel hlist_del(&c->nsid_hash); 196d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel free(c); 197d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel} 198d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 199d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelvoid netns_map_init(void) 200d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel{ 201d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel static int initialized; 202d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct dirent *entry; 203d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel DIR *dir; 204d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel int nsid; 205d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 206d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (initialized || !ipnetns_have_nsid()) 207d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return; 208d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 209d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (rtnl_open(&rtnsh, 0) < 0) { 210d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(stderr, "Cannot open rtnetlink\n"); 211d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel exit(1); 212d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 213d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 214d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel dir = opendir(NETNS_RUN_DIR); 215d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (!dir) 216d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return; 217d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 218d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel while ((entry = readdir(dir)) != NULL) { 219d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (strcmp(entry->d_name, ".") == 0) 220d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel continue; 221d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (strcmp(entry->d_name, "..") == 0) 222d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel continue; 223d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel nsid = get_netnsid_from_name(entry->d_name); 224d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 225d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (nsid >= 0) 226d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel netns_map_add(nsid, entry->d_name); 227d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 228d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel closedir(dir); 229d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel initialized = 1; 230d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel} 231d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 232d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelstatic int netns_get_name(int nsid, char *name) 233d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel{ 234d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct dirent *entry; 235d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel DIR *dir; 236d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel int id; 237d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 238d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel dir = opendir(NETNS_RUN_DIR); 239d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (!dir) 240d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return -ENOENT; 241d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 242d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel while ((entry = readdir(dir)) != NULL) { 243d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (strcmp(entry->d_name, ".") == 0) 244d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel continue; 245d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (strcmp(entry->d_name, "..") == 0) 246d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel continue; 247d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel id = get_netnsid_from_name(entry->d_name); 248d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 249d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (nsid == id) { 250d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel strcpy(name, entry->d_name); 251d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel closedir(dir); 252d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return 0; 253d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 254d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 255d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel closedir(dir); 256d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return -ENOENT; 257d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel} 258d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 259d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelint print_nsid(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) 260d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel{ 261d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct rtgenmsg *rthdr = NLMSG_DATA(n); 262d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct rtattr *tb[NETNSA_MAX+1]; 263d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel int len = n->nlmsg_len; 264d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel FILE *fp = (FILE *)arg; 265d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel struct nsid_cache *c; 266d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel char name[NAME_MAX]; 267d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel int nsid; 268d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 269d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (n->nlmsg_type != RTM_NEWNSID && n->nlmsg_type != RTM_DELNSID) 270d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return 0; 271d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 272d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel len -= NLMSG_SPACE(sizeof(*rthdr)); 273d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (len < 0) { 274d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(stderr, "BUG: wrong nlmsg len %d in %s\n", len, 275d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel __func__); 276d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return -1; 277d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 278d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 279d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len); 280d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (tb[NETNSA_NSID] == NULL) { 281d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(stderr, "BUG: NETNSA_NSID is missing %s\n", __func__); 282d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return -1; 283d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 284d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 285d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (n->nlmsg_type == RTM_DELNSID) 286d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(fp, "Deleted "); 287d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 288d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel nsid = rta_getattr_u32(tb[NETNSA_NSID]); 289d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(fp, "nsid %u ", nsid); 290d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 291d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel c = netns_map_get_by_nsid(nsid); 292d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (c != NULL) { 293d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(fp, "(iproute2 netns name: %s)", c->name); 294d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel netns_map_del(c); 295d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 296d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 297d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel /* During 'ip monitor nsid', no chance to have new nsid in cache. */ 298d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (c == NULL && n->nlmsg_type == RTM_NEWNSID) 299d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (netns_get_name(nsid, name) == 0) { 300d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(fp, "(iproute2 netns name: %s)", name); 301d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel netns_map_add(nsid, name); 302d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 303d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 304d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(fp, "\n"); 305d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fflush(fp); 306d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return 0; 307d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel} 308d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 309d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtelstatic int netns_list_id(int argc, char **argv) 310d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel{ 311d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (!ipnetns_have_nsid()) { 312d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(stderr, 313d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel "RTM_GETNSID is not supported by the kernel.\n"); 314d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return -ENOTSUP; 315d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 316d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 317d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETNSID) < 0) { 318d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel perror("Cannot send dump request"); 319d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel exit(1); 320d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 321d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if (rtnl_dump_filter(&rth, print_nsid, stdout) < 0) { 322d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel fprintf(stderr, "Dump terminated\n"); 323d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel exit(1); 324d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel } 325d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return 0; 326d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel} 327d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 3280dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_list(int argc, char **argv) 3290dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 3300dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman struct dirent *entry; 3310dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman DIR *dir; 332d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel int id; 3330dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 3340dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman dir = opendir(NETNS_RUN_DIR); 3350dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (!dir) 336a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return 0; 3370dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 3380dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman while ((entry = readdir(dir)) != NULL) { 3390dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (strcmp(entry->d_name, ".") == 0) 3400dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman continue; 3410dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (strcmp(entry->d_name, "..") == 0) 3420dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman continue; 343d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel printf("%s", entry->d_name); 3444c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel if (ipnetns_have_nsid()) { 3454c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel id = get_netnsid_from_name(entry->d_name); 3464c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel if (id >= 0) 3474c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel printf(" (id: %d)", id); 3484c7d9a588896c56e3b484a160850b14b389856c0Nicolas Dichtel } 349d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel printf("\n"); 3500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 3510dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman closedir(dir); 352a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return 0; 3530dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 3540dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 355b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochanstatic int cmd_exec(const char *cmd, char **argv, bool do_fork) 3560dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 35795592b47be09bd9347026ff9aa298fc097733e56JunweiZhang fflush(stdout); 358b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan if (do_fork) { 35995592b47be09bd9347026ff9aa298fc097733e56JunweiZhang int status; 36095592b47be09bd9347026ff9aa298fc097733e56JunweiZhang pid_t pid; 36195592b47be09bd9347026ff9aa298fc097733e56JunweiZhang 36295592b47be09bd9347026ff9aa298fc097733e56JunweiZhang pid = fork(); 36395592b47be09bd9347026ff9aa298fc097733e56JunweiZhang if (pid < 0) { 36495592b47be09bd9347026ff9aa298fc097733e56JunweiZhang perror("fork"); 365a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger exit(1); 36695592b47be09bd9347026ff9aa298fc097733e56JunweiZhang } 36795592b47be09bd9347026ff9aa298fc097733e56JunweiZhang 36895592b47be09bd9347026ff9aa298fc097733e56JunweiZhang if (pid != 0) { 36995592b47be09bd9347026ff9aa298fc097733e56JunweiZhang /* Parent */ 37095592b47be09bd9347026ff9aa298fc097733e56JunweiZhang if (waitpid(pid, &status, 0) < 0) { 37195592b47be09bd9347026ff9aa298fc097733e56JunweiZhang perror("waitpid"); 372a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger exit(1); 37395592b47be09bd9347026ff9aa298fc097733e56JunweiZhang } 37495592b47be09bd9347026ff9aa298fc097733e56JunweiZhang 3753c61c01a666d9f4dbb871305ab6791e19ede7d4aNicolas Dichtel if (WIFEXITED(status)) { 376b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan return WEXITSTATUS(status); 3773c61c01a666d9f4dbb871305ab6791e19ede7d4aNicolas Dichtel } 37895592b47be09bd9347026ff9aa298fc097733e56JunweiZhang 3793c61c01a666d9f4dbb871305ab6791e19ede7d4aNicolas Dichtel exit(1); 38095592b47be09bd9347026ff9aa298fc097733e56JunweiZhang } 38195592b47be09bd9347026ff9aa298fc097733e56JunweiZhang } 38295592b47be09bd9347026ff9aa298fc097733e56JunweiZhang 383b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan if (execvp(cmd, argv) < 0) 38414645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk fprintf(stderr, "exec of \"%s\" failed: %s\n", 385b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan cmd, strerror(errno)); 386a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger _exit(1); 3870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 3880dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 389b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochanstatic int on_netns_exec(char *nsname, void *arg) 390b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan{ 391b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan char **argv = arg; 392b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan cmd_exec(argv[1], argv + 1, true); 393b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan return 0; 394b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan} 395b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan 396b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochanstatic int netns_exec(int argc, char **argv) 397b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan{ 398b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan /* Setup the proper environment for apps that are not netns 399b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan * aware, and execute a program in that environment. 400b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan */ 401b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan const char *cmd; 402b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan 403b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan if (argc < 1 && !do_all) { 404b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan fprintf(stderr, "No netns name specified\n"); 405b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan return -1; 406b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan } 407b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan if ((argc < 2 && !do_all) || (argc < 1 && do_all)) { 408b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan fprintf(stderr, "No command specified\n"); 409b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan return -1; 410b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan } 411b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan 412b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan if (do_all) 413b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan return do_each_netns(on_netns_exec, --argv, 1); 414b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan 415b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan if (netns_switch(argv[0])) 416b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan return -1; 417b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan 418b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan /* ip must return the status of the child, 419b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan * but do_cmd() will add a minus to this, 420b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan * so let's add another one here to cancel it. 421b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan */ 422b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan cmd = argv[1]; 423b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan return -cmd_exec(cmd, argv + 1, !!batch_mode); 424b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan} 425b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan 4269a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biedermanstatic int is_pid(const char *str) 4279a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman{ 4289a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman int ch; 4299a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman for (; (ch = *str); str++) { 4309a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (!isdigit(ch)) 4319a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman return 0; 4329a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 4339a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman return 1; 4349a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman} 4359a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 4369a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biedermanstatic int netns_pids(int argc, char **argv) 4379a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman{ 4389a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman const char *name; 439ea343669fa21cd4819576ddbb008ca49dfa5bf75Felix Janda char net_path[PATH_MAX]; 4409a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman int netns; 4419a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman struct stat netst; 4429a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman DIR *dir; 4439a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman struct dirent *entry; 4449a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 4459a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (argc < 1) { 4469a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, "No netns name specified\n"); 447a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 4489a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 4499a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (argc > 1) { 4509a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, "extra arguments specified\n"); 451a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 4529a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 4539a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 4549a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman name = argv[0]; 4559a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); 4569a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman netns = open(net_path, O_RDONLY); 4579a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (netns < 0) { 4589a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, "Cannot open network namespace: %s\n", 4599a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman strerror(errno)); 460a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 4619a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 4629a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (fstat(netns, &netst) < 0) { 4639a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, "Stat of netns failed: %s\n", 4649a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman strerror(errno)); 465a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 4669a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 4679a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman dir = opendir("/proc/"); 4689a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (!dir) { 4699a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, "Open of /proc failed: %s\n", 4709a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman strerror(errno)); 471a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 4729a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 4739a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman while((entry = readdir(dir))) { 474ea343669fa21cd4819576ddbb008ca49dfa5bf75Felix Janda char pid_net_path[PATH_MAX]; 4759a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman struct stat st; 4769a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (!is_pid(entry->d_name)) 4779a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman continue; 4789a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%s/ns/net", 4799a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman entry->d_name); 4809a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (stat(pid_net_path, &st) != 0) 4819a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman continue; 4829a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if ((st.st_dev == netst.st_dev) && 4839a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman (st.st_ino == netst.st_ino)) { 4849a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman printf("%s\n", entry->d_name); 4859a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 4869a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 4879a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman closedir(dir); 488a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return 0; 4890612519e011812276ade512d4a7f8113497f64edStephen Hemminger 4909a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman} 4919a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 4929a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biedermanstatic int netns_identify(int argc, char **argv) 4939a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman{ 4949a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman const char *pidstr; 495ea343669fa21cd4819576ddbb008ca49dfa5bf75Felix Janda char net_path[PATH_MAX]; 4969a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman int netns; 4979a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman struct stat netst; 4989a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman DIR *dir; 4999a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman struct dirent *entry; 5009a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 5019a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (argc < 1) { 5020948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk pidstr = "self"; 5030948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk } else if (argc > 1) { 5049a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, "extra arguments specified\n"); 505a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 5060948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk } else { 5070948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk pidstr = argv[0]; 5080948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk if (!is_pid(pidstr)) { 5090948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk fprintf(stderr, "Specified string '%s' is not a pid\n", 5100948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk pidstr); 5110948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk return -1; 5120948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk } 5139a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 5149a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 5159a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr); 5169a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman netns = open(net_path, O_RDONLY); 5179a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (netns < 0) { 5189a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, "Cannot open network namespace: %s\n", 5199a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman strerror(errno)); 520a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 5219a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 5229a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (fstat(netns, &netst) < 0) { 5239a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, "Stat of netns failed: %s\n", 5249a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman strerror(errno)); 525a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 5269a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 5279a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman dir = opendir(NETNS_RUN_DIR); 5289a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (!dir) { 5299a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman /* Succeed treat a missing directory as an empty directory */ 5309a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (errno == ENOENT) 531a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return 0; 5329a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 5339a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman fprintf(stderr, "Failed to open directory %s:%s\n", 5349a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman NETNS_RUN_DIR, strerror(errno)); 535a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 5369a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 5379a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 5389a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman while((entry = readdir(dir))) { 539ea343669fa21cd4819576ddbb008ca49dfa5bf75Felix Janda char name_path[PATH_MAX]; 5409a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman struct stat st; 5419a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 5429a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (strcmp(entry->d_name, ".") == 0) 5439a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman continue; 5449a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (strcmp(entry->d_name, "..") == 0) 5459a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman continue; 5469a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 5479a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman snprintf(name_path, sizeof(name_path), "%s/%s", NETNS_RUN_DIR, 5489a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman entry->d_name); 5499a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 5509a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (stat(name_path, &st) != 0) 5519a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman continue; 5529a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 5539a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if ((st.st_dev == netst.st_dev) && 5549a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman (st.st_ino == netst.st_ino)) { 5559a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman printf("%s\n", entry->d_name); 5569a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 5579a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman } 5589a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman closedir(dir); 559a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return 0; 5600612519e011812276ade512d4a7f8113497f64edStephen Hemminger 5619a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman} 5629a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 56333724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochanstatic int on_netns_del(char *nsname, void *arg) 5640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 565ea343669fa21cd4819576ddbb008ca49dfa5bf75Felix Janda char netns_path[PATH_MAX]; 5660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 56733724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, nsname); 5680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman umount2(netns_path, MNT_DETACH); 5690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (unlink(netns_path) < 0) { 57014645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n", 5710dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns_path, strerror(errno)); 572a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 5730dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 574a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return 0; 5750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 5760dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 57733724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochanstatic int netns_delete(int argc, char **argv) 57833724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan{ 57933724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan if (argc < 1 && !do_all) { 58033724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan fprintf(stderr, "No netns name specified\n"); 58133724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan return -1; 58233724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan } 58333724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan 58433724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan if (do_all) 58533724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan return netns_foreach(on_netns_del, NULL); 58633724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan 58733724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan return on_netns_del(argv[0], NULL); 58833724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan} 58933724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan 590c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimkstatic int create_netns_dir(void) 591c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk{ 592c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk /* Create the base netns directory if it doesn't exist */ 593c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk if (mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) { 594c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk if (errno != EEXIST) { 595c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk fprintf(stderr, "mkdir %s failed: %s\n", 596c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk NETNS_RUN_DIR, strerror(errno)); 597c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk return -1; 598c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk } 599c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk } 600c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk 601c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk return 0; 602c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk} 603c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk 6040dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_add(int argc, char **argv) 6050dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 6060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* This function creates a new network namespace and 6070dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * a new mount namespace and bind them into a well known 6080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * location in the filesystem based on the name provided. 6090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * 6100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * The mount namespace is created so that any necessary 6110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * userspace tweaks like remounting /sys, or bind mounting 6120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * a new /etc/resolv.conf can be shared between uers. 6130dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman */ 614ea343669fa21cd4819576ddbb008ca49dfa5bf75Felix Janda char netns_path[PATH_MAX]; 6150dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman const char *name; 616223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman int fd; 61758a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman int made_netns_run_dir_mount = 0; 6180dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 6190dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (argc < 1) { 6200dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "No netns name specified\n"); 621a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 6220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 6230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman name = argv[0]; 6240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 6250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name); 6260dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 627c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk if (create_netns_dir()) 628c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk return -1; 6290dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 630d259f0302f02206d7eb448da2673487fe1e0f8f6Stephen Hemminger /* Make it possible for network namespace mounts to propagate between 63158a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman * mount namespaces. This makes it likely that a unmounting a network 63258a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman * namespace file in one namespace will unmount the network namespace 63358a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman * file in all namespaces allowing the network namespace to be freed 63458a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman * sooner. 63558a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman */ 63658a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) { 63758a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman /* Fail unless we need to make the mount point */ 63858a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman if (errno != EINVAL || made_netns_run_dir_mount) { 63958a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman fprintf(stderr, "mount --make-shared %s failed: %s\n", 64058a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman NETNS_RUN_DIR, strerror(errno)); 641a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 64258a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman } 64358a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman 64458a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman /* Upgrade NETNS_RUN_DIR to a mount point */ 64558a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND, NULL)) { 64658a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman fprintf(stderr, "mount --bind %s %s failed: %s\n", 64758a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno)); 648a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 64958a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman } 65058a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman made_netns_run_dir_mount = 1; 65158a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman } 65258a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman 6530dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* Create the filesystem state */ 654223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0); 655223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman if (fd < 0) { 65655713c8c72a6cb7f42b3faf8a3208c9bc73f1a94Mike Rapoport fprintf(stderr, "Cannot create namespace file \"%s\": %s\n", 6570dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns_path, strerror(errno)); 658a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 6590dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 660223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman close(fd); 6610dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (unshare(CLONE_NEWNET) < 0) { 66214645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk fprintf(stderr, "Failed to create a new network namespace \"%s\": %s\n", 66314645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk name, strerror(errno)); 6640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman goto out_delete; 6650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 6660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 6670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* Bind the netns last so I can watch for it */ 6680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0) { 6690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Bind /proc/self/ns/net -> %s failed: %s\n", 6700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns_path, strerror(errno)); 6710dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman goto out_delete; 6720dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 673a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return 0; 6740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanout_delete: 6750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns_delete(argc, argv); 676a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 6770dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 6780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 679d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtelstatic int set_netnsid_from_name(const char *name, int nsid) 680d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel{ 681d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel struct { 682d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel struct nlmsghdr n; 683d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel struct rtgenmsg g; 684d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel char buf[1024]; 685d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel } req; 686d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel int fd, err = 0; 687d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 688d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel memset(&req, 0, sizeof(req)); 689d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); 690d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel req.n.nlmsg_flags = NLM_F_REQUEST; 691d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel req.n.nlmsg_type = RTM_NEWNSID; 692d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel req.g.rtgen_family = AF_UNSPEC; 693d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 694d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel fd = netns_get_fd(name); 695d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel if (fd < 0) 696d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return fd; 697d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 698d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel addattr32(&req.n, 1024, NETNSA_FD, fd); 699d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel addattr32(&req.n, 1024, NETNSA_NSID, nsid); 700c079e121a73af5eb49e003b13607e8a690331df6Stephen Hemminger if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) 701d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel err = -2; 702d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 703d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel close(fd); 704d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return err; 705d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel} 706d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 707d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtelstatic int netns_set(int argc, char **argv) 708d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel{ 709ea343669fa21cd4819576ddbb008ca49dfa5bf75Felix Janda char netns_path[PATH_MAX]; 710d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel const char *name; 711d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel int netns, nsid; 712d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 713d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel if (argc < 1) { 714d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel fprintf(stderr, "No netns name specified\n"); 715d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return -1; 716d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel } 717d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel if (argc < 2) { 718d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel fprintf(stderr, "No nsid specified\n"); 719d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return -1; 720d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel } 721d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel name = argv[0]; 722d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel nsid = atoi(argv[1]); 723d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 724d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name); 725d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel netns = open(netns_path, O_RDONLY | O_CLOEXEC); 726d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel if (netns < 0) { 727d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel fprintf(stderr, "Cannot open network namespace \"%s\": %s\n", 728d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel name, strerror(errno)); 729d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return -1; 730d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel } 731d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 732d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return set_netnsid_from_name(name, nsid); 733d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel} 7340dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 7350dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_monitor(int argc, char **argv) 7360dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 7370dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman char buf[4096]; 7380dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman struct inotify_event *event; 7390dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman int fd; 7400dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fd = inotify_init(); 7410dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (fd < 0) { 7420dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "inotify_init failed: %s\n", 7430dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman strerror(errno)); 744a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 7450dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 746c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk 747c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk if (create_netns_dir()) 748c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk return -1; 749c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk 7500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) { 7510dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "inotify_add_watch failed: %s\n", 7520dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman strerror(errno)); 753a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 7540dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 7550dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman for(;;) { 7560dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman ssize_t len = read(fd, buf, sizeof(buf)); 7570dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (len < 0) { 7580dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "read failed: %s\n", 7590dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman strerror(errno)); 760a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return -1; 7610dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 7620dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman for (event = (struct inotify_event *)buf; 7630dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman (char *)event < &buf[len]; 7640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman event = (struct inotify_event *)((char *)event + sizeof(*event) + event->len)) { 7650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (event->mask & IN_CREATE) 7660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman printf("add %s\n", event->name); 7670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (event->mask & IN_DELETE) 7680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman printf("delete %s\n", event->name); 7690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 7700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 771a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger return 0; 7720dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 7730dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 7740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanint do_netns(int argc, char **argv) 7750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 776d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel netns_map_init(); 777d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 7780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (argc < 1) 7790dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_list(0, NULL); 7800dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 7810dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if ((matches(*argv, "list") == 0) || (matches(*argv, "show") == 0) || 7820dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman (matches(*argv, "lst") == 0)) 7830dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_list(argc-1, argv+1); 7840dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 785d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel if ((matches(*argv, "list-id") == 0)) 786d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel return netns_list_id(argc-1, argv+1); 787d652ccbf8195e63ff6eedb923fad060b065fd18aNicolas Dichtel 7880dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "help") == 0) 7898e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman return usage(); 7900dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 7910dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "add") == 0) 7920dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_add(argc-1, argv+1); 7930dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 794d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel if (matches(*argv, "set") == 0) 795d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel return netns_set(argc-1, argv+1); 796d182ee1307c7a83b581d8f6d473bbce2004420c0Nicolas Dichtel 7970dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "delete") == 0) 7980dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_delete(argc-1, argv+1); 7990dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 8009a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (matches(*argv, "identify") == 0) 8019a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman return netns_identify(argc-1, argv+1); 8029a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 8039a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman if (matches(*argv, "pids") == 0) 8049a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman return netns_pids(argc-1, argv+1); 8059a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman 8060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "exec") == 0) 8070dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_exec(argc-1, argv+1); 8080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 8090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "monitor") == 0) 8100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_monitor(argc-1, argv+1); 8110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 8120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv); 813a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger exit(-1); 8140dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 815