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