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