xref: /aosp_15_r20/external/iproute2/lib/namespace.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
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