1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * namespace.c
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker */
9*de1e4e89SAndroid Build Coastguard Worker
10*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
11*de1e4e89SAndroid Build Coastguard Worker #include <dirent.h>
12*de1e4e89SAndroid Build Coastguard Worker #include <limits.h>
13*de1e4e89SAndroid Build Coastguard Worker
14*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
15*de1e4e89SAndroid Build Coastguard Worker #include "namespace.h"
16*de1e4e89SAndroid Build Coastguard Worker
bind_etc(const char * name)17*de1e4e89SAndroid Build Coastguard Worker static void bind_etc(const char *name)
18*de1e4e89SAndroid Build Coastguard Worker {
19*de1e4e89SAndroid Build Coastguard Worker char etc_netns_path[PATH_MAX];
20*de1e4e89SAndroid Build Coastguard Worker char netns_name[PATH_MAX];
21*de1e4e89SAndroid Build Coastguard Worker char etc_name[PATH_MAX];
22*de1e4e89SAndroid Build Coastguard Worker struct dirent *entry;
23*de1e4e89SAndroid Build Coastguard Worker DIR *dir;
24*de1e4e89SAndroid Build Coastguard Worker
25*de1e4e89SAndroid Build Coastguard Worker snprintf(etc_netns_path, sizeof(etc_netns_path), "%s/%s", NETNS_ETC_DIR, name);
26*de1e4e89SAndroid Build Coastguard Worker dir = opendir(etc_netns_path);
27*de1e4e89SAndroid Build Coastguard Worker if (!dir)
28*de1e4e89SAndroid Build Coastguard Worker return;
29*de1e4e89SAndroid Build Coastguard Worker
30*de1e4e89SAndroid Build Coastguard Worker while ((entry = readdir(dir)) != NULL) {
31*de1e4e89SAndroid Build Coastguard Worker if (strcmp(entry->d_name, ".") == 0)
32*de1e4e89SAndroid Build Coastguard Worker continue;
33*de1e4e89SAndroid Build Coastguard Worker if (strcmp(entry->d_name, "..") == 0)
34*de1e4e89SAndroid Build Coastguard Worker continue;
35*de1e4e89SAndroid Build Coastguard Worker snprintf(netns_name, sizeof(netns_name), "%s/%s", etc_netns_path, entry->d_name);
36*de1e4e89SAndroid Build Coastguard Worker snprintf(etc_name, sizeof(etc_name), "/etc/%s", entry->d_name);
37*de1e4e89SAndroid Build Coastguard Worker if (mount(netns_name, etc_name, "none", MS_BIND, NULL) < 0) {
38*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Bind %s -> %s failed: %s\n",
39*de1e4e89SAndroid Build Coastguard Worker netns_name, etc_name, strerror(errno));
40*de1e4e89SAndroid Build Coastguard Worker }
41*de1e4e89SAndroid Build Coastguard Worker }
42*de1e4e89SAndroid Build Coastguard Worker closedir(dir);
43*de1e4e89SAndroid Build Coastguard Worker }
44*de1e4e89SAndroid Build Coastguard Worker
netns_switch(char * name)45*de1e4e89SAndroid Build Coastguard Worker int netns_switch(char *name)
46*de1e4e89SAndroid Build Coastguard Worker {
47*de1e4e89SAndroid Build Coastguard Worker char net_path[PATH_MAX];
48*de1e4e89SAndroid Build Coastguard Worker int netns;
49*de1e4e89SAndroid Build Coastguard Worker
50*de1e4e89SAndroid Build Coastguard Worker snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
51*de1e4e89SAndroid Build Coastguard Worker netns = open(net_path, O_RDONLY | O_CLOEXEC);
52*de1e4e89SAndroid Build Coastguard Worker if (netns < 0) {
53*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
54*de1e4e89SAndroid Build Coastguard Worker name, strerror(errno));
55*de1e4e89SAndroid Build Coastguard Worker return -1;
56*de1e4e89SAndroid Build Coastguard Worker }
57*de1e4e89SAndroid Build Coastguard Worker
58*de1e4e89SAndroid Build Coastguard Worker if (setns(netns, CLONE_NEWNET) < 0) {
59*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "setting the network namespace \"%s\" failed: %s\n",
60*de1e4e89SAndroid Build Coastguard Worker name, strerror(errno));
61*de1e4e89SAndroid Build Coastguard Worker close(netns);
62*de1e4e89SAndroid Build Coastguard Worker return -1;
63*de1e4e89SAndroid Build Coastguard Worker }
64*de1e4e89SAndroid Build Coastguard Worker close(netns);
65*de1e4e89SAndroid Build Coastguard Worker
66*de1e4e89SAndroid Build Coastguard Worker if (unshare(CLONE_NEWNS) < 0) {
67*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "unshare failed: %s\n", strerror(errno));
68*de1e4e89SAndroid Build Coastguard Worker return -1;
69*de1e4e89SAndroid Build Coastguard Worker }
70*de1e4e89SAndroid Build Coastguard Worker /* Don't let any mounts propagate back to the parent */
71*de1e4e89SAndroid Build Coastguard Worker if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) {
72*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n",
73*de1e4e89SAndroid Build Coastguard Worker strerror(errno));
74*de1e4e89SAndroid Build Coastguard Worker return -1;
75*de1e4e89SAndroid Build Coastguard Worker }
76*de1e4e89SAndroid Build Coastguard Worker /* Mount a version of /sys that describes the network namespace */
77*de1e4e89SAndroid Build Coastguard Worker if (umount2("/sys", MNT_DETACH) < 0) {
78*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno));
79*de1e4e89SAndroid Build Coastguard Worker return -1;
80*de1e4e89SAndroid Build Coastguard Worker }
81*de1e4e89SAndroid Build Coastguard Worker if (mount(name, "/sys", "sysfs", 0, NULL) < 0) {
82*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno));
83*de1e4e89SAndroid Build Coastguard Worker return -1;
84*de1e4e89SAndroid Build Coastguard Worker }
85*de1e4e89SAndroid Build Coastguard Worker
86*de1e4e89SAndroid Build Coastguard Worker /* Setup bind mounts for config files in /etc */
87*de1e4e89SAndroid Build Coastguard Worker bind_etc(name);
88*de1e4e89SAndroid Build Coastguard Worker return 0;
89*de1e4e89SAndroid Build Coastguard Worker }
90*de1e4e89SAndroid Build Coastguard Worker
netns_get_fd(const char * name)91*de1e4e89SAndroid Build Coastguard Worker int netns_get_fd(const char *name)
92*de1e4e89SAndroid Build Coastguard Worker {
93*de1e4e89SAndroid Build Coastguard Worker char pathbuf[PATH_MAX];
94*de1e4e89SAndroid Build Coastguard Worker const char *path, *ptr;
95*de1e4e89SAndroid Build Coastguard Worker
96*de1e4e89SAndroid Build Coastguard Worker path = name;
97*de1e4e89SAndroid Build Coastguard Worker ptr = strchr(name, '/');
98*de1e4e89SAndroid Build Coastguard Worker if (!ptr) {
99*de1e4e89SAndroid Build Coastguard Worker snprintf(pathbuf, sizeof(pathbuf), "%s/%s",
100*de1e4e89SAndroid Build Coastguard Worker NETNS_RUN_DIR, name );
101*de1e4e89SAndroid Build Coastguard Worker path = pathbuf;
102*de1e4e89SAndroid Build Coastguard Worker }
103*de1e4e89SAndroid Build Coastguard Worker return open(path, O_RDONLY);
104*de1e4e89SAndroid Build Coastguard Worker }
105*de1e4e89SAndroid Build Coastguard Worker
netns_foreach(int (* func)(char * nsname,void * arg),void * arg)106*de1e4e89SAndroid Build Coastguard Worker int netns_foreach(int (*func)(char *nsname, void *arg), void *arg)
107*de1e4e89SAndroid Build Coastguard Worker {
108*de1e4e89SAndroid Build Coastguard Worker DIR *dir;
109*de1e4e89SAndroid Build Coastguard Worker struct dirent *entry;
110*de1e4e89SAndroid Build Coastguard Worker
111*de1e4e89SAndroid Build Coastguard Worker dir = opendir(NETNS_RUN_DIR);
112*de1e4e89SAndroid Build Coastguard Worker if (!dir)
113*de1e4e89SAndroid Build Coastguard Worker return -1;
114*de1e4e89SAndroid Build Coastguard Worker
115*de1e4e89SAndroid Build Coastguard Worker while ((entry = readdir(dir)) != NULL) {
116*de1e4e89SAndroid Build Coastguard Worker if (strcmp(entry->d_name, ".") == 0)
117*de1e4e89SAndroid Build Coastguard Worker continue;
118*de1e4e89SAndroid Build Coastguard Worker if (strcmp(entry->d_name, "..") == 0)
119*de1e4e89SAndroid Build Coastguard Worker continue;
120*de1e4e89SAndroid Build Coastguard Worker if (func(entry->d_name, arg))
121*de1e4e89SAndroid Build Coastguard Worker break;
122*de1e4e89SAndroid Build Coastguard Worker }
123*de1e4e89SAndroid Build Coastguard Worker
124*de1e4e89SAndroid Build Coastguard Worker closedir(dir);
125*de1e4e89SAndroid Build Coastguard Worker return 0;
126*de1e4e89SAndroid Build Coastguard Worker }
127