ipnetns.c revision 95592b47be09bd9347026ff9aa298fc097733e56
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"
200dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
210dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#define NETNS_RUN_DIR "/var/run/netns"
220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#define NETNS_ETC_DIR "/etc/netns"
230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#ifndef CLONE_NEWNET
250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#define CLONE_NEWNET 0x40000000	/* New network namespace (lo, device, names sockets, etc) */
260dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#endif
270dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
280dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#ifndef MNT_DETACH
290dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#define MNT_DETACH	0x00000002	/* Just detach from the tree */
300dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#endif /* MNT_DETACH */
310dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
3203fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger/* sys/mount.h may be out too old to have these */
3303fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger#ifndef MS_REC
3403fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger#define MS_REC		16384
3503fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger#endif
3603fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger
3703fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger#ifndef MS_SLAVE
3803fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger#define MS_SLAVE	(1 << 19)
3903fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger#endif
4003fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger
4103fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger#ifndef MS_SHARED
4203fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger#define MS_SHARED	(1 << 20)
4303fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger#endif
4403fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger
4595592b47be09bd9347026ff9aa298fc097733e56JunweiZhangextern char *batch_file;
4603fdb011dd661315a83998af8af779d8f089e3feStephen Hemminger
472e8a07f543e6f48f0d0479e3dd4796c18f733e12Eric W. Biederman#ifndef HAVE_SETNS
480dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int setns(int fd, int nstype)
490dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#ifdef __NR_setns
510dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	return syscall(__NR_setns, fd, nstype);
520dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#else
530dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	errno = ENOSYS;
540dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	return -1;
550dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#endif
560dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
572e8a07f543e6f48f0d0479e3dd4796c18f733e12Eric W. Biederman#endif /* HAVE_SETNS */
580dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
598e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biedermanstatic int usage(void)
600dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
610dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "Usage: ip netns list\n");
620dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "       ip netns add NAME\n");
630dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "       ip netns delete NAME\n");
649a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	fprintf(stderr, "       ip netns identify PID\n");
659a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	fprintf(stderr, "       ip netns pids NAME\n");
660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "       ip netns exec NAME cmd ...\n");
670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "       ip netns monitor\n");
688e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman	return EXIT_FAILURE;
690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
710dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanint get_netns_fd(const char *name)
720dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
730dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char pathbuf[MAXPATHLEN];
740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	const char *path, *ptr;
750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
760dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	path = name;
770dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	ptr = strchr(name, '/');
780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (!ptr) {
790dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		snprintf(pathbuf, sizeof(pathbuf), "%s/%s",
800dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			NETNS_RUN_DIR, name );
810dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		path = pathbuf;
820dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
830dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	return open(path, O_RDONLY);
840dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
850dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
860dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_list(int argc, char **argv)
870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
880dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	struct dirent *entry;
890dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	DIR *dir;
900dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
910dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	dir = opendir(NETNS_RUN_DIR);
920dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (!dir)
938e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_SUCCESS;
940dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
950dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	while ((entry = readdir(dir)) != NULL) {
960dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		if (strcmp(entry->d_name, ".") == 0)
970dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			continue;
980dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		if (strcmp(entry->d_name, "..") == 0)
990dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			continue;
1000dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		printf("%s\n", entry->d_name);
1010dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
1020dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	closedir(dir);
1038e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman	return EXIT_SUCCESS;
1040dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
1050dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
1060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic void bind_etc(const char *name)
1070dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
1080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char etc_netns_path[MAXPATHLEN];
1090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char netns_name[MAXPATHLEN];
1100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char etc_name[MAXPATHLEN];
1110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	struct dirent *entry;
1120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	DIR *dir;
1130dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
1140dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	snprintf(etc_netns_path, sizeof(etc_netns_path), "%s/%s", NETNS_ETC_DIR, name);
1150dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	dir = opendir(etc_netns_path);
1160dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (!dir)
1170dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return;
1180dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
1190dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	while ((entry = readdir(dir)) != NULL) {
1200dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		if (strcmp(entry->d_name, ".") == 0)
1210dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			continue;
1220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		if (strcmp(entry->d_name, "..") == 0)
1230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			continue;
1240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		snprintf(netns_name, sizeof(netns_name), "%s/%s", etc_netns_path, entry->d_name);
1250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		snprintf(etc_name, sizeof(etc_name), "/etc/%s", entry->d_name);
1260dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		if (mount(netns_name, etc_name, "none", MS_BIND, NULL) < 0) {
1270dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			fprintf(stderr, "Bind %s -> %s failed: %s\n",
1280dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman				netns_name, etc_name, strerror(errno));
1290dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		}
1300dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
1310dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	closedir(dir);
1320dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
1330dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
1340dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_exec(int argc, char **argv)
1350dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
1360dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* Setup the proper environment for apps that are not netns
1370dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * aware, and execute a program in that environment.
1380dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 */
1390dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	const char *name, *cmd;
1400dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char net_path[MAXPATHLEN];
1410dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	int netns;
1420dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
1430dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (argc < 1) {
1440dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "No netns name specified\n");
1458e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
1460dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
1470dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (argc < 2) {
14814645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "No command specified\n");
1498e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
1500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
1510dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	name = argv[0];
1520dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	cmd = argv[1];
1530dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
154bcb9d403196944d12b7ec095d66a805ea786fd2eAndrey Vagin	netns = open(net_path, O_RDONLY | O_CLOEXEC);
1550dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (netns < 0) {
15614645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
1574395d48c78a77a99c5a8618403211032356fe552Eric W. Biederman			name, strerror(errno));
1588e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
1590dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
1600dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (setns(netns, CLONE_NEWNET) < 0) {
16114645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "seting the network namespace \"%s\" failed: %s\n",
16214645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk			name, strerror(errno));
1638e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
1640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
1650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
1660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (unshare(CLONE_NEWNS) < 0) {
1670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "unshare failed: %s\n", strerror(errno));
1688e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
1690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
170144e6ce1679a768e987230efb4afa402a5ab58acEric W. Biederman	/* Don't let any mounts propogate back to the parent */
171144e6ce1679a768e987230efb4afa402a5ab58acEric W. Biederman	if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) {
17214645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n",
173144e6ce1679a768e987230efb4afa402a5ab58acEric W. Biederman			strerror(errno));
1748e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
175144e6ce1679a768e987230efb4afa402a5ab58acEric W. Biederman	}
1760dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* Mount a version of /sys that describes the network namespace */
1770dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (umount2("/sys", MNT_DETACH) < 0) {
1780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno));
1798e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
1800dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
1810dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (mount(name, "/sys", "sysfs", 0, NULL) < 0) {
1820dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno));
1838e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
1840dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
1850dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
1860dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* Setup bind mounts for config files in /etc */
1870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	bind_etc(name);
1880dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
18995592b47be09bd9347026ff9aa298fc097733e56JunweiZhang	fflush(stdout);
19095592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
19195592b47be09bd9347026ff9aa298fc097733e56JunweiZhang	if (batch_file) {
19295592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		int status;
19395592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		pid_t pid;
19495592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
19595592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		pid = fork();
19695592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		if (pid < 0) {
19795592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			perror("fork");
19895592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			return EXIT_FAILURE;
19995592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		}
20095592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
20195592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		if (pid != 0) {
20295592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			/* Parent  */
20395592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			if (waitpid(pid, &status, 0) < 0) {
20495592b47be09bd9347026ff9aa298fc097733e56JunweiZhang				perror("waitpid");
20595592b47be09bd9347026ff9aa298fc097733e56JunweiZhang				return EXIT_FAILURE;
20695592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			}
20795592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
20895592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			if (WIFEXITED(status)) {
20995592b47be09bd9347026ff9aa298fc097733e56JunweiZhang				/* ip must returns the status of the child,
21095592b47be09bd9347026ff9aa298fc097733e56JunweiZhang				 * but do_cmd() will add a minus to this,
21195592b47be09bd9347026ff9aa298fc097733e56JunweiZhang				 * so let's add another one here to cancel it.
21295592b47be09bd9347026ff9aa298fc097733e56JunweiZhang				 */
21395592b47be09bd9347026ff9aa298fc097733e56JunweiZhang				return -WEXITSTATUS(status);
21495592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			}
21595592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
21695592b47be09bd9347026ff9aa298fc097733e56JunweiZhang			return EXIT_FAILURE;
21795592b47be09bd9347026ff9aa298fc097733e56JunweiZhang		}
21895592b47be09bd9347026ff9aa298fc097733e56JunweiZhang	}
21995592b47be09bd9347026ff9aa298fc097733e56JunweiZhang
2200dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (execvp(cmd, argv + 1)  < 0)
22114645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "exec of \"%s\" failed: %s\n",
2220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			cmd, strerror(errno));
22395592b47be09bd9347026ff9aa298fc097733e56JunweiZhang	_exit(EXIT_FAILURE);
2240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
2250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
2269a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biedermanstatic int is_pid(const char *str)
2279a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman{
2289a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	int ch;
2299a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	for (; (ch = *str); str++) {
2309a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (!isdigit(ch))
2319a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			return 0;
2329a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2339a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	return 1;
2349a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman}
2359a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2369a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biedermanstatic int netns_pids(int argc, char **argv)
2379a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman{
2389a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	const char *name;
2399a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	char net_path[MAXPATHLEN];
2409a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	int netns;
2419a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	struct stat netst;
2429a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	DIR *dir;
2439a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	struct dirent *entry;
2449a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2459a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (argc < 1) {
2469a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "No netns name specified\n");
2479a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
2489a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2499a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (argc > 1) {
2509a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "extra arguments specified\n");
2519a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
2529a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2539a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2549a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	name = argv[0];
2559a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
2569a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	netns = open(net_path, O_RDONLY);
2579a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (netns < 0) {
2589a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Cannot open network namespace: %s\n",
2599a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
2609a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
2619a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2629a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (fstat(netns, &netst) < 0) {
2639a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Stat of netns failed: %s\n",
2649a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
2659a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
2669a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2679a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	dir = opendir("/proc/");
2689a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (!dir) {
2699a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Open of /proc failed: %s\n",
2709a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
2719a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
2729a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2739a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	while((entry = readdir(dir))) {
2749a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		char pid_net_path[MAXPATHLEN];
2759a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		struct stat st;
2769a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (!is_pid(entry->d_name))
2779a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
2789a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%s/ns/net",
2799a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			entry->d_name);
2809a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (stat(pid_net_path, &st) != 0)
2819a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
2829a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if ((st.st_dev == netst.st_dev) &&
2839a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		    (st.st_ino == netst.st_ino)) {
2849a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			printf("%s\n", entry->d_name);
2859a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		}
2869a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
2879a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	closedir(dir);
2889a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	return EXIT_SUCCESS;
2899a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2909a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman}
2919a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
2929a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biedermanstatic int netns_identify(int argc, char **argv)
2939a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman{
2949a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	const char *pidstr;
2959a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	char net_path[MAXPATHLEN];
2969a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	int netns;
2979a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	struct stat netst;
2989a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	DIR *dir;
2999a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	struct dirent *entry;
3009a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3019a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (argc < 1) {
3029a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "No pid specified\n");
3039a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
3049a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
3059a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (argc > 1) {
3069a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "extra arguments specified\n");
3079a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
3089a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
3099a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	pidstr = argv[0];
3109a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3119a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (!is_pid(pidstr)) {
3129a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Specified string '%s' is not a pid\n",
3139a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			pidstr);
3149a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
3159a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
3169a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3179a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr);
3189a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	netns = open(net_path, O_RDONLY);
3199a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (netns < 0) {
3209a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Cannot open network namespace: %s\n",
3219a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
3229a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
3239a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
3249a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (fstat(netns, &netst) < 0) {
3259a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Stat of netns failed: %s\n",
3269a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			strerror(errno));
3279a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
3289a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
3299a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	dir = opendir(NETNS_RUN_DIR);
3309a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (!dir) {
3319a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		/* Succeed treat a missing directory as an empty directory */
3329a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (errno == ENOENT)
3339a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			return EXIT_SUCCESS;
3349a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3359a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		fprintf(stderr, "Failed to open directory %s:%s\n",
3369a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			NETNS_RUN_DIR, strerror(errno));
3379a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return EXIT_FAILURE;
3389a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
3399a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3409a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	while((entry = readdir(dir))) {
3419a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		char name_path[MAXPATHLEN];
3429a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		struct stat st;
3439a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3449a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (strcmp(entry->d_name, ".") == 0)
3459a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
3469a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (strcmp(entry->d_name, "..") == 0)
3479a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
3489a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3499a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		snprintf(name_path, sizeof(name_path), "%s/%s",	NETNS_RUN_DIR,
3509a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			entry->d_name);
3519a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3529a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if (stat(name_path, &st) != 0)
3539a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			continue;
3549a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3559a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		if ((st.st_dev == netst.st_dev) &&
3569a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		    (st.st_ino == netst.st_ino)) {
3579a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman			printf("%s\n", entry->d_name);
3589a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		}
3599a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	}
3609a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	closedir(dir);
3619a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	return EXIT_SUCCESS;
3629a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3639a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman}
3649a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
3650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_delete(int argc, char **argv)
3660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
3670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	const char *name;
3680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char netns_path[MAXPATHLEN];
3690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
3700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (argc < 1) {
3710dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "No netns name specified\n");
3728e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
3730dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
3740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
3750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	name = argv[0];
3760dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
3770dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	umount2(netns_path, MNT_DETACH);
3780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (unlink(netns_path) < 0) {
37914645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
3800dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			netns_path, strerror(errno));
3818e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
3820dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
3838e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman	return EXIT_SUCCESS;
3840dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
3850dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
3860dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_add(int argc, char **argv)
3870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
3880dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* This function creates a new network namespace and
3890dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * a new mount namespace and bind them into a well known
3900dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * location in the filesystem based on the name provided.
3910dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 *
3920dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * The mount namespace is created so that any necessary
3930dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * userspace tweaks like remounting /sys, or bind mounting
3940dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 * a new /etc/resolv.conf can be shared between uers.
3950dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	 */
3960dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char netns_path[MAXPATHLEN];
3970dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	const char *name;
398223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman	int fd;
39958a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	int made_netns_run_dir_mount = 0;
4000dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4010dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (argc < 1) {
4020dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "No netns name specified\n");
4038e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
4040dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
4050dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	name = argv[0];
4060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4070dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
4080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* Create the base netns directory if it doesn't exist */
4100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
4110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
41258a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	/* Make it possible for network namespace mounts to propogate between
41358a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 * mount namespaces.  This makes it likely that a unmounting a network
41458a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 * namespace file in one namespace will unmount the network namespace
41558a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 * file in all namespaces allowing the network namespace to be freed
41658a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 * sooner.
41758a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	 */
41858a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) {
41958a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		/* Fail unless we need to make the mount point */
42058a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		if (errno != EINVAL || made_netns_run_dir_mount) {
42158a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman			fprintf(stderr, "mount --make-shared %s failed: %s\n",
42258a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman				NETNS_RUN_DIR, strerror(errno));
42358a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman			return EXIT_FAILURE;
42458a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		}
42558a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman
42658a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		/* Upgrade NETNS_RUN_DIR to a mount point */
42758a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND, NULL)) {
42858a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman			fprintf(stderr, "mount --bind %s %s failed: %s\n",
42958a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman				NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
43058a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman			return EXIT_FAILURE;
43158a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		}
43258a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman		made_netns_run_dir_mount = 1;
43358a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman	}
43458a3e8270fe72f8ed92687d3a3132c2a708582ddEric W. Biederman
4350dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* Create the filesystem state */
436223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman	fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
437223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman	if (fd < 0) {
43814645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "Cannot not create namespace file \"%s\": %s\n",
4390dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			netns_path, strerror(errno));
4408e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
4410dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
442223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman	close(fd);
4430dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (unshare(CLONE_NEWNET) < 0) {
44414645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "Failed to create a new network namespace \"%s\": %s\n",
44514645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk			name, strerror(errno));
4460dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		goto out_delete;
4470dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
4480dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4490dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	/* Bind the netns last so I can watch for it */
4500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0) {
4510dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "Bind /proc/self/ns/net -> %s failed: %s\n",
4520dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			netns_path, strerror(errno));
4530dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		goto out_delete;
4540dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
4558e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman	return EXIT_SUCCESS;
4560dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanout_delete:
4570dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	netns_delete(argc, argv);
4588e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman	return EXIT_FAILURE;
4590dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
4600dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4610dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4620dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_monitor(int argc, char **argv)
4630dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
4640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	char buf[4096];
4650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	struct inotify_event *event;
4660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	int fd;
4670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fd = inotify_init();
4680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (fd < 0) {
4690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "inotify_init failed: %s\n",
4700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			strerror(errno));
4718e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
4720dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
4730dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) {
4740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		fprintf(stderr, "inotify_add_watch failed: %s\n",
4750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			strerror(errno));
4768e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return EXIT_FAILURE;
4770dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
4780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	for(;;) {
4790dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		ssize_t len = read(fd, buf, sizeof(buf));
4800dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		if (len < 0) {
4810dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			fprintf(stderr, "read failed: %s\n",
4820dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman				strerror(errno));
4838e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman			return EXIT_FAILURE;
4840dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		}
4850dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		for (event = (struct inotify_event *)buf;
4860dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		     (char *)event < &buf[len];
4870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		     event = (struct inotify_event *)((char *)event + sizeof(*event) + event->len)) {
4880dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			if (event->mask & IN_CREATE)
4890dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman				printf("add %s\n", event->name);
4900dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman			if (event->mask & IN_DELETE)
4910dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman				printf("delete %s\n", event->name);
4920dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		}
4930dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	}
4948e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman	return EXIT_SUCCESS;
4950dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
4960dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
4970dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanint do_netns(int argc, char **argv)
4980dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{
4990dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (argc < 1)
5000dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_list(0, NULL);
5010dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
5020dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if ((matches(*argv, "list") == 0) || (matches(*argv, "show") == 0) ||
5030dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	    (matches(*argv, "lst") == 0))
5040dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_list(argc-1, argv+1);
5050dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
5060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "help") == 0)
5078e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman		return usage();
5080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
5090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "add") == 0)
5100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_add(argc-1, argv+1);
5110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
5120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "delete") == 0)
5130dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_delete(argc-1, argv+1);
5140dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
5159a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (matches(*argv, "identify") == 0)
5169a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return netns_identify(argc-1, argv+1);
5179a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
5189a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman	if (matches(*argv, "pids") == 0)
5199a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman		return netns_pids(argc-1, argv+1);
5209a7b3d91b69ea9c3c128d973c4bda2324da1a795Eric W. Biederman
5210dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "exec") == 0)
5220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_exec(argc-1, argv+1);
5230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
5240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	if (matches(*argv, "monitor") == 0)
5250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman		return netns_monitor(argc-1, argv+1);
5260dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman
5270dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman	fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv);
5288e2d47dce288d5a60d8c67f537860a3683d36df6Eric W. Biederman	return EXIT_FAILURE;
5290dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman}
530