]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_netns_notify.c
Merge pull request #13403 from anlancs/fix/zebra-missing-vrf-flag
[mirror_frr.git] / zebra / zebra_netns_notify.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Zebra NS collector and notifier for Network NameSpaces
4 * Copyright (C) 2017 6WIND
5 */
6
7 #include <zebra.h>
8
9 #ifdef HAVE_NETLINK
10 #ifdef HAVE_NETNS
11 #undef _GNU_SOURCE
12 #define _GNU_SOURCE
13
14 #include <sched.h>
15 #endif
16 #include <dirent.h>
17 #include <sys/inotify.h>
18 #include <sys/stat.h>
19
20 #include "frrevent.h"
21 #include "ns.h"
22 #include "command.h"
23 #include "memory.h"
24 #include "lib_errors.h"
25
26 #include "zebra_router.h"
27 #endif /* defined(HAVE_NETLINK) */
28
29 #include "zebra_netns_notify.h"
30 #include "zebra_netns_id.h"
31 #include "zebra_errors.h"
32 #include "interface.h"
33
34 #ifdef HAVE_NETLINK
35
36 /* upon creation of folder under /var/run/netns,
37 * wait that netns context is bound to
38 * that folder 10 seconds
39 */
40 #define ZEBRA_NS_POLLING_INTERVAL_MSEC 1000
41 #define ZEBRA_NS_POLLING_MAX_RETRIES 200
42
43 DEFINE_MTYPE_STATIC(ZEBRA, NETNS_MISC, "ZebraNetNSInfo");
44 static struct event *zebra_netns_notify_current;
45
46 struct zebra_netns_info {
47 const char *netnspath;
48 unsigned int retries;
49 };
50
51 static void zebra_ns_ready_read(struct event *t);
52 static void zebra_ns_notify_create_context_from_entry_name(const char *name);
53 static int zebra_ns_continue_read(struct zebra_netns_info *zns_info,
54 int stop_retry);
55 static void zebra_ns_notify_read(struct event *t);
56
57 static struct vrf *vrf_handler_create(struct vty *vty, const char *vrfname)
58 {
59 if (strlen(vrfname) > VRF_NAMSIZ) {
60 flog_warn(EC_LIB_VRF_LENGTH,
61 "%% VRF name %s invalid: length exceeds %d bytes",
62 vrfname, VRF_NAMSIZ);
63 return NULL;
64 }
65
66 return vrf_get(VRF_UNKNOWN, vrfname);
67 }
68
69 static void zebra_ns_notify_create_context_from_entry_name(const char *name)
70 {
71 char *netnspath = ns_netns_pathname(NULL, name);
72 struct vrf *vrf;
73 int ret;
74 ns_id_t ns_id, ns_id_external, ns_id_relative = NS_UNKNOWN;
75 struct ns *default_ns;
76
77 if (netnspath == NULL)
78 return;
79
80 frr_with_privs(&zserv_privs) {
81 ns_id = zebra_ns_id_get(netnspath, -1);
82 }
83 if (ns_id == NS_UNKNOWN)
84 return;
85 ns_id_external = ns_map_nsid_with_external(ns_id, true);
86 /* if VRF with NS ID already present */
87 vrf = vrf_lookup_by_id((vrf_id_t)ns_id_external);
88 if (vrf) {
89 zlog_debug(
90 "NS notify : same NSID used by VRF %s. Ignore NS %s creation",
91 vrf->name, netnspath);
92 return;
93 }
94 vrf = vrf_handler_create(NULL, name);
95 if (!vrf) {
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 = zebra_vrf_netns_handler_create(NULL, vrf, netnspath,
113 ns_id_external, ns_id,
114 ns_id_relative);
115 }
116 if (ret != CMD_SUCCESS) {
117 flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED,
118 "NS notify : failed to create NS %s", netnspath);
119 ns_map_nsid_with_external(ns_id, false);
120 vrf_delete(vrf);
121 return;
122 }
123 zlog_info("NS notify : created VRF %s NS %s", name, netnspath);
124 }
125
126 static int zebra_ns_continue_read(struct zebra_netns_info *zns_info,
127 int stop_retry)
128 {
129 void *ns_path_ptr = (void *)zns_info->netnspath;
130
131 if (stop_retry) {
132 XFREE(MTYPE_NETNS_MISC, ns_path_ptr);
133 XFREE(MTYPE_NETNS_MISC, zns_info);
134 return 0;
135 }
136 event_add_timer_msec(zrouter.master, zebra_ns_ready_read,
137 (void *)zns_info, ZEBRA_NS_POLLING_INTERVAL_MSEC,
138 NULL);
139 return 0;
140 }
141
142 static int zebra_ns_delete(char *name)
143 {
144 struct vrf *vrf = vrf_lookup_by_name(name);
145 struct interface *ifp, *tmp;
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
154 /*
155 * We don't receive interface down/delete notifications from kernel
156 * when a netns is deleted. Therefore we have to manually replicate
157 * the necessary actions here.
158 */
159 RB_FOREACH_SAFE (ifp, if_name_head, &vrf->ifaces_by_name, tmp) {
160 if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
161 continue;
162
163 if (if_is_no_ptm_operative(ifp)) {
164 UNSET_FLAG(ifp->flags, IFF_RUNNING);
165 if_down(ifp);
166 }
167
168 if (IS_ZEBRA_IF_BOND(ifp))
169 zebra_l2if_update_bond(ifp, false);
170 if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
171 zebra_l2if_update_bond_slave(ifp, IFINDEX_INTERNAL,
172 false);
173 /* Special handling for bridge or VxLAN interfaces. */
174 if (IS_ZEBRA_IF_BRIDGE(ifp))
175 zebra_l2_bridge_del(ifp);
176 else if (IS_ZEBRA_IF_VXLAN(ifp))
177 zebra_l2_vxlanif_del(ifp);
178
179 UNSET_FLAG(ifp->flags, IFF_UP);
180 if_delete_update(&ifp);
181 }
182
183 ns = (struct ns *)vrf->ns_ctxt;
184 /* the deletion order is the same
185 * as the one used when siging signal is received
186 */
187 vrf->ns_ctxt = NULL;
188 vrf_delete(vrf);
189 if (ns)
190 ns_delete(ns);
191
192 zlog_info("NS notify : deleted VRF %s", name);
193 return 0;
194 }
195
196 static int zebra_ns_notify_self_identify(struct stat *netst)
197 {
198 char net_path[PATH_MAX];
199 int netns;
200
201 snprintf(net_path, sizeof(net_path), "/proc/self/ns/net");
202 netns = open(net_path, O_RDONLY);
203 if (netns < 0)
204 return -1;
205 if (fstat(netns, netst) < 0) {
206 close(netns);
207 return -1;
208 }
209 close(netns);
210 return 0;
211 }
212
213 static bool zebra_ns_notify_is_default_netns(const char *name)
214 {
215 struct stat default_netns_stat;
216 struct stat st;
217 char netnspath[PATH_MAX];
218
219 if (zebra_ns_notify_self_identify(&default_netns_stat))
220 return false;
221
222 memset(&st, 0, sizeof(st));
223 snprintf(netnspath, sizeof(netnspath), "%s/%s", NS_RUN_DIR, name);
224 /* compare with local stat */
225 if (stat(netnspath, &st) == 0 &&
226 (st.st_dev == default_netns_stat.st_dev) &&
227 (st.st_ino == default_netns_stat.st_ino))
228 return true;
229 return false;
230 }
231
232 static void zebra_ns_ready_read(struct event *t)
233 {
234 struct zebra_netns_info *zns_info = EVENT_ARG(t);
235 const char *netnspath;
236 int err, stop_retry = 0;
237
238 if (!zns_info)
239 return;
240 if (!zns_info->netnspath) {
241 XFREE(MTYPE_NETNS_MISC, zns_info);
242 return;
243 }
244 netnspath = zns_info->netnspath;
245 if (--zns_info->retries == 0)
246 stop_retry = 1;
247 frr_with_privs(&zserv_privs) {
248 err = ns_switch_to_netns(netnspath);
249 }
250 if (err < 0) {
251 zebra_ns_continue_read(zns_info, stop_retry);
252 return;
253 }
254
255 /* go back to default ns */
256 frr_with_privs(&zserv_privs) {
257 err = ns_switchback_to_initial();
258 }
259 if (err < 0) {
260 zebra_ns_continue_read(zns_info, stop_retry);
261 return;
262 }
263
264 /* check default name is not already set */
265 if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) {
266 zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", basename(netnspath));
267 zebra_ns_continue_read(zns_info, 1);
268 return;
269 }
270 if (zebra_ns_notify_is_default_netns(basename(netnspath))) {
271 zlog_warn(
272 "NS notify : NS %s is default VRF. Ignore VRF creation",
273 basename(netnspath));
274 zebra_ns_continue_read(zns_info, 1);
275 return;
276 }
277
278 /* success : close fd and create zns context */
279 zebra_ns_notify_create_context_from_entry_name(basename(netnspath));
280 zebra_ns_continue_read(zns_info, 1);
281 }
282
283 static void zebra_ns_notify_read(struct event *t)
284 {
285 int fd_monitor = EVENT_FD(t);
286 struct inotify_event *event;
287 char buf[BUFSIZ];
288 ssize_t len;
289 char event_name[NAME_MAX + 1];
290
291 event_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor,
292 &zebra_netns_notify_current);
293 len = read(fd_monitor, buf, sizeof(buf));
294 if (len < 0) {
295 flog_err_sys(EC_ZEBRA_NS_NOTIFY_READ,
296 "NS notify read: failed to read (%s)",
297 safe_strerror(errno));
298 return;
299 }
300 for (event = (struct inotify_event *)buf; (char *)event < &buf[len];
301 event = (struct inotify_event *)((char *)event + sizeof(*event)
302 + event->len)) {
303 char *netnspath;
304 struct zebra_netns_info *netnsinfo;
305
306 if (!(event->mask & (IN_CREATE | IN_DELETE)))
307 continue;
308
309 if (offsetof(struct inotify_event, name) + event->len
310 >= sizeof(buf)) {
311 flog_err(EC_ZEBRA_NS_NOTIFY_READ,
312 "NS notify read: buffer underflow");
313 break;
314 }
315
316 if (strnlen(event->name, event->len) == event->len) {
317 flog_err(EC_ZEBRA_NS_NOTIFY_READ,
318 "NS notify error: bad event name");
319 break;
320 }
321
322 /*
323 * Coverity Scan extra steps to satisfy `STRING_NULL` warning:
324 * - Make sure event name is present by checking `len != 0`
325 * - Event name length must be at most `NAME_MAX + 1`
326 * (null byte inclusive)
327 * - Copy event name to a stack buffer to make sure it
328 * includes the null byte. `event->name` includes at least
329 * one null byte and `event->len` accounts the null bytes,
330 * so the operation after `memcpy` will look like a
331 * truncation to satisfy Coverity Scan null byte ending.
332 *
333 * Example:
334 * if `event->name` is `abc\0` and `event->len` is 4,
335 * `memcpy` will copy the 4 bytes and then we set the
336 * null byte again at the position 4.
337 *
338 * For more information please read inotify(7) man page.
339 */
340 if (event->len == 0)
341 continue;
342
343 if (event->len > sizeof(event_name)) {
344 flog_err(EC_ZEBRA_NS_NOTIFY_READ,
345 "NS notify error: unexpected big event name");
346 break;
347 }
348
349 memcpy(event_name, event->name, event->len);
350 event_name[event->len - 1] = 0;
351
352 if (event->mask & IN_DELETE) {
353 zebra_ns_delete(event_name);
354 continue;
355 }
356 netnspath = ns_netns_pathname(NULL, event_name);
357 if (!netnspath)
358 continue;
359 netnspath = XSTRDUP(MTYPE_NETNS_MISC, netnspath);
360 netnsinfo = XCALLOC(MTYPE_NETNS_MISC,
361 sizeof(struct zebra_netns_info));
362 netnsinfo->retries = ZEBRA_NS_POLLING_MAX_RETRIES;
363 netnsinfo->netnspath = netnspath;
364 event_add_timer_msec(zrouter.master, zebra_ns_ready_read,
365 (void *)netnsinfo, 0, NULL);
366 }
367 }
368
369 void zebra_ns_notify_parse(void)
370 {
371 struct dirent *dent;
372 DIR *srcdir = opendir(NS_RUN_DIR);
373
374 if (srcdir == NULL) {
375 flog_err_sys(EC_LIB_SYSTEM_CALL,
376 "NS parsing init: failed to parse %s", NS_RUN_DIR);
377 return;
378 }
379 while ((dent = readdir(srcdir)) != NULL) {
380 struct stat st;
381
382 if (strcmp(dent->d_name, ".") == 0
383 || strcmp(dent->d_name, "..") == 0)
384 continue;
385 if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) {
386 flog_err_sys(
387 EC_LIB_SYSTEM_CALL,
388 "NS parsing init: failed to parse entry %s",
389 dent->d_name);
390 continue;
391 }
392 if (S_ISDIR(st.st_mode)) {
393 zlog_debug("NS parsing init: %s is not a NS",
394 dent->d_name);
395 continue;
396 }
397 /* check default name is not already set */
398 if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) {
399 zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", dent->d_name);
400 continue;
401 }
402 if (zebra_ns_notify_is_default_netns(dent->d_name)) {
403 zlog_warn(
404 "NS notify : NS %s is default VRF. Ignore VRF creation",
405 dent->d_name);
406 continue;
407 }
408 zebra_ns_notify_create_context_from_entry_name(dent->d_name);
409 }
410 closedir(srcdir);
411 }
412
413 void zebra_ns_notify_init(void)
414 {
415 int fd_monitor;
416
417 fd_monitor = inotify_init();
418 if (fd_monitor < 0) {
419 flog_err_sys(
420 EC_LIB_SYSTEM_CALL,
421 "NS notify init: failed to initialize inotify (%s)",
422 safe_strerror(errno));
423 }
424 if (inotify_add_watch(fd_monitor, NS_RUN_DIR,
425 IN_CREATE | IN_DELETE) < 0) {
426 flog_err_sys(EC_LIB_SYSTEM_CALL,
427 "NS notify watch: failed to add watch (%s)",
428 safe_strerror(errno));
429 }
430 event_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor,
431 &zebra_netns_notify_current);
432 }
433
434 void zebra_ns_notify_close(void)
435 {
436 if (zebra_netns_notify_current == NULL)
437 return;
438
439 int fd = 0;
440
441 if (zebra_netns_notify_current->u.fd > 0)
442 fd = zebra_netns_notify_current->u.fd;
443
444 if (zebra_netns_notify_current->master != NULL)
445 EVENT_OFF(zebra_netns_notify_current);
446
447 /* auto-removal of notify items */
448 if (fd > 0)
449 close(fd);
450 }
451
452 #else
453 void zebra_ns_notify_parse(void)
454 {
455 }
456
457 void zebra_ns_notify_init(void)
458 {
459 }
460
461 void zebra_ns_notify_close(void)
462 {
463 }
464 #endif /* !HAVE_NETLINK */