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> 160dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 170dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include "utils.h" 180dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#include "ip_common.h" 190dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 200dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#define NETNS_RUN_DIR "/var/run/netns" 210dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#define NETNS_ETC_DIR "/etc/netns" 220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#ifndef CLONE_NEWNET 240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ 250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#endif 260dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 270dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#ifndef MNT_DETACH 280dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#define MNT_DETACH 0x00000002 /* Just detach from the tree */ 290dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#endif /* MNT_DETACH */ 300dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 312e8a07f543e6f48f0d0479e3dd4796c18f733e12Eric W. Biederman#ifndef HAVE_SETNS 320dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int setns(int fd, int nstype) 330dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 340dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#ifdef __NR_setns 350dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return syscall(__NR_setns, fd, nstype); 360dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#else 370dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman errno = ENOSYS; 380dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 390dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman#endif 400dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 412e8a07f543e6f48f0d0479e3dd4796c18f733e12Eric W. Biederman#endif /* HAVE_SETNS */ 420dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 430dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 440dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic void usage(void) __attribute__((noreturn)); 450dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 460dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic void usage(void) 470dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 480dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Usage: ip netns list\n"); 490dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, " ip netns add NAME\n"); 500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, " ip netns delete NAME\n"); 510dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, " ip netns exec NAME cmd ...\n"); 520dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, " ip netns monitor\n"); 530dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman exit(-1); 540dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 550dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 560dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanint get_netns_fd(const char *name) 570dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 580dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman char pathbuf[MAXPATHLEN]; 590dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman const char *path, *ptr; 600dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 610dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman path = name; 620dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman ptr = strchr(name, '/'); 630dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (!ptr) { 640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman snprintf(pathbuf, sizeof(pathbuf), "%s/%s", 650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman NETNS_RUN_DIR, name ); 660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman path = pathbuf; 670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return open(path, O_RDONLY); 690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 710dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_list(int argc, char **argv) 720dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 730dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman struct dirent *entry; 740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman DIR *dir; 750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 760dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman dir = opendir(NETNS_RUN_DIR); 770dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (!dir) 780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return 0; 790dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 800dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman while ((entry = readdir(dir)) != NULL) { 810dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (strcmp(entry->d_name, ".") == 0) 820dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman continue; 830dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (strcmp(entry->d_name, "..") == 0) 840dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman continue; 850dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman printf("%s\n", entry->d_name); 860dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman closedir(dir); 880dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return 0; 890dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 900dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 910dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic void bind_etc(const char *name) 920dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 930dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman char etc_netns_path[MAXPATHLEN]; 940dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman char netns_name[MAXPATHLEN]; 950dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman char etc_name[MAXPATHLEN]; 960dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman struct dirent *entry; 970dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman DIR *dir; 980dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 990dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman snprintf(etc_netns_path, sizeof(etc_netns_path), "%s/%s", NETNS_ETC_DIR, name); 1000dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman dir = opendir(etc_netns_path); 1010dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (!dir) 1020dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return; 1030dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1040dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman while ((entry = readdir(dir)) != NULL) { 1050dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (strcmp(entry->d_name, ".") == 0) 1060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman continue; 1070dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (strcmp(entry->d_name, "..") == 0) 1080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman continue; 1090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman snprintf(netns_name, sizeof(netns_name), "%s/%s", etc_netns_path, entry->d_name); 1100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman snprintf(etc_name, sizeof(etc_name), "/etc/%s", entry->d_name); 1110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (mount(netns_name, etc_name, "none", MS_BIND, NULL) < 0) { 1120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Bind %s -> %s failed: %s\n", 1130dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns_name, etc_name, strerror(errno)); 1140dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1150dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1160dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman closedir(dir); 1170dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 1180dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1190dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_exec(int argc, char **argv) 1200dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 1210dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* Setup the proper environment for apps that are not netns 1220dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * aware, and execute a program in that environment. 1230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman */ 1240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman const char *name, *cmd; 1250dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman char net_path[MAXPATHLEN]; 1260dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman int netns; 1270dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1280dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (argc < 1) { 1290dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "No netns name specified\n"); 1300dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 1310dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1320dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (argc < 2) { 1330dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "No cmd specified\n"); 1340dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 1350dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1360dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman name = argv[0]; 1370dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman cmd = argv[1]; 1380dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); 1390dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns = open(net_path, O_RDONLY); 1400dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (netns < 0) { 1410dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Cannot open network namespace: %s\n", 1420dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman strerror(errno)); 1430dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 1440dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1450dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (setns(netns, CLONE_NEWNET) < 0) { 1460dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "seting the network namespace failed: %s\n", 1470dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman strerror(errno)); 1480dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 1490dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1510dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (unshare(CLONE_NEWNS) < 0) { 1520dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "unshare failed: %s\n", strerror(errno)); 1530dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 1540dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1550dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* Mount a version of /sys that describes the network namespace */ 1560dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (umount2("/sys", MNT_DETACH) < 0) { 1570dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno)); 1580dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 1590dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1600dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (mount(name, "/sys", "sysfs", 0, NULL) < 0) { 1610dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno)); 1620dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 1630dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* Setup bind mounts for config files in /etc */ 1660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman bind_etc(name); 1670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (execvp(cmd, argv + 1) < 0) 1690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "exec of %s failed: %s\n", 1700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman cmd, strerror(errno)); 1710dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman exit(-1); 1720dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 1730dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_delete(int argc, char **argv) 1750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 1760dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman const char *name; 1770dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman char netns_path[MAXPATHLEN]; 1780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1790dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (argc < 1) { 1800dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "No netns name specified\n"); 1810dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 1820dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1830dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1840dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman name = argv[0]; 1850dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name); 1860dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman umount2(netns_path, MNT_DETACH); 1870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (unlink(netns_path) < 0) { 1880dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Cannot remove %s: %s\n", 1890dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns_path, strerror(errno)); 1900dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 1910dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 1920dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return 0; 1930dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 1940dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 1950dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_add(int argc, char **argv) 1960dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 1970dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* This function creates a new network namespace and 1980dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * a new mount namespace and bind them into a well known 1990dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * location in the filesystem based on the name provided. 2000dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * 2010dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * The mount namespace is created so that any necessary 2020dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * userspace tweaks like remounting /sys, or bind mounting 2030dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman * a new /etc/resolv.conf can be shared between uers. 2040dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman */ 2050dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman char netns_path[MAXPATHLEN]; 2060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman const char *name; 207223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman int fd; 2080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (argc < 1) { 2100dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "No netns name specified\n"); 2110dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 2120dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 2130dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman name = argv[0]; 2140dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2150dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name); 2160dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2170dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* Create the base netns directory if it doesn't exist */ 2180dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); 2190dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2200dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* Create the filesystem state */ 221223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0); 222223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman if (fd < 0) { 2230dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Could not create %s: %s\n", 2240dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns_path, strerror(errno)); 225223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman return -1; 2260dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 227223f4d8ea6803bd9288d54c819e54a88a63c1730Eric W. Biederman close(fd); 2280dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (unshare(CLONE_NEWNET) < 0) { 2290dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Failed to create a new network namespace: %s\n", 2300dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman strerror(errno)); 2310dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman goto out_delete; 2320dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 2330dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2340dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman /* Bind the netns last so I can watch for it */ 2350dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0) { 2360dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Bind /proc/self/ns/net -> %s failed: %s\n", 2370dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns_path, strerror(errno)); 2380dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman goto out_delete; 2390dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 2400dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return 0; 2410dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanout_delete: 2420dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman netns_delete(argc, argv); 2430dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman exit(-1); 2440dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 2450dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 2460dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2470dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2480dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanstatic int netns_monitor(int argc, char **argv) 2490dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 2500dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman char buf[4096]; 2510dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman struct inotify_event *event; 2520dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman int fd; 2530dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fd = inotify_init(); 2540dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (fd < 0) { 2550dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "inotify_init failed: %s\n", 2560dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman strerror(errno)); 2570dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 2580dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 2590dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) { 2600dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "inotify_add_watch failed: %s\n", 2610dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman strerror(errno)); 2620dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 2630dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 2640dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman for(;;) { 2650dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman ssize_t len = read(fd, buf, sizeof(buf)); 2660dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (len < 0) { 2670dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "read failed: %s\n", 2680dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman strerror(errno)); 2690dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return -1; 2700dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 2710dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman for (event = (struct inotify_event *)buf; 2720dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman (char *)event < &buf[len]; 2730dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman event = (struct inotify_event *)((char *)event + sizeof(*event) + event->len)) { 2740dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (event->mask & IN_CREATE) 2750dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman printf("add %s\n", event->name); 2760dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (event->mask & IN_DELETE) 2770dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman printf("delete %s\n", event->name); 2780dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 2790dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman } 2800dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return 0; 2810dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 2820dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2830dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biedermanint do_netns(int argc, char **argv) 2840dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman{ 2850dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (argc < 1) 2860dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_list(0, NULL); 2870dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2880dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if ((matches(*argv, "list") == 0) || (matches(*argv, "show") == 0) || 2890dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman (matches(*argv, "lst") == 0)) 2900dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_list(argc-1, argv+1); 2910dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2920dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "help") == 0) 2930dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman usage(); 2940dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2950dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "add") == 0) 2960dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_add(argc-1, argv+1); 2970dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 2980dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "delete") == 0) 2990dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_delete(argc-1, argv+1); 3000dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 3010dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "exec") == 0) 3020dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_exec(argc-1, argv+1); 3030dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 3040dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman if (matches(*argv, "monitor") == 0) 3050dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman return netns_monitor(argc-1, argv+1); 3060dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman 3070dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv); 3080dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman exit(-1); 3090dc34c7713bb7055378fe5cbc720d63d0db572a1Eric W. Biederman} 310