blob: 5a213dcf46cd0b69f775bd5d213cc46c3fc35d43 [file] [log] [blame]
Eric W. Biederman0dc34c72011-07-13 09:48:26 -07001#define _ATFILE_SOURCE
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <sys/wait.h>
5#include <sys/inotify.h>
6#include <sys/mount.h>
7#include <sys/param.h>
8#include <sys/syscall.h>
9#include <stdio.h>
10#include <string.h>
11#include <sched.h>
12#include <fcntl.h>
13#include <dirent.h>
14#include <errno.h>
15#include <unistd.h>
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +000016#include <ctype.h>
Eric W. Biederman0dc34c72011-07-13 09:48:26 -070017
Nicolas Dichteld182ee12015-02-17 17:30:37 +010018#include <linux/net_namespace.h>
19
Eric W. Biederman0dc34c72011-07-13 09:48:26 -070020#include "utils.h"
21#include "ip_common.h"
Vadim Kochaneb67e442014-12-24 23:04:08 +020022#include "namespace.h"
Eric W. Biederman0dc34c72011-07-13 09:48:26 -070023
Eric W. Biederman8e2d47d2013-01-17 14:46:09 +000024static int usage(void)
Eric W. Biederman0dc34c72011-07-13 09:48:26 -070025{
26 fprintf(stderr, "Usage: ip netns list\n");
27 fprintf(stderr, " ip netns add NAME\n");
Nicolas Dichteld182ee12015-02-17 17:30:37 +010028 fprintf(stderr, " ip netns set NAME NETNSID\n");
Vadim Kochan33724932015-01-18 16:10:19 +020029 fprintf(stderr, " ip [-all] netns delete [NAME]\n");
vadimk0948adc2014-11-07 18:25:30 +020030 fprintf(stderr, " ip netns identify [PID]\n");
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +000031 fprintf(stderr, " ip netns pids NAME\n");
Vadim Kochanb13ba032015-01-18 16:10:18 +020032 fprintf(stderr, " ip [-all] netns exec [NAME] cmd ...\n");
Eric W. Biederman0dc34c72011-07-13 09:48:26 -070033 fprintf(stderr, " ip netns monitor\n");
Stephen Hemmingera05f6512013-07-12 08:43:23 -070034 exit(-1);
Eric W. Biederman0dc34c72011-07-13 09:48:26 -070035}
36
Nicolas Dichteld182ee12015-02-17 17:30:37 +010037static int get_netnsid_from_name(const char *name)
38{
39 struct {
40 struct nlmsghdr n;
41 struct rtgenmsg g;
42 char buf[1024];
43 } req, answer;
44 struct rtattr *tb[NETNSA_MAX + 1];
45 struct rtgenmsg *rthdr;
46 int len, fd;
47
48 memset(&req, 0, sizeof(req));
49 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
50 req.n.nlmsg_flags = NLM_F_REQUEST;
51 req.n.nlmsg_type = RTM_GETNSID;
52 req.g.rtgen_family = AF_UNSPEC;
53
54 fd = netns_get_fd(name);
55 if (fd < 0)
56 return fd;
57
58 addattr32(&req.n, 1024, NETNSA_FD, fd);
59 if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) {
60 close(fd);
61 return -2;
62 }
63 close(fd);
64
65 /* Validate message and parse attributes */
66 if (answer.n.nlmsg_type == NLMSG_ERROR)
67 return -1;
68
69 rthdr = NLMSG_DATA(&answer.n);
70 len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr));
71 if (len < 0)
72 return -1;
73
74 parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
75
76 if (tb[NETNSA_NSID])
77 return rta_getattr_u32(tb[NETNSA_NSID]);
78
79 return -1;
80}
81
Eric W. Biederman0dc34c72011-07-13 09:48:26 -070082static int netns_list(int argc, char **argv)
83{
84 struct dirent *entry;
85 DIR *dir;
Nicolas Dichteld182ee12015-02-17 17:30:37 +010086 int id;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -070087
88 dir = opendir(NETNS_RUN_DIR);
89 if (!dir)
Stephen Hemmingera05f6512013-07-12 08:43:23 -070090 return 0;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -070091
92 while ((entry = readdir(dir)) != NULL) {
93 if (strcmp(entry->d_name, ".") == 0)
94 continue;
95 if (strcmp(entry->d_name, "..") == 0)
96 continue;
Nicolas Dichteld182ee12015-02-17 17:30:37 +010097 printf("%s", entry->d_name);
98 id = get_netnsid_from_name(entry->d_name);
99 if (id >= 0)
100 printf(" (id: %d)", id);
101 printf("\n");
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700102 }
103 closedir(dir);
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700104 return 0;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700105}
106
Vadim Kochanb13ba032015-01-18 16:10:18 +0200107static int cmd_exec(const char *cmd, char **argv, bool do_fork)
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700108{
JunweiZhang95592b42013-07-09 08:55:20 -0700109 fflush(stdout);
Vadim Kochanb13ba032015-01-18 16:10:18 +0200110 if (do_fork) {
JunweiZhang95592b42013-07-09 08:55:20 -0700111 int status;
112 pid_t pid;
113
114 pid = fork();
115 if (pid < 0) {
116 perror("fork");
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700117 exit(1);
JunweiZhang95592b42013-07-09 08:55:20 -0700118 }
119
120 if (pid != 0) {
121 /* Parent */
122 if (waitpid(pid, &status, 0) < 0) {
123 perror("waitpid");
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700124 exit(1);
JunweiZhang95592b42013-07-09 08:55:20 -0700125 }
126
Nicolas Dichtel3c61c012013-08-29 14:29:07 +0200127 if (WIFEXITED(status)) {
Vadim Kochanb13ba032015-01-18 16:10:18 +0200128 return WEXITSTATUS(status);
Nicolas Dichtel3c61c012013-08-29 14:29:07 +0200129 }
JunweiZhang95592b42013-07-09 08:55:20 -0700130
Nicolas Dichtel3c61c012013-08-29 14:29:07 +0200131 exit(1);
JunweiZhang95592b42013-07-09 08:55:20 -0700132 }
133 }
134
Vadim Kochanb13ba032015-01-18 16:10:18 +0200135 if (execvp(cmd, argv) < 0)
Kees van Reeuwijk14645ec2013-02-08 03:32:36 +0000136 fprintf(stderr, "exec of \"%s\" failed: %s\n",
Vadim Kochanb13ba032015-01-18 16:10:18 +0200137 cmd, strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700138 _exit(1);
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700139}
140
Vadim Kochanb13ba032015-01-18 16:10:18 +0200141static int on_netns_exec(char *nsname, void *arg)
142{
143 char **argv = arg;
144 cmd_exec(argv[1], argv + 1, true);
145 return 0;
146}
147
148static int netns_exec(int argc, char **argv)
149{
150 /* Setup the proper environment for apps that are not netns
151 * aware, and execute a program in that environment.
152 */
153 const char *cmd;
154
155 if (argc < 1 && !do_all) {
156 fprintf(stderr, "No netns name specified\n");
157 return -1;
158 }
159 if ((argc < 2 && !do_all) || (argc < 1 && do_all)) {
160 fprintf(stderr, "No command specified\n");
161 return -1;
162 }
163
164 if (do_all)
165 return do_each_netns(on_netns_exec, --argv, 1);
166
167 if (netns_switch(argv[0]))
168 return -1;
169
170 /* ip must return the status of the child,
171 * but do_cmd() will add a minus to this,
172 * so let's add another one here to cancel it.
173 */
174 cmd = argv[1];
175 return -cmd_exec(cmd, argv + 1, !!batch_mode);
176}
177
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000178static int is_pid(const char *str)
179{
180 int ch;
181 for (; (ch = *str); str++) {
182 if (!isdigit(ch))
183 return 0;
184 }
185 return 1;
186}
187
188static int netns_pids(int argc, char **argv)
189{
190 const char *name;
191 char net_path[MAXPATHLEN];
192 int netns;
193 struct stat netst;
194 DIR *dir;
195 struct dirent *entry;
196
197 if (argc < 1) {
198 fprintf(stderr, "No netns name specified\n");
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700199 return -1;
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000200 }
201 if (argc > 1) {
202 fprintf(stderr, "extra arguments specified\n");
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700203 return -1;
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000204 }
205
206 name = argv[0];
207 snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
208 netns = open(net_path, O_RDONLY);
209 if (netns < 0) {
210 fprintf(stderr, "Cannot open network namespace: %s\n",
211 strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700212 return -1;
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000213 }
214 if (fstat(netns, &netst) < 0) {
215 fprintf(stderr, "Stat of netns failed: %s\n",
216 strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700217 return -1;
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000218 }
219 dir = opendir("/proc/");
220 if (!dir) {
221 fprintf(stderr, "Open of /proc failed: %s\n",
222 strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700223 return -1;
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000224 }
225 while((entry = readdir(dir))) {
226 char pid_net_path[MAXPATHLEN];
227 struct stat st;
228 if (!is_pid(entry->d_name))
229 continue;
230 snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%s/ns/net",
231 entry->d_name);
232 if (stat(pid_net_path, &st) != 0)
233 continue;
234 if ((st.st_dev == netst.st_dev) &&
235 (st.st_ino == netst.st_ino)) {
236 printf("%s\n", entry->d_name);
237 }
238 }
239 closedir(dir);
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700240 return 0;
Stephen Hemminger06125192014-02-17 10:55:31 -0800241
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000242}
243
244static int netns_identify(int argc, char **argv)
245{
246 const char *pidstr;
247 char net_path[MAXPATHLEN];
248 int netns;
249 struct stat netst;
250 DIR *dir;
251 struct dirent *entry;
252
253 if (argc < 1) {
vadimk0948adc2014-11-07 18:25:30 +0200254 pidstr = "self";
255 } else if (argc > 1) {
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000256 fprintf(stderr, "extra arguments specified\n");
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700257 return -1;
vadimk0948adc2014-11-07 18:25:30 +0200258 } else {
259 pidstr = argv[0];
260 if (!is_pid(pidstr)) {
261 fprintf(stderr, "Specified string '%s' is not a pid\n",
262 pidstr);
263 return -1;
264 }
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000265 }
266
267 snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr);
268 netns = open(net_path, O_RDONLY);
269 if (netns < 0) {
270 fprintf(stderr, "Cannot open network namespace: %s\n",
271 strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700272 return -1;
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000273 }
274 if (fstat(netns, &netst) < 0) {
275 fprintf(stderr, "Stat of netns failed: %s\n",
276 strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700277 return -1;
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000278 }
279 dir = opendir(NETNS_RUN_DIR);
280 if (!dir) {
281 /* Succeed treat a missing directory as an empty directory */
282 if (errno == ENOENT)
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700283 return 0;
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000284
285 fprintf(stderr, "Failed to open directory %s:%s\n",
286 NETNS_RUN_DIR, strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700287 return -1;
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000288 }
289
290 while((entry = readdir(dir))) {
291 char name_path[MAXPATHLEN];
292 struct stat st;
293
294 if (strcmp(entry->d_name, ".") == 0)
295 continue;
296 if (strcmp(entry->d_name, "..") == 0)
297 continue;
298
299 snprintf(name_path, sizeof(name_path), "%s/%s", NETNS_RUN_DIR,
300 entry->d_name);
301
302 if (stat(name_path, &st) != 0)
303 continue;
304
305 if ((st.st_dev == netst.st_dev) &&
306 (st.st_ino == netst.st_ino)) {
307 printf("%s\n", entry->d_name);
308 }
309 }
310 closedir(dir);
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700311 return 0;
Stephen Hemminger06125192014-02-17 10:55:31 -0800312
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000313}
314
Vadim Kochan33724932015-01-18 16:10:19 +0200315static int on_netns_del(char *nsname, void *arg)
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700316{
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700317 char netns_path[MAXPATHLEN];
318
Vadim Kochan33724932015-01-18 16:10:19 +0200319 snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, nsname);
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700320 umount2(netns_path, MNT_DETACH);
321 if (unlink(netns_path) < 0) {
Kees van Reeuwijk14645ec2013-02-08 03:32:36 +0000322 fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700323 netns_path, strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700324 return -1;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700325 }
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700326 return 0;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700327}
328
Vadim Kochan33724932015-01-18 16:10:19 +0200329static int netns_delete(int argc, char **argv)
330{
331 if (argc < 1 && !do_all) {
332 fprintf(stderr, "No netns name specified\n");
333 return -1;
334 }
335
336 if (do_all)
337 return netns_foreach(on_netns_del, NULL);
338
339 return on_netns_del(argv[0], NULL);
340}
341
vadimkc1cbb182014-08-31 22:45:29 +0300342static int create_netns_dir(void)
343{
344 /* Create the base netns directory if it doesn't exist */
345 if (mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
346 if (errno != EEXIST) {
347 fprintf(stderr, "mkdir %s failed: %s\n",
348 NETNS_RUN_DIR, strerror(errno));
349 return -1;
350 }
351 }
352
353 return 0;
354}
355
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700356static int netns_add(int argc, char **argv)
357{
358 /* This function creates a new network namespace and
359 * a new mount namespace and bind them into a well known
360 * location in the filesystem based on the name provided.
361 *
362 * The mount namespace is created so that any necessary
363 * userspace tweaks like remounting /sys, or bind mounting
364 * a new /etc/resolv.conf can be shared between uers.
365 */
366 char netns_path[MAXPATHLEN];
367 const char *name;
Eric W. Biederman223f4d82011-07-15 14:29:41 +0000368 int fd;
Eric W. Biederman58a3e822013-01-17 14:47:18 +0000369 int made_netns_run_dir_mount = 0;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700370
371 if (argc < 1) {
372 fprintf(stderr, "No netns name specified\n");
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700373 return -1;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700374 }
375 name = argv[0];
376
377 snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
378
vadimkc1cbb182014-08-31 22:45:29 +0300379 if (create_netns_dir())
380 return -1;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700381
Stephen Hemmingerd259f032013-08-04 15:00:56 -0700382 /* Make it possible for network namespace mounts to propagate between
Eric W. Biederman58a3e822013-01-17 14:47:18 +0000383 * mount namespaces. This makes it likely that a unmounting a network
384 * namespace file in one namespace will unmount the network namespace
385 * file in all namespaces allowing the network namespace to be freed
386 * sooner.
387 */
388 while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) {
389 /* Fail unless we need to make the mount point */
390 if (errno != EINVAL || made_netns_run_dir_mount) {
391 fprintf(stderr, "mount --make-shared %s failed: %s\n",
392 NETNS_RUN_DIR, strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700393 return -1;
Eric W. Biederman58a3e822013-01-17 14:47:18 +0000394 }
395
396 /* Upgrade NETNS_RUN_DIR to a mount point */
397 if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND, NULL)) {
398 fprintf(stderr, "mount --bind %s %s failed: %s\n",
399 NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700400 return -1;
Eric W. Biederman58a3e822013-01-17 14:47:18 +0000401 }
402 made_netns_run_dir_mount = 1;
403 }
404
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700405 /* Create the filesystem state */
Eric W. Biederman223f4d82011-07-15 14:29:41 +0000406 fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
407 if (fd < 0) {
Mike Rapoport55713c82014-05-11 12:21:26 +0300408 fprintf(stderr, "Cannot create namespace file \"%s\": %s\n",
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700409 netns_path, strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700410 return -1;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700411 }
Eric W. Biederman223f4d82011-07-15 14:29:41 +0000412 close(fd);
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700413 if (unshare(CLONE_NEWNET) < 0) {
Kees van Reeuwijk14645ec2013-02-08 03:32:36 +0000414 fprintf(stderr, "Failed to create a new network namespace \"%s\": %s\n",
415 name, strerror(errno));
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700416 goto out_delete;
417 }
418
419 /* Bind the netns last so I can watch for it */
420 if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0) {
421 fprintf(stderr, "Bind /proc/self/ns/net -> %s failed: %s\n",
422 netns_path, strerror(errno));
423 goto out_delete;
424 }
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700425 return 0;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700426out_delete:
427 netns_delete(argc, argv);
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700428 return -1;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700429}
430
Nicolas Dichteld182ee12015-02-17 17:30:37 +0100431static int set_netnsid_from_name(const char *name, int nsid)
432{
433 struct {
434 struct nlmsghdr n;
435 struct rtgenmsg g;
436 char buf[1024];
437 } req;
438 int fd, err = 0;
439
440 memset(&req, 0, sizeof(req));
441 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
442 req.n.nlmsg_flags = NLM_F_REQUEST;
443 req.n.nlmsg_type = RTM_NEWNSID;
444 req.g.rtgen_family = AF_UNSPEC;
445
446 fd = netns_get_fd(name);
447 if (fd < 0)
448 return fd;
449
450 addattr32(&req.n, 1024, NETNSA_FD, fd);
451 addattr32(&req.n, 1024, NETNSA_NSID, nsid);
452 if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
453 err = -2;
454
455 close(fd);
456 return err;
457}
458
459static int netns_set(int argc, char **argv)
460{
461 char netns_path[MAXPATHLEN];
462 const char *name;
463 int netns, nsid;
464
465 if (argc < 1) {
466 fprintf(stderr, "No netns name specified\n");
467 return -1;
468 }
469 if (argc < 2) {
470 fprintf(stderr, "No nsid specified\n");
471 return -1;
472 }
473 name = argv[0];
474 nsid = atoi(argv[1]);
475
476 snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
477 netns = open(netns_path, O_RDONLY | O_CLOEXEC);
478 if (netns < 0) {
479 fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
480 name, strerror(errno));
481 return -1;
482 }
483
484 return set_netnsid_from_name(name, nsid);
485}
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700486
487static int netns_monitor(int argc, char **argv)
488{
489 char buf[4096];
490 struct inotify_event *event;
491 int fd;
492 fd = inotify_init();
493 if (fd < 0) {
494 fprintf(stderr, "inotify_init failed: %s\n",
495 strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700496 return -1;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700497 }
vadimkc1cbb182014-08-31 22:45:29 +0300498
499 if (create_netns_dir())
500 return -1;
501
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700502 if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) {
503 fprintf(stderr, "inotify_add_watch failed: %s\n",
504 strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700505 return -1;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700506 }
507 for(;;) {
508 ssize_t len = read(fd, buf, sizeof(buf));
509 if (len < 0) {
510 fprintf(stderr, "read failed: %s\n",
511 strerror(errno));
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700512 return -1;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700513 }
514 for (event = (struct inotify_event *)buf;
515 (char *)event < &buf[len];
516 event = (struct inotify_event *)((char *)event + sizeof(*event) + event->len)) {
517 if (event->mask & IN_CREATE)
518 printf("add %s\n", event->name);
519 if (event->mask & IN_DELETE)
520 printf("delete %s\n", event->name);
521 }
522 }
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700523 return 0;
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700524}
525
526int do_netns(int argc, char **argv)
527{
528 if (argc < 1)
529 return netns_list(0, NULL);
530
531 if ((matches(*argv, "list") == 0) || (matches(*argv, "show") == 0) ||
532 (matches(*argv, "lst") == 0))
533 return netns_list(argc-1, argv+1);
534
535 if (matches(*argv, "help") == 0)
Eric W. Biederman8e2d47d2013-01-17 14:46:09 +0000536 return usage();
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700537
538 if (matches(*argv, "add") == 0)
539 return netns_add(argc-1, argv+1);
540
Nicolas Dichteld182ee12015-02-17 17:30:37 +0100541 if (matches(*argv, "set") == 0)
542 return netns_set(argc-1, argv+1);
543
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700544 if (matches(*argv, "delete") == 0)
545 return netns_delete(argc-1, argv+1);
546
Eric W. Biederman9a7b3d92013-01-17 14:48:15 +0000547 if (matches(*argv, "identify") == 0)
548 return netns_identify(argc-1, argv+1);
549
550 if (matches(*argv, "pids") == 0)
551 return netns_pids(argc-1, argv+1);
552
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700553 if (matches(*argv, "exec") == 0)
554 return netns_exec(argc-1, argv+1);
555
556 if (matches(*argv, "monitor") == 0)
557 return netns_monitor(argc-1, argv+1);
558
559 fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv);
Stephen Hemmingera05f6512013-07-12 08:43:23 -0700560 exit(-1);
Eric W. Biederman0dc34c72011-07-13 09:48:26 -0700561}