1 /*
2  * Zebra NS collector and notifier for Network NameSpaces
3  * Copyright (C) 2017 6WIND
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the Free
7  * Software Foundation; either version 2 of the License, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; see the file COPYING; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include <zebra.h>
21 
22 #ifdef HAVE_NETLINK
23 #ifdef HAVE_NETNS
24 #undef _GNU_SOURCE
25 #define _GNU_SOURCE
26 
27 #include <sched.h>
28 #endif
29 #include <dirent.h>
30 #include <sys/inotify.h>
31 #include <sys/stat.h>
32 
33 #include "thread.h"
34 #include "ns.h"
35 #include "command.h"
36 #include "memory.h"
37 #include "lib_errors.h"
38 
39 #include "zebra_router.h"
40 #include "zebra_memory.h"
41 #endif /* defined(HAVE_NETLINK) */
42 
43 #include "zebra_netns_notify.h"
44 #include "zebra_netns_id.h"
45 #include "zebra_errors.h"
46 
47 #ifdef HAVE_NETLINK
48 
49 /* upon creation of folder under /var/run/netns,
50  * wait that netns context is bound to
51  * that folder 10 seconds
52  */
53 #define ZEBRA_NS_POLLING_INTERVAL_MSEC     1000
54 #define ZEBRA_NS_POLLING_MAX_RETRIES  200
55 
56 DEFINE_MTYPE_STATIC(ZEBRA, NETNS_MISC, "ZebraNetNSInfo")
57 static struct thread *zebra_netns_notify_current;
58 
59 struct zebra_netns_info {
60 	const char *netnspath;
61 	unsigned int retries;
62 };
63 
64 static int zebra_ns_ready_read(struct thread *t);
65 static void zebra_ns_notify_create_context_from_entry_name(const char *name);
66 static int zebra_ns_continue_read(struct zebra_netns_info *zns_info,
67 				  int stop_retry);
68 static int zebra_ns_notify_read(struct thread *t);
69 
zebra_ns_notify_create_context_from_entry_name(const char * name)70 static void zebra_ns_notify_create_context_from_entry_name(const char *name)
71 {
72 	char *netnspath = ns_netns_pathname(NULL, name);
73 	struct vrf *vrf;
74 	int ret;
75 	ns_id_t ns_id, ns_id_external, ns_id_relative = NS_UNKNOWN;
76 	struct ns *default_ns;
77 
78 	if (netnspath == NULL)
79 		return;
80 
81 	frr_with_privs(&zserv_privs) {
82 		ns_id = zebra_ns_id_get(netnspath, -1);
83 	}
84 	if (ns_id == NS_UNKNOWN)
85 		return;
86 	ns_id_external = ns_map_nsid_with_external(ns_id, true);
87 	/* if VRF with NS ID already present */
88 	vrf = vrf_lookup_by_id((vrf_id_t)ns_id_external);
89 	if (vrf) {
90 		zlog_debug(
91 			"NS notify : same NSID used by VRF %s. Ignore NS %s creation",
92 			vrf->name, netnspath);
93 		return;
94 	}
95 	if (vrf_handler_create(NULL, name, &vrf) != CMD_SUCCESS) {
96 		flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED,
97 			  "NS notify : failed to create VRF %s", name);
98 		ns_map_nsid_with_external(ns_id, false);
99 		return;
100 	}
101 
102 	default_ns = ns_get_default();
103 
104 	/* force kernel ns_id creation in that new vrf */
105 	frr_with_privs(&zserv_privs) {
106 		ns_switch_to_netns(netnspath);
107 		ns_id_relative = zebra_ns_id_get(NULL, default_ns->fd);
108 		ns_switchback_to_initial();
109 	}
110 
111 	frr_with_privs(&zserv_privs) {
112 		ret = vrf_netns_handler_create(NULL, vrf, netnspath,
113 					       ns_id_external,
114 					       ns_id,
115 					       ns_id_relative);
116 	}
117 	if (ret != CMD_SUCCESS) {
118 		flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED,
119 			  "NS notify : failed to create NS %s", netnspath);
120 		ns_map_nsid_with_external(ns_id, false);
121 		vrf_delete(vrf);
122 		return;
123 	}
124 	zlog_info("NS notify : created VRF %s NS %s", name, netnspath);
125 }
126 
zebra_ns_continue_read(struct zebra_netns_info * zns_info,int stop_retry)127 static int zebra_ns_continue_read(struct zebra_netns_info *zns_info,
128 				  int stop_retry)
129 {
130 	void *ns_path_ptr = (void *)zns_info->netnspath;
131 
132 	if (stop_retry) {
133 		XFREE(MTYPE_NETNS_MISC, ns_path_ptr);
134 		XFREE(MTYPE_NETNS_MISC, zns_info);
135 		return 0;
136 	}
137 	thread_add_timer_msec(zrouter.master, zebra_ns_ready_read,
138 			      (void *)zns_info, ZEBRA_NS_POLLING_INTERVAL_MSEC,
139 			      NULL);
140 	return 0;
141 }
142 
zebra_ns_delete(char * name)143 static int zebra_ns_delete(char *name)
144 {
145 	struct vrf *vrf = vrf_lookup_by_name(name);
146 	struct ns *ns;
147 
148 	if (!vrf) {
149 		flog_warn(EC_ZEBRA_NS_DELETION_FAILED_NO_VRF,
150 			  "NS notify : no VRF found using NS %s", name);
151 		return 0;
152 	}
153 	/* Clear configured flag and invoke delete. */
154 	UNSET_FLAG(vrf->status, VRF_CONFIGURED);
155 	ns = (struct ns *)vrf->ns_ctxt;
156 	/* the deletion order is the same
157 	 * as the one used when siging signal is received
158 	 */
159 	vrf_delete(vrf);
160 	if (ns)
161 		ns_delete(ns);
162 
163 	zlog_info("NS notify : deleted VRF %s", name);
164 	return 0;
165 }
166 
zebra_ns_notify_self_identify(struct stat * netst)167 static int zebra_ns_notify_self_identify(struct stat *netst)
168 {
169 	char net_path[PATH_MAX];
170 	int netns;
171 
172 	snprintf(net_path, sizeof(net_path), "/proc/self/ns/net");
173 	netns = open(net_path, O_RDONLY);
174 	if (netns < 0)
175 		return -1;
176 	if (fstat(netns, netst) < 0) {
177 		close(netns);
178 		return -1;
179 	}
180 	close(netns);
181 	return 0;
182 }
183 
zebra_ns_notify_is_default_netns(const char * name)184 static bool zebra_ns_notify_is_default_netns(const char *name)
185 {
186 	struct stat default_netns_stat;
187 	struct stat st;
188 	char netnspath[PATH_MAX];
189 
190 	if (zebra_ns_notify_self_identify(&default_netns_stat))
191 		return false;
192 
193 	memset(&st, 0, sizeof(struct stat));
194 	snprintf(netnspath, sizeof(netnspath), "%s/%s", NS_RUN_DIR, name);
195 	/* compare with local stat */
196 	if (stat(netnspath, &st) == 0 &&
197 	    (st.st_dev == default_netns_stat.st_dev) &&
198 	    (st.st_ino == default_netns_stat.st_ino))
199 		return true;
200 	return false;
201 }
202 
zebra_ns_ready_read(struct thread * t)203 static int zebra_ns_ready_read(struct thread *t)
204 {
205 	struct zebra_netns_info *zns_info = THREAD_ARG(t);
206 	const char *netnspath;
207 	int err, stop_retry = 0;
208 
209 	if (!zns_info)
210 		return 0;
211 	if (!zns_info->netnspath) {
212 		XFREE(MTYPE_NETNS_MISC, zns_info);
213 		return 0;
214 	}
215 	netnspath = zns_info->netnspath;
216 	if (--zns_info->retries == 0)
217 		stop_retry = 1;
218 	frr_with_privs(&zserv_privs) {
219 		err = ns_switch_to_netns(netnspath);
220 	}
221 	if (err < 0)
222 		return zebra_ns_continue_read(zns_info, stop_retry);
223 
224 	/* go back to default ns */
225 	frr_with_privs(&zserv_privs) {
226 		err = ns_switchback_to_initial();
227 	}
228 	if (err < 0)
229 		return zebra_ns_continue_read(zns_info, stop_retry);
230 
231 	/* check default name is not already set */
232 	if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) {
233 		zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", basename(netnspath));
234 		return zebra_ns_continue_read(zns_info, 1);
235 	}
236 	if (zebra_ns_notify_is_default_netns(basename(netnspath))) {
237 		zlog_warn(
238 			  "NS notify : NS %s is default VRF. Updating VRF Name", basename(netnspath));
239 		vrf_set_default_name(basename(netnspath), false);
240 		return zebra_ns_continue_read(zns_info, 1);
241 	}
242 
243 	/* success : close fd and create zns context */
244 	zebra_ns_notify_create_context_from_entry_name(basename(netnspath));
245 	return zebra_ns_continue_read(zns_info, 1);
246 }
247 
zebra_ns_notify_read(struct thread * t)248 static int zebra_ns_notify_read(struct thread *t)
249 {
250 	int fd_monitor = THREAD_FD(t);
251 	struct inotify_event *event;
252 	char buf[BUFSIZ];
253 	ssize_t len;
254 
255 	zebra_netns_notify_current = thread_add_read(
256 		zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL);
257 	len = read(fd_monitor, buf, sizeof(buf));
258 	if (len < 0) {
259 		flog_err_sys(EC_ZEBRA_NS_NOTIFY_READ,
260 			     "NS notify read: failed to read (%s)",
261 			     safe_strerror(errno));
262 		return 0;
263 	}
264 	for (event = (struct inotify_event *)buf; (char *)event < &buf[len];
265 	     event = (struct inotify_event *)((char *)event + sizeof(*event)
266 					      + event->len)) {
267 		char *netnspath;
268 		struct zebra_netns_info *netnsinfo;
269 
270 		if (!(event->mask & (IN_CREATE | IN_DELETE)))
271 			continue;
272 
273 		if (offsetof(struct inotify_event, name) + event->len
274 		    >= sizeof(buf)) {
275 			flog_err(EC_ZEBRA_NS_NOTIFY_READ,
276 				 "NS notify read: buffer underflow");
277 			break;
278 		}
279 
280 		if (strnlen(event->name, event->len) == event->len) {
281 			flog_err(EC_ZEBRA_NS_NOTIFY_READ,
282 				 "NS notify error: bad event name");
283 			break;
284 		}
285 
286 		if (event->mask & IN_DELETE) {
287 			zebra_ns_delete(event->name);
288 			continue;
289 		}
290 		netnspath = ns_netns_pathname(NULL, event->name);
291 		if (!netnspath)
292 			continue;
293 		netnspath = XSTRDUP(MTYPE_NETNS_MISC, netnspath);
294 		netnsinfo = XCALLOC(MTYPE_NETNS_MISC,
295 				    sizeof(struct zebra_netns_info));
296 		netnsinfo->retries = ZEBRA_NS_POLLING_MAX_RETRIES;
297 		netnsinfo->netnspath = netnspath;
298 		thread_add_timer_msec(zrouter.master, zebra_ns_ready_read,
299 				      (void *)netnsinfo, 0, NULL);
300 	}
301 	return 0;
302 }
303 
zebra_ns_notify_parse(void)304 void zebra_ns_notify_parse(void)
305 {
306 	struct dirent *dent;
307 	DIR *srcdir = opendir(NS_RUN_DIR);
308 
309 	if (srcdir == NULL) {
310 		flog_err_sys(EC_LIB_SYSTEM_CALL,
311 			     "NS parsing init: failed to parse %s", NS_RUN_DIR);
312 		return;
313 	}
314 	while ((dent = readdir(srcdir)) != NULL) {
315 		struct stat st;
316 
317 		if (strcmp(dent->d_name, ".") == 0
318 		    || strcmp(dent->d_name, "..") == 0)
319 			continue;
320 		if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) {
321 			flog_err_sys(
322 				EC_LIB_SYSTEM_CALL,
323 				"NS parsing init: failed to parse entry %s",
324 				dent->d_name);
325 			continue;
326 		}
327 		if (S_ISDIR(st.st_mode)) {
328 			zlog_debug("NS parsing init: %s is not a NS",
329 				   dent->d_name);
330 			continue;
331 		}
332 		/* check default name is not already set */
333 		if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) {
334 			zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", dent->d_name);
335 			continue;
336 		}
337 		if (zebra_ns_notify_is_default_netns(dent->d_name)) {
338 			zlog_warn(
339 				  "NS notify : NS %s is default VRF. Updating VRF Name", dent->d_name);
340 			vrf_set_default_name(dent->d_name, false);
341 			continue;
342 		}
343 		zebra_ns_notify_create_context_from_entry_name(dent->d_name);
344 	}
345 	closedir(srcdir);
346 }
347 
zebra_ns_notify_init(void)348 void zebra_ns_notify_init(void)
349 {
350 	int fd_monitor;
351 
352 	zebra_netns_notify_current = NULL;
353 	fd_monitor = inotify_init();
354 	if (fd_monitor < 0) {
355 		flog_err_sys(
356 			EC_LIB_SYSTEM_CALL,
357 			"NS notify init: failed to initialize inotify (%s)",
358 			safe_strerror(errno));
359 	}
360 	if (inotify_add_watch(fd_monitor, NS_RUN_DIR,
361 			      IN_CREATE | IN_DELETE) < 0) {
362 		flog_err_sys(EC_LIB_SYSTEM_CALL,
363 			     "NS notify watch: failed to add watch (%s)",
364 			     safe_strerror(errno));
365 	}
366 	zebra_netns_notify_current = thread_add_read(
367 		zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL);
368 }
369 
zebra_ns_notify_close(void)370 void zebra_ns_notify_close(void)
371 {
372 	if (zebra_netns_notify_current == NULL)
373 		return;
374 
375 	int fd = 0;
376 
377 	if (zebra_netns_notify_current->u.fd > 0)
378 		fd = zebra_netns_notify_current->u.fd;
379 
380 	if (zebra_netns_notify_current->master != NULL)
381 		thread_cancel(zebra_netns_notify_current);
382 
383 	/* auto-removal of notify items */
384 	if (fd > 0)
385 		close(fd);
386 }
387 
388 #else
zebra_ns_notify_parse(void)389 void zebra_ns_notify_parse(void)
390 {
391 }
392 
zebra_ns_notify_init(void)393 void zebra_ns_notify_init(void)
394 {
395 }
396 
zebra_ns_notify_close(void)397 void zebra_ns_notify_close(void)
398 {
399 }
400 #endif /* !HAVE_NETLINK */
401