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