ipnetns.c revision 33724939097b8ebb5c37cc0dc2b5e57fe342c8fe
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/param.h>
80dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <sys/syscall.h>
90dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <stdio.h>
100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <string.h>
110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <sched.h>
120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <fcntl.h>
130dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <dirent.h>
140dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <errno.h>
150dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include <unistd.h>
169a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman#include <ctype.h>
170dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
180dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include "utils.h"
190dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include "ip_common.h"
20eb67e4498aec35eb16eaf894329f85b6316dabe8Vadim Kochan#include "namespace.h"
210dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
228e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biedermanstatic int usage(void)
230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "Usage: ip netns list\n");
250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "       ip netns add NAME\n");
2633724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan	fprintf(stderr, "       ip [-all] netns delete [NAME]\n");
270948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk	fprintf(stderr, "       ip netns identify [PID]\n");
289a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	fprintf(stderr, "       ip netns pids NAME\n");
29b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	fprintf(stderr, "       ip [-all] netns exec [NAME] cmd ...\n");
300dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "       ip netns monitor\n");
31a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	exit(-1);
320dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
330dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
340dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_list(int argc, char **argv)
350dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
360dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	struct dirent *entry;
370dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	DIR *dir;
380dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
390dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	dir = opendir(NETNS_RUN_DIR);
400dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (!dir)
41a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return 0;
420dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
430dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	while ((entry = readdir(dir)) != NULL) {
440dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		if (strcmp(entry->d_name, ".") == 0)
450dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			continue;
460dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		if (strcmp(entry->d_name, "..") == 0)
470dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			continue;
480dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		printf("%s\n", entry->d_name);
490dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	closedir(dir);
51a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	return 0;
520dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
530dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
54b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochanstatic int cmd_exec(const char *cmd, char **argv, bool do_fork)
550dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
5695592b47be09bd9347026ff9aa298fc097733e56JunweiZhang	fflush(stdout);
57b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	if (do_fork) {
5895592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		int status;
5995592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		pid_t pid;
6095592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
6195592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		pid = fork();
6295592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		if (pid < 0) {
6395592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			perror("fork");
64a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger			exit(1);
6595592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		}
6695592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
6795592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		if (pid != 0) {
6895592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			/* Parent  */
6995592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			if (waitpid(pid, &status, 0) < 0) {
7095592b47be09bd9347026ff9aa298fc097733e56JunweiZhang				perror("waitpid");
71a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger				exit(1);
7295592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			}
7395592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
743c61c01a666d9f4dbb871305ab6791e19ede7d4aNicolas Dichtel			if (WIFEXITED(status)) {
75b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan				return WEXITSTATUS(status);
763c61c01a666d9f4dbb871305ab6791e19ede7d4aNicolas Dichtel			}
7795592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
783c61c01a666d9f4dbb871305ab6791e19ede7d4aNicolas Dichtel			exit(1);
7995592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		}
8095592b47be09bd9347026ff9aa298fc097733e56JunweiZhang	}
8195592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
82b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	if (execvp(cmd, argv)  < 0)
8314645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "exec of \"%s\" failed: %s\n",
84b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan				cmd, strerror(errno));
85a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	_exit(1);
860dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
88b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochanstatic int on_netns_exec(char *nsname, void *arg)
89b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan{
90b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	char **argv = arg;
91b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	cmd_exec(argv[1], argv + 1, true);
92b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	return 0;
93b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan}
94b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan
95b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochanstatic int netns_exec(int argc, char **argv)
96b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan{
97b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	/* Setup the proper environment for apps that are not netns
98b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	 * aware, and execute a program in that environment.
99b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	 */
100b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	const char *cmd;
101b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan
102b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	if (argc < 1 && !do_all) {
103b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan		fprintf(stderr, "No netns name specified\n");
104b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan		return -1;
105b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	}
106b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	if ((argc < 2 && !do_all) || (argc < 1 && do_all)) {
107b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan		fprintf(stderr, "No command specified\n");
108b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan		return -1;
109b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	}
110b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan
111b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	if (do_all)
112b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan		return do_each_netns(on_netns_exec, --argv, 1);
113b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan
114b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	if (netns_switch(argv[0]))
115b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan		return -1;
116b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan
117b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	/* ip must return the status of the child,
118b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	 * but do_cmd() will add a minus to this,
119b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	 * so let's add another one here to cancel it.
120b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	 */
121b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	cmd = argv[1];
122b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan	return -cmd_exec(cmd, argv + 1, !!batch_mode);
123b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan}
124b13ba03f54e95de2b2209763f874ac6713d13dd1Vadim Kochan
1259a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biedermanstatic int is_pid(const char *str)
1269a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman{
1279a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	int ch;
1289a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	for (; (ch = *str); str++) {
1299a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (!isdigit(ch))
1309a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			return 0;
1319a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
1329a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	return 1;
1339a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman}
1349a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
1359a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biedermanstatic int netns_pids(int argc, char **argv)
1369a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman{
1379a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	const char *name;
1389a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	char net_path[MAXPATHLEN];
1399a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	int netns;
1409a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	struct stat netst;
1419a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	DIR *dir;
1429a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	struct dirent *entry;
1439a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
1449a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (argc < 1) {
1459a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "No netns name specified\n");
146a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
1479a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
1489a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (argc > 1) {
1499a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "extra arguments specified\n");
150a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
1519a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
1529a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
1539a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	name = argv[0];
1549a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
1559a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	netns = open(net_path, O_RDONLY);
1569a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (netns < 0) {
1579a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Cannot open network namespace: %s\n",
1589a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
159a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
1609a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
1619a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (fstat(netns, &netst) < 0) {
1629a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Stat of netns failed: %s\n",
1639a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
164a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
1659a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
1669a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	dir = opendir("/proc/");
1679a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (!dir) {
1689a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Open of /proc failed: %s\n",
1699a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
170a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
1719a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
1729a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	while((entry = readdir(dir))) {
1739a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		char pid_net_path[MAXPATHLEN];
1749a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		struct stat st;
1759a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (!is_pid(entry->d_name))
1769a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
1779a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%s/ns/net",
1789a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			entry->d_name);
1799a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (stat(pid_net_path, &st) != 0)
1809a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
1819a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if ((st.st_dev == netst.st_dev) &&
1829a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		    (st.st_ino == netst.st_ino)) {
1839a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			printf("%s\n", entry->d_name);
1849a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		}
1859a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
1869a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	closedir(dir);
187a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	return 0;
1880612519e011812276ade512d4a7f8113497f64edStephen Hemminger
1899a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman}
1909a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
1919a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biedermanstatic int netns_identify(int argc, char **argv)
1929a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman{
1939a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	const char *pidstr;
1949a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	char net_path[MAXPATHLEN];
1959a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	int netns;
1969a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	struct stat netst;
1979a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	DIR *dir;
1989a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	struct dirent *entry;
1999a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2009a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (argc < 1) {
2010948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk		pidstr = "self";
2020948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk	} else if (argc > 1) {
2039a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "extra arguments specified\n");
204a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
2050948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk	} else {
2060948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk		pidstr = argv[0];
2070948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk		if (!is_pid(pidstr)) {
2080948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk			fprintf(stderr, "Specified string '%s' is not a pid\n",
2090948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk					pidstr);
2100948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk			return -1;
2110948adc01a3cee312e2bf81cfffe316f0b5f950bvadimk		}
2129a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2139a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2149a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr);
2159a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	netns = open(net_path, O_RDONLY);
2169a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (netns < 0) {
2179a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Cannot open network namespace: %s\n",
2189a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
219a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
2209a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2219a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (fstat(netns, &netst) < 0) {
2229a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Stat of netns failed: %s\n",
2239a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
224a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
2259a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2269a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	dir = opendir(NETNS_RUN_DIR);
2279a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (!dir) {
2289a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		/* Succeed treat a missing directory as an empty directory */
2299a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (errno == ENOENT)
230a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger			return 0;
2319a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2329a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Failed to open directory %s:%s\n",
2339a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			NETNS_RUN_DIR, strerror(errno));
234a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
2359a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2369a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2379a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	while((entry = readdir(dir))) {
2389a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		char name_path[MAXPATHLEN];
2399a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		struct stat st;
2409a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2419a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (strcmp(entry->d_name, ".") == 0)
2429a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
2439a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (strcmp(entry->d_name, "..") == 0)
2449a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
2459a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2469a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		snprintf(name_path, sizeof(name_path), "%s/%s",	NETNS_RUN_DIR,
2479a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			entry->d_name);
2489a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2499a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (stat(name_path, &st) != 0)
2509a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
2519a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2529a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if ((st.st_dev == netst.st_dev) &&
2539a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		    (st.st_ino == netst.st_ino)) {
2549a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			printf("%s\n", entry->d_name);
2559a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		}
2569a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2579a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	closedir(dir);
258a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	return 0;
2590612519e011812276ade512d4a7f8113497f64edStephen Hemminger
2609a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman}
2619a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
26233724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochanstatic int on_netns_del(char *nsname, void *arg)
2630dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
2640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char netns_path[MAXPATHLEN];
2650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
26633724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, nsname);
2670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	umount2(netns_path, MNT_DETACH);
2680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (unlink(netns_path) < 0) {
26914645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
2700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			netns_path, strerror(errno));
271a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
2720dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
273a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	return 0;
2740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
2750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
27633724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochanstatic int netns_delete(int argc, char **argv)
27733724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan{
27833724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan	if (argc < 1 && !do_all) {
27933724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan		fprintf(stderr, "No netns name specified\n");
28033724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan		return -1;
28133724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan	}
28233724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan
28333724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan	if (do_all)
28433724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan		return netns_foreach(on_netns_del, NULL);
28533724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan
28633724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan	return on_netns_del(argv[0], NULL);
28733724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan}
28833724939097b8ebb5c37cc0dc2b5e57fe342c8feVadim Kochan
289c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimkstatic int create_netns_dir(void)
290c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk{
291c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk	/* Create the base netns directory if it doesn't exist */
292c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk	if (mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
293c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk		if (errno != EEXIST) {
294c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk			fprintf(stderr, "mkdir %s failed: %s\n",
295c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk				NETNS_RUN_DIR, strerror(errno));
296c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk			return -1;
297c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk		}
298c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk	}
299c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk
300c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk	return 0;
301c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk}
302c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk
3030dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_add(int argc, char **argv)
3040dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
3050dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* This function creates a new network namespace and
3060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * a new mount namespace and bind them into a well known
3070dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * location in the filesystem based on the name provided.
3080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 *
3090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * The mount namespace is created so that any necessary
3100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * userspace tweaks like remounting /sys, or bind mounting
3110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * a new /etc/resolv.conf can be shared between uers.
3120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 */
3130dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char netns_path[MAXPATHLEN];
3140dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	const char *name;
315223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman	int fd;
31658a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	int made_netns_run_dir_mount = 0;
3170dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
3180dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (argc < 1) {
3190dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "No netns name specified\n");
320a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
3210dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
3220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	name = argv[0];
3230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
3240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
3250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
326c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk	if (create_netns_dir())
327c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk		return -1;
3280dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
329d259f0302f02206d7eb448da2673487fe1e0f8f6Stephen Hemminger	/* Make it possible for network namespace mounts to propagate between
33058a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 * mount namespaces.  This makes it likely that a unmounting a network
33158a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 * namespace file in one namespace will unmount the network namespace
33258a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 * file in all namespaces allowing the network namespace to be freed
33358a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 * sooner.
33458a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 */
33558a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) {
33658a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		/* Fail unless we need to make the mount point */
33758a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		if (errno != EINVAL || made_netns_run_dir_mount) {
33858a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman			fprintf(stderr, "mount --make-shared %s failed: %s\n",
33958a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman				NETNS_RUN_DIR, strerror(errno));
340a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger			return -1;
34158a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		}
34258a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman
34358a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		/* Upgrade NETNS_RUN_DIR to a mount point */
34458a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND, NULL)) {
34558a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman			fprintf(stderr, "mount --bind %s %s failed: %s\n",
34658a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman				NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
347a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger			return -1;
34858a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		}
34958a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		made_netns_run_dir_mount = 1;
35058a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	}
35158a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman
3520dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* Create the filesystem state */
353223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman	fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
354223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman	if (fd < 0) {
35555713c8c72a6cb7f42b3faf8a3208c9bc73f1a94Mike Rapoport		fprintf(stderr, "Cannot create namespace file \"%s\": %s\n",
3560dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			netns_path, strerror(errno));
357a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
3580dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
359223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman	close(fd);
3600dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (unshare(CLONE_NEWNET) < 0) {
36114645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "Failed to create a new network namespace \"%s\": %s\n",
36214645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk			name, strerror(errno));
3630dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		goto out_delete;
3640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
3650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
3660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* Bind the netns last so I can watch for it */
3670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0) {
3680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "Bind /proc/self/ns/net -> %s failed: %s\n",
3690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			netns_path, strerror(errno));
3700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		goto out_delete;
3710dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
372a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	return 0;
3730dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanout_delete:
3740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	netns_delete(argc, argv);
375a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	return -1;
3760dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
3770dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
3780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
3790dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_monitor(int argc, char **argv)
3800dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
3810dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char buf[4096];
3820dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	struct inotify_event *event;
3830dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	int fd;
3840dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fd = inotify_init();
3850dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (fd < 0) {
3860dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "inotify_init failed: %s\n",
3870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			strerror(errno));
388a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
3890dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
390c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk
391c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk	if (create_netns_dir())
392c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk		return -1;
393c1cbb18adbf2f5abc13a840fb9dab7dd7d26b2aavadimk
3940dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) {
3950dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "inotify_add_watch failed: %s\n",
3960dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			strerror(errno));
397a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger		return -1;
3980dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
3990dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	for(;;) {
4000dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		ssize_t len = read(fd, buf, sizeof(buf));
4010dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		if (len < 0) {
4020dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			fprintf(stderr, "read failed: %s\n",
4030dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman				strerror(errno));
404a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger			return -1;
4050dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		}
4060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		for (event = (struct inotify_event *)buf;
4070dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		     (char *)event < &buf[len];
4080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		     event = (struct inotify_event *)((char *)event + sizeof(*event) + event->len)) {
4090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			if (event->mask & IN_CREATE)
4100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman				printf("add %s\n", event->name);
4110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			if (event->mask & IN_DELETE)
4120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman				printf("delete %s\n", event->name);
4130dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		}
4140dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
415a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	return 0;
4160dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
4170dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4180dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanint do_netns(int argc, char **argv)
4190dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
4200dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (argc < 1)
4210dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_list(0, NULL);
4220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if ((matches(*argv, "list") == 0) || (matches(*argv, "show") == 0) ||
4240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	    (matches(*argv, "lst") == 0))
4250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_list(argc-1, argv+1);
4260dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4270dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "help") == 0)
4288e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return usage();
4290dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4300dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "add") == 0)
4310dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_add(argc-1, argv+1);
4320dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4330dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "delete") == 0)
4340dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_delete(argc-1, argv+1);
4350dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4369a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (matches(*argv, "identify") == 0)
4379a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return netns_identify(argc-1, argv+1);
4389a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
4399a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (matches(*argv, "pids") == 0)
4409a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return netns_pids(argc-1, argv+1);
4419a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
4420dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "exec") == 0)
4430dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_exec(argc-1, argv+1);
4440dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4450dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "monitor") == 0)
4460dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_monitor(argc-1, argv+1);
4470dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4480dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv);
449a05f6511f5432257a5efdd8b369735228c167e94Stephen Hemminger	exit(-1);
4500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
451