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