]> git.proxmox.com Git - mirror_frr.git/blame - lib/vrf.c
*: use C99 standard fixed-width integer types
[mirror_frr.git] / lib / vrf.c
CommitLineData
b72ede27
FL
1/*
2 * VRF functions.
3 * Copyright (C) 2014 6WIND S.A.
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
896014f4
DL
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
b72ede27
FL
20 */
21
22#include <zebra.h>
23
4691b65a
PG
24/* for basename */
25#include <libgen.h>
26
6a69b354 27#include "if.h"
b72ede27 28#include "vrf.h"
7922fc65 29#include "vrf_int.h"
b72ede27
FL
30#include "prefix.h"
31#include "table.h"
32#include "log.h"
33#include "memory.h"
19dc275e 34#include "command.h"
b95c1883 35#include "ns.h"
3bc34908 36#include "privs.h"
19dc275e 37
ec31f30d
PG
38/* default VRF ID value used when VRF backend is not NETNS */
39#define VRF_DEFAULT_INTERNAL 0
40
d62a17ae 41DEFINE_MTYPE_STATIC(LIB, VRF, "VRF")
4a1ab8e4
DL
42DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map")
43
e80e7cce
DL
44DEFINE_QOBJ_TYPE(vrf)
45
d62a17ae 46static __inline int vrf_id_compare(const struct vrf *, const struct vrf *);
47static __inline int vrf_name_compare(const struct vrf *, const struct vrf *);
1a1a7065 48
d62a17ae 49RB_GENERATE(vrf_id_head, vrf, id_entry, vrf_id_compare);
50RB_GENERATE(vrf_name_head, vrf, name_entry, vrf_name_compare);
1a1a7065 51
d62a17ae 52struct vrf_id_head vrfs_by_id = RB_INITIALIZER(&vrfs_by_id);
53struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name);
1a1a7065 54
78dd30b2 55static int vrf_backend;
3bc34908 56static struct zebra_privs_t *vrf_daemon_privs;
78dd30b2 57
19dc275e
DS
58/*
59 * Turn on/off debug code
60 * for vrf.
61 */
62int debug_vrf = 0;
b72ede27 63
b72ede27 64/* Holding VRF hooks */
d62a17ae 65struct vrf_master {
66 int (*vrf_new_hook)(struct vrf *);
67 int (*vrf_delete_hook)(struct vrf *);
68 int (*vrf_enable_hook)(struct vrf *);
69 int (*vrf_disable_hook)(struct vrf *);
70} vrf_master = {
71 0,
72};
b72ede27 73
d62a17ae 74static int vrf_is_enabled(struct vrf *vrf);
e5bf3e1e 75
216b18ef 76/* VRF list existance check by name. */
d62a17ae 77struct vrf *vrf_lookup_by_name(const char *name)
216b18ef 78{
d62a17ae 79 struct vrf vrf;
80 strlcpy(vrf.name, name, sizeof(vrf.name));
81 return (RB_FIND(vrf_name_head, &vrfs_by_name, &vrf));
216b18ef 82}
216b18ef 83
d62a17ae 84static __inline int vrf_id_compare(const struct vrf *a, const struct vrf *b)
b72ede27 85{
d62a17ae 86 return (a->vrf_id - b->vrf_id);
216b18ef
DS
87}
88
d62a17ae 89static int vrf_name_compare(const struct vrf *a, const struct vrf *b)
b72ede27 90{
d62a17ae 91 return strcmp(a->name, b->name);
b72ede27
FL
92}
93
e26aedbe
PG
94/* if ns_id is different and not VRF_UNKNOWN,
95 * then update vrf identifier, and enable VRF
96 */
97static void vrf_update_vrf_id(ns_id_t ns_id, void *opaqueptr)
98{
99 ns_id_t vrf_id = (vrf_id_t)ns_id;
100 vrf_id_t old_vrf_id;
101 struct vrf *vrf = (struct vrf *)opaqueptr;
102
103 if (!vrf)
104 return;
105 old_vrf_id = vrf->vrf_id;
106 if (vrf_id == vrf->vrf_id)
107 return;
108 if (vrf->vrf_id != VRF_UNKNOWN)
109 RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
110 vrf->vrf_id = vrf_id;
111 RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
112 if (old_vrf_id == VRF_UNKNOWN)
113 vrf_enable((struct vrf *)vrf);
114}
115
ce1be369
PG
116int vrf_switch_to_netns(vrf_id_t vrf_id)
117{
118 char *name;
119 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
120
ce1be369 121 /* VRF is default VRF. silently ignore */
e26aedbe
PG
122 if (!vrf || vrf->vrf_id == VRF_DEFAULT)
123 return 0;
124 /* VRF has no NETNS backend. silently ignore */
125 if (vrf->data.l.netns_name[0] == '\0')
ce1be369
PG
126 return 0;
127 name = ns_netns_pathname(NULL, vrf->data.l.netns_name);
128 if (debug_vrf)
129 zlog_debug("VRF_SWITCH: %s(%u)", name, vrf->vrf_id);
130 return ns_switch_to_netns(name);
131}
132
133int vrf_switchback_to_initial(void)
134{
135 int ret = ns_switchback_to_initial();
136
137 if (ret == 0 && debug_vrf)
138 zlog_debug("VRF_SWITCHBACK");
139 return ret;
140}
141
216b18ef 142/* Get a VRF. If not found, create one.
34f8e6af
DS
143 * Arg:
144 * name - The name of the vrf. May be NULL if unknown.
145 * vrf_id - The vrf_id of the vrf. May be VRF_UNKNOWN if unknown
216b18ef 146 * Description: Please note that this routine can be called with just the name
34f8e6af
DS
147 * and 0 vrf-id
148 */
d62a17ae 149struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
150{
151 struct vrf *vrf = NULL;
152 int new = 0;
153
154 if (debug_vrf)
996c9314
LB
155 zlog_debug("VRF_GET: %s(%u)", name == NULL ? "(NULL)" : name,
156 vrf_id);
d62a17ae 157
158 /* Nothing to see, move along here */
159 if (!name && vrf_id == VRF_UNKNOWN)
160 return NULL;
161
162 /* Try to find VRF both by ID and name */
163 if (vrf_id != VRF_UNKNOWN)
164 vrf = vrf_lookup_by_id(vrf_id);
165 if (!vrf && name)
166 vrf = vrf_lookup_by_name(name);
167
168 if (vrf == NULL) {
169 vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf));
170 vrf->vrf_id = VRF_UNKNOWN;
d62a17ae 171 QOBJ_REG(vrf, vrf);
172 new = 1;
173
174 if (debug_vrf)
175 zlog_debug("VRF(%u) %s is created.", vrf_id,
176 (name) ? name : "(NULL)");
177 }
178
179 /* Set identifier */
180 if (vrf_id != VRF_UNKNOWN && vrf->vrf_id == VRF_UNKNOWN) {
181 vrf->vrf_id = vrf_id;
182 RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
183 }
184
185 /* Set name */
186 if (name && vrf->name[0] != '\0' && strcmp(name, vrf->name)) {
187 RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
188 strlcpy(vrf->name, name, sizeof(vrf->name));
189 RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
190 } else if (name && vrf->name[0] == '\0') {
191 strlcpy(vrf->name, name, sizeof(vrf->name));
192 RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
193 }
d62a17ae 194 if (new &&vrf_master.vrf_new_hook)
195 (*vrf_master.vrf_new_hook)(vrf);
196
197 return vrf;
b72ede27
FL
198}
199
84915b0a 200/* Delete a VRF. This is called when the underlying VRF goes away, a
201 * pre-configured VRF is deleted or when shutting down (vrf_terminate()).
202 */
d62a17ae 203void vrf_delete(struct vrf *vrf)
b72ede27 204{
d62a17ae 205 if (debug_vrf)
206 zlog_debug("VRF %u is to be deleted.", vrf->vrf_id);
b72ede27 207
d62a17ae 208 if (vrf_is_enabled(vrf))
209 vrf_disable(vrf);
e5bf3e1e 210
84915b0a 211 /* If the VRF is user configured, it'll stick around, just remove
212 * the ID mapping. Interfaces assigned to this VRF should've been
213 * removed already as part of the VRF going down.
214 */
215 if (vrf_is_user_cfged(vrf)) {
216 if (vrf->vrf_id != VRF_UNKNOWN) {
217 /* Delete any VRF interfaces - should be only
218 * the VRF itself, other interfaces should've
219 * been moved out of the VRF.
220 */
221 if_terminate(vrf);
222 RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
223 vrf->vrf_id = VRF_UNKNOWN;
224 }
225 return;
226 }
227
d62a17ae 228 if (vrf_master.vrf_delete_hook)
229 (*vrf_master.vrf_delete_hook)(vrf);
216b18ef 230
d62a17ae 231 QOBJ_UNREG(vrf);
f4e14fdb 232 if_terminate(vrf);
b72ede27 233
d62a17ae 234 if (vrf->vrf_id != VRF_UNKNOWN)
235 RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
236 if (vrf->name[0] != '\0')
237 RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
b72ede27 238
d62a17ae 239 XFREE(MTYPE_VRF, vrf);
b72ede27
FL
240}
241
242/* Look up a VRF by identifier. */
d62a17ae 243struct vrf *vrf_lookup_by_id(vrf_id_t vrf_id)
b72ede27 244{
d62a17ae 245 struct vrf vrf;
246 vrf.vrf_id = vrf_id;
247 return (RB_FIND(vrf_id_head, &vrfs_by_id, &vrf));
b72ede27
FL
248}
249
e5bf3e1e
FL
250/*
251 * Enable a VRF - that is, let the VRF be ready to use.
252 * The VRF_ENABLE_HOOK callback will be called to inform
253 * that they can allocate resources in this VRF.
254 *
255 * RETURN: 1 - enabled successfully; otherwise, 0.
256 */
d62a17ae 257int vrf_enable(struct vrf *vrf)
e5bf3e1e 258{
d62a17ae 259 if (vrf_is_enabled(vrf))
260 return 1;
05e8e11e 261
d62a17ae 262 if (debug_vrf)
263 zlog_debug("VRF %u is enabled.", vrf->vrf_id);
e5bf3e1e 264
d62a17ae 265 SET_FLAG(vrf->status, VRF_ACTIVE);
e5bf3e1e 266
d62a17ae 267 if (vrf_master.vrf_enable_hook)
268 (*vrf_master.vrf_enable_hook)(vrf);
e5bf3e1e 269
d62a17ae 270 return 1;
e5bf3e1e
FL
271}
272
273/*
274 * Disable a VRF - that is, let the VRF be unusable.
275 * The VRF_DELETE_HOOK callback will be called to inform
276 * that they must release the resources in the VRF.
277 */
697d3ec7 278void vrf_disable(struct vrf *vrf)
e5bf3e1e 279{
d62a17ae 280 if (!vrf_is_enabled(vrf))
281 return;
a647bfa8 282
d62a17ae 283 UNSET_FLAG(vrf->status, VRF_ACTIVE);
e5bf3e1e 284
d62a17ae 285 if (debug_vrf)
286 zlog_debug("VRF %u is to be disabled.", vrf->vrf_id);
e5bf3e1e 287
d62a17ae 288 /* Till now, nothing to be done for the default VRF. */
289 // Pending: see why this statement.
e74f14fc 290
d62a17ae 291 if (vrf_master.vrf_disable_hook)
292 (*vrf_master.vrf_disable_hook)(vrf);
e5bf3e1e
FL
293}
294
b7cfce93
MK
295const char *vrf_id_to_name(vrf_id_t vrf_id)
296{
297 struct vrf *vrf;
298
299 vrf = vrf_lookup_by_id(vrf_id);
300 if (vrf)
301 return vrf->name;
302
181c08c6 303 return "n/a";
b7cfce93
MK
304}
305
d62a17ae 306vrf_id_t vrf_name_to_id(const char *name)
216b18ef 307{
d62a17ae 308 struct vrf *vrf;
309 vrf_id_t vrf_id = VRF_DEFAULT; // Pending: need a way to return invalid
310 // id/ routine not used.
216b18ef 311
d62a17ae 312 vrf = vrf_lookup_by_name(name);
313 if (vrf)
314 vrf_id = vrf->vrf_id;
216b18ef 315
d62a17ae 316 return vrf_id;
216b18ef
DS
317}
318
b72ede27 319/* Get the data pointer of the specified VRF. If not found, create one. */
d62a17ae 320void *vrf_info_get(vrf_id_t vrf_id)
b72ede27 321{
d62a17ae 322 struct vrf *vrf = vrf_get(vrf_id, NULL);
323 return vrf->info;
b72ede27
FL
324}
325
326/* Look up the data pointer of the specified VRF. */
d62a17ae 327void *vrf_info_lookup(vrf_id_t vrf_id)
b72ede27 328{
d62a17ae 329 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
330 return vrf ? vrf->info : NULL;
b72ede27
FL
331}
332
7076bb2f
FL
333/*
334 * VRF bit-map
335 */
336
3bd74754 337#define VRF_BITMAP_NUM_OF_GROUPS 1024
a9ff90c4 338#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT32_MAX / VRF_BITMAP_NUM_OF_GROUPS)
d62a17ae 339#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
340 (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
341
342#define VRF_BITMAP_GROUP(_id) ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
343#define VRF_BITMAP_BIT_OFFSET(_id) ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
344
345#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) ((_bit_offset) / CHAR_BIT)
d7c0a89a
QY
346#define VRF_BITMAP_FLAG(_bit_offset) \
347 (((uint8_t)1) << ((_bit_offset) % CHAR_BIT))
d62a17ae 348
349struct vrf_bitmap {
d7c0a89a 350 uint8_t *groups[VRF_BITMAP_NUM_OF_GROUPS];
7076bb2f
FL
351};
352
d62a17ae 353vrf_bitmap_t vrf_bitmap_init(void)
7076bb2f 354{
d62a17ae 355 return (vrf_bitmap_t)XCALLOC(MTYPE_VRF_BITMAP,
356 sizeof(struct vrf_bitmap));
7076bb2f
FL
357}
358
d62a17ae 359void vrf_bitmap_free(vrf_bitmap_t bmap)
7076bb2f 360{
d62a17ae 361 struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
362 int i;
7076bb2f 363
d62a17ae 364 if (bmap == VRF_BITMAP_NULL)
365 return;
7076bb2f 366
d62a17ae 367 for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
368 if (bm->groups[i])
369 XFREE(MTYPE_VRF_BITMAP, bm->groups[i]);
7076bb2f 370
d62a17ae 371 XFREE(MTYPE_VRF_BITMAP, bm);
7076bb2f
FL
372}
373
d62a17ae 374void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
7076bb2f 375{
d62a17ae 376 struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
d7c0a89a
QY
377 uint8_t group = VRF_BITMAP_GROUP(vrf_id);
378 uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
7076bb2f 379
d62a17ae 380 if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN)
381 return;
7076bb2f 382
d62a17ae 383 if (bm->groups[group] == NULL)
384 bm->groups[group] = XCALLOC(MTYPE_VRF_BITMAP,
385 VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
7076bb2f 386
d62a17ae 387 SET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
388 VRF_BITMAP_FLAG(offset));
7076bb2f
FL
389}
390
d62a17ae 391void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
7076bb2f 392{
d62a17ae 393 struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
d7c0a89a
QY
394 uint8_t group = VRF_BITMAP_GROUP(vrf_id);
395 uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
7076bb2f 396
d62a17ae 397 if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
398 || bm->groups[group] == NULL)
399 return;
7076bb2f 400
d62a17ae 401 UNSET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
402 VRF_BITMAP_FLAG(offset));
7076bb2f
FL
403}
404
d62a17ae 405int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
7076bb2f 406{
d62a17ae 407 struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
d7c0a89a
QY
408 uint8_t group = VRF_BITMAP_GROUP(vrf_id);
409 uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
7076bb2f 410
d62a17ae 411 if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
412 || bm->groups[group] == NULL)
413 return 0;
7076bb2f 414
d62a17ae 415 return CHECK_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
416 VRF_BITMAP_FLAG(offset))
417 ? 1
418 : 0;
7076bb2f
FL
419}
420
d62a17ae 421static void vrf_autocomplete(vector comps, struct cmd_token *token)
d617d5fe 422{
d62a17ae 423 struct vrf *vrf = NULL;
d617d5fe 424
a2addae8 425 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
a9ff90c4 426 if (vrf->vrf_id != VRF_DEFAULT)
d62a17ae 427 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
428 }
d617d5fe
DS
429}
430
431static const struct cmd_variable_handler vrf_var_handlers[] = {
d62a17ae 432 {
433 .varname = "vrf",
434 .completions = vrf_autocomplete,
435 },
436 {.completions = NULL},
d617d5fe
DS
437};
438
b72ede27 439/* Initialize VRF module. */
d62a17ae 440void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *),
441 int (*disable)(struct vrf *), int (*delete)(struct vrf *))
442{
443 struct vrf *default_vrf;
444
e26aedbe
PG
445 /* initialise NS, in case VRF backend if NETNS */
446 ns_init();
d62a17ae 447 if (debug_vrf)
448 zlog_debug("%s: Initializing VRF subsystem",
449 __PRETTY_FUNCTION__);
450
451 vrf_master.vrf_new_hook = create;
452 vrf_master.vrf_enable_hook = enable;
453 vrf_master.vrf_disable_hook = disable;
454 vrf_master.vrf_delete_hook = delete;
455
456 /* The default VRF always exists. */
457 default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME);
458 if (!default_vrf) {
459 zlog_err("vrf_init: failed to create the default VRF!");
460 exit(1);
461 }
462
463 /* Enable the default VRF. */
464 if (!vrf_enable(default_vrf)) {
465 zlog_err("vrf_init: failed to enable the default VRF!");
466 exit(1);
467 }
468
469 cmd_variable_handler_register(vrf_var_handlers);
b72ede27
FL
470}
471
472/* Terminate VRF module. */
d62a17ae 473void vrf_terminate(void)
b72ede27 474{
d62a17ae 475 struct vrf *vrf;
b72ede27 476
d62a17ae 477 if (debug_vrf)
478 zlog_debug("%s: Shutting down vrf subsystem",
479 __PRETTY_FUNCTION__);
19dc275e 480
55cd0f61
DS
481 while (!RB_EMPTY(vrf_id_head, &vrfs_by_id)) {
482 vrf = RB_ROOT(vrf_id_head, &vrfs_by_id);
483
65c3a7c4 484 /* Clear configured flag and invoke delete. */
485 UNSET_FLAG(vrf->status, VRF_CONFIGURED);
d62a17ae 486 vrf_delete(vrf);
65c3a7c4 487 }
55cd0f61
DS
488
489 while (!RB_EMPTY(vrf_name_head, &vrfs_by_name)) {
490 vrf = RB_ROOT(vrf_name_head, &vrfs_by_name);
491
65c3a7c4 492 /* Clear configured flag and invoke delete. */
493 UNSET_FLAG(vrf->status, VRF_CONFIGURED);
d62a17ae 494 vrf_delete(vrf);
65c3a7c4 495 }
b72ede27
FL
496}
497
e5bf3e1e 498/* Create a socket for the VRF. */
0f4977c6
PG
499int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
500 char *interfacename)
e5bf3e1e 501{
2e0d2b3d 502 int ret, save_errno, ret2;
e5bf3e1e 503
2e0d2b3d
PG
504 ret = vrf_switch_to_netns(vrf_id);
505 if (ret < 0)
996c9314
LB
506 zlog_err("%s: Can't switch to VRF %u (%s)", __func__, vrf_id,
507 safe_strerror(errno));
d62a17ae 508 ret = socket(domain, type, protocol);
2e0d2b3d
PG
509 save_errno = errno;
510 ret2 = vrf_switchback_to_initial();
511 if (ret2 < 0)
996c9314
LB
512 zlog_err("%s: Can't switchback from VRF %u (%s)", __func__,
513 vrf_id, safe_strerror(errno));
2e0d2b3d 514 errno = save_errno;
0f4977c6
PG
515 if (ret <= 0)
516 return ret;
517 ret2 = vrf_bind(vrf_id, ret, interfacename);
518 if (ret2 < 0) {
519 close(ret);
520 ret = ret2;
521 }
d62a17ae 522 return ret;
e5bf3e1e
FL
523}
524
78dd30b2
PG
525int vrf_is_backend_netns(void)
526{
527 return (vrf_backend == VRF_BACKEND_NETNS);
528}
529
530int vrf_get_backend(void)
531{
532 return vrf_backend;
533}
534
535void vrf_configure_backend(int vrf_backend_netns)
536{
537 vrf_backend = vrf_backend_netns;
538}
539
697d3ec7 540int vrf_handler_create(struct vty *vty, const char *vrfname, struct vrf **vrf)
f30c50b9 541{
d62a17ae 542 struct vrf *vrfp;
f30c50b9 543
d62a17ae 544 if (strlen(vrfname) > VRF_NAMSIZ) {
697d3ec7
PG
545 if (vty)
546 vty_out(vty,
996c9314
LB
547 "%% VRF name %s invalid: length exceeds %d bytes\n",
548 vrfname, VRF_NAMSIZ);
697d3ec7
PG
549 else
550 zlog_warn(
996c9314
LB
551 "%% VRF name %s invalid: length exceeds %d bytes\n",
552 vrfname, VRF_NAMSIZ);
d62a17ae 553 return CMD_WARNING_CONFIG_FAILED;
554 }
f30c50b9 555
d62a17ae 556 vrfp = vrf_get(VRF_UNKNOWN, vrfname);
f30c50b9 557
697d3ec7
PG
558 if (vty)
559 VTY_PUSH_CONTEXT(VRF_NODE, vrfp);
f30c50b9 560
697d3ec7
PG
561 if (vrf)
562 *vrf = vrfp;
d62a17ae 563 return CMD_SUCCESS;
f30c50b9
RW
564}
565
996c9314
LB
566int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
567 ns_id_t ns_id)
e26aedbe
PG
568{
569 struct ns *ns = NULL;
570
571 if (!vrf)
572 return CMD_WARNING_CONFIG_FAILED;
573 if (vrf->vrf_id != VRF_UNKNOWN && vrf->ns_ctxt == NULL) {
574 if (vty)
575 vty_out(vty,
576 "VRF %u is already configured with VRF %s\n",
577 vrf->vrf_id, vrf->name);
578 else
579 zlog_warn("VRF %u is already configured with VRF %s\n",
580 vrf->vrf_id, vrf->name);
581 return CMD_WARNING_CONFIG_FAILED;
582 }
583 if (vrf->ns_ctxt != NULL) {
996c9314 584 ns = (struct ns *)vrf->ns_ctxt;
e26aedbe
PG
585 if (ns && 0 != strcmp(ns->name, pathname)) {
586 if (vty)
587 vty_out(vty,
996c9314
LB
588 "VRF %u already configured with NETNS %s\n",
589 vrf->vrf_id, ns->name);
e26aedbe
PG
590 else
591 zlog_warn(
996c9314
LB
592 "VRF %u already configured with NETNS %s",
593 vrf->vrf_id, ns->name);
e26aedbe
PG
594 return CMD_WARNING_CONFIG_FAILED;
595 }
596 }
597 ns = ns_lookup_name(pathname);
598 if (ns && ns->vrf_ctxt) {
599 struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt;
600
601 if (vrf2 == vrf)
602 return CMD_SUCCESS;
603 if (vty)
996c9314
LB
604 vty_out(vty,
605 "NS %s is already configured"
e26aedbe 606 " with VRF %u(%s)\n",
996c9314 607 ns->name, vrf2->vrf_id, vrf2->name);
e26aedbe
PG
608 else
609 zlog_warn("NS %s is already configured with VRF %u(%s)",
610 ns->name, vrf2->vrf_id, vrf2->name);
611 return CMD_WARNING_CONFIG_FAILED;
612 }
613 ns = ns_get_created(ns, pathname, ns_id);
614 ns->vrf_ctxt = (void *)vrf;
615 vrf->ns_ctxt = (void *)ns;
616 /* update VRF netns NAME */
617 if (vrf)
618 strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ);
619
620 if (!ns_enable(ns, vrf_update_vrf_id)) {
621 if (vty)
622 vty_out(vty, "Can not associate NS %u with NETNS %s\n",
996c9314 623 ns->ns_id, ns->name);
e26aedbe
PG
624 else
625 zlog_warn("Can not associate NS %u with NETNS %s",
626 ns->ns_id, ns->name);
627 return CMD_WARNING_CONFIG_FAILED;
628 }
629
630 return CMD_SUCCESS;
631}
632
ce1be369
PG
633int vrf_is_mapped_on_netns(vrf_id_t vrf_id)
634{
635 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
636
637 if (!vrf || vrf->data.l.netns_name[0] == '\0')
638 return 0;
639 if (vrf->vrf_id == VRF_DEFAULT)
640 return 0;
641 return 1;
642}
643
697d3ec7
PG
644/* vrf CLI commands */
645DEFUN_NOSH (vrf,
646 vrf_cmd,
647 "vrf NAME",
648 "Select a VRF to configure\n"
649 "VRF's name\n")
650{
651 int idx_name = 1;
652 const char *vrfname = argv[idx_name]->arg;
653
654 return vrf_handler_create(vty, vrfname, NULL);
655}
656
f30c50b9
RW
657DEFUN_NOSH (no_vrf,
658 no_vrf_cmd,
d7a75a6c 659 "no vrf NAME",
f30c50b9
RW
660 NO_STR
661 "Delete a pseudo VRF's configuration\n"
662 "VRF's name\n")
663{
d62a17ae 664 const char *vrfname = argv[2]->arg;
53dc2b05 665
d62a17ae 666 struct vrf *vrfp;
f30c50b9 667
d62a17ae 668 vrfp = vrf_lookup_by_name(vrfname);
f30c50b9 669
d62a17ae 670 if (vrfp == NULL) {
671 vty_out(vty, "%% VRF %s does not exist\n", vrfname);
672 return CMD_WARNING_CONFIG_FAILED;
673 }
f30c50b9 674
d62a17ae 675 if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
676 vty_out(vty, "%% Only inactive VRFs can be deleted\n");
677 return CMD_WARNING_CONFIG_FAILED;
678 }
f30c50b9 679
84915b0a 680 /* Clear configured flag and invoke delete. */
681 UNSET_FLAG(vrfp->status, VRF_CONFIGURED);
d62a17ae 682 vrf_delete(vrfp);
f30c50b9 683
d62a17ae 684 return CMD_SUCCESS;
f30c50b9
RW
685}
686
53dc2b05 687
d62a17ae 688struct cmd_node vrf_node = {VRF_NODE, "%s(config-vrf)# ", 1};
7ddcfca4 689
e26aedbe
PG
690DEFUN_NOSH (vrf_netns,
691 vrf_netns_cmd,
692 "netns NAME",
693 "Attach VRF to a Namespace\n"
694 "The file name in " NS_RUN_DIR ", or a full pathname\n")
695{
3bc34908 696 int idx_name = 1, ret;
e26aedbe
PG
697 char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg);
698
699 VTY_DECLVAR_CONTEXT(vrf, vrf);
700
701 if (!pathname)
702 return CMD_WARNING_CONFIG_FAILED;
3bc34908
PG
703
704 if (vrf_daemon_privs &&
705 vrf_daemon_privs->change(ZPRIVS_RAISE))
706 zlog_err("%s: Can't raise privileges", __func__);
707
708 ret = vrf_netns_handler_create(vty, vrf, pathname, NS_UNKNOWN);
709
710 if (vrf_daemon_privs &&
711 vrf_daemon_privs->change(ZPRIVS_LOWER))
712 zlog_err("%s: Can't lower privileges", __func__);
713 return ret;
e26aedbe
PG
714}
715
716DEFUN (no_vrf_netns,
717 no_vrf_netns_cmd,
718 "no netns [NAME]",
719 NO_STR
720 "Detach VRF from a Namespace\n"
721 "The file name in " NS_RUN_DIR ", or a full pathname\n")
722{
723 struct ns *ns = NULL;
724
725 VTY_DECLVAR_CONTEXT(vrf, vrf);
726
727 if (!vrf_is_backend_netns()) {
728 vty_out(vty, "VRF backend is not Netns. Aborting\n");
729 return CMD_WARNING_CONFIG_FAILED;
730 }
731 if (!vrf->ns_ctxt) {
732 vty_out(vty, "VRF %s(%u) is not configured with NetNS\n",
733 vrf->name, vrf->vrf_id);
734 return CMD_WARNING_CONFIG_FAILED;
735 }
736
737 ns = (struct ns *)vrf->ns_ctxt;
738
739 ns->vrf_ctxt = NULL;
740 vrf_disable(vrf);
741 /* vrf ID from VRF is necessary for Zebra
742 * so that propagate to other clients is done
743 */
744 ns_delete(ns);
745 vrf->ns_ctxt = NULL;
746 return CMD_SUCCESS;
747}
748
19dc275e
DS
749/*
750 * Debug CLI for vrf's
751 */
752DEFUN (vrf_debug,
753 vrf_debug_cmd,
754 "debug vrf",
755 DEBUG_STR
756 "VRF Debugging\n")
757{
d62a17ae 758 debug_vrf = 1;
19dc275e 759
d62a17ae 760 return CMD_SUCCESS;
19dc275e
DS
761}
762
763DEFUN (no_vrf_debug,
764 no_vrf_debug_cmd,
765 "no debug vrf",
766 NO_STR
767 DEBUG_STR
768 "VRF Debugging\n")
769{
d62a17ae 770 debug_vrf = 0;
19dc275e 771
d62a17ae 772 return CMD_SUCCESS;
19dc275e
DS
773}
774
d62a17ae 775static int vrf_write_host(struct vty *vty)
19dc275e 776{
d62a17ae 777 if (debug_vrf)
778 vty_out(vty, "debug vrf\n");
19dc275e 779
d62a17ae 780 return 1;
19dc275e
DS
781}
782
d62a17ae 783static struct cmd_node vrf_debug_node = {VRF_DEBUG_NODE, "", 1};
19dc275e 784
d62a17ae 785void vrf_install_commands(void)
19dc275e 786{
d62a17ae 787 install_node(&vrf_debug_node, vrf_write_host);
19dc275e 788
d62a17ae 789 install_element(CONFIG_NODE, &vrf_debug_cmd);
790 install_element(ENABLE_NODE, &vrf_debug_cmd);
791 install_element(CONFIG_NODE, &no_vrf_debug_cmd);
792 install_element(ENABLE_NODE, &no_vrf_debug_cmd);
19dc275e 793}
53dc2b05 794
3bc34908
PG
795void vrf_cmd_init(int (*writefunc)(struct vty *vty),
796 struct zebra_privs_t *daemon_privs)
7ddcfca4 797{
d62a17ae 798 install_element(CONFIG_NODE, &vrf_cmd);
799 install_element(CONFIG_NODE, &no_vrf_cmd);
800 install_node(&vrf_node, writefunc);
801 install_default(VRF_NODE);
e26aedbe
PG
802 if (vrf_is_backend_netns() && ns_have_netns()) {
803 /* Install NS commands. */
3bc34908 804 vrf_daemon_privs = daemon_privs;
e26aedbe
PG
805 install_element(VRF_NODE, &vrf_netns_cmd);
806 install_element(VRF_NODE, &no_vrf_netns_cmd);
807 }
19dc275e 808}
ec31f30d
PG
809
810vrf_id_t vrf_get_default_id(void)
811{
812 struct vrf *vrf = vrf_lookup_by_name(VRF_DEFAULT_NAME);
813
814 if (vrf)
815 return vrf->vrf_id;
816 if (vrf_is_backend_netns())
817 return ns_get_default_id();
818 else
819 return VRF_DEFAULT_INTERNAL;
820}
2e0d2b3d 821
0f4977c6
PG
822int vrf_bind(vrf_id_t vrf_id, int fd, char *name)
823{
824 int ret = 0;
825
826 if (fd < 0 || name == NULL)
827 return fd;
828 if (vrf_is_mapped_on_netns(vrf_id))
829 return fd;
830#ifdef SO_BINDTODEVICE
996c9314 831 ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name));
0f4977c6 832 if (ret < 0)
996c9314
LB
833 zlog_debug("bind to interface %s failed, errno=%d", name,
834 errno);
0f4977c6
PG
835#endif /* SO_BINDTODEVICE */
836 return ret;
837}
2e0d2b3d 838int vrf_getaddrinfo(const char *node, const char *service,
996c9314
LB
839 const struct addrinfo *hints, struct addrinfo **res,
840 vrf_id_t vrf_id)
2e0d2b3d
PG
841{
842 int ret, ret2, save_errno;
843
844 ret = vrf_switch_to_netns(vrf_id);
845 if (ret < 0)
996c9314
LB
846 zlog_err("%s: Can't switch to VRF %u (%s)", __func__, vrf_id,
847 safe_strerror(errno));
2e0d2b3d
PG
848 ret = getaddrinfo(node, service, hints, res);
849 save_errno = errno;
850 ret2 = vrf_switchback_to_initial();
851 if (ret2 < 0)
996c9314
LB
852 zlog_err("%s: Can't switchback from VRF %u (%s)", __func__,
853 vrf_id, safe_strerror(errno));
2e0d2b3d
PG
854 errno = save_errno;
855 return ret;
856}
857
516d7591
PG
858int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params)
859{
860 int ret, saved_errno, rc;
861
862 ret = vrf_switch_to_netns(vrf_id);
863 if (ret < 0) {
996c9314
LB
864 zlog_err("%s: Can't switch to VRF %u (%s)", __func__, vrf_id,
865 safe_strerror(errno));
516d7591
PG
866 return 0;
867 }
868 rc = ioctl(d, request, params);
869 saved_errno = errno;
870 ret = vrf_switchback_to_initial();
871 if (ret < 0)
996c9314
LB
872 zlog_err("%s: Can't switchback from VRF %u (%s)", __func__,
873 vrf_id, safe_strerror(errno));
516d7591
PG
874 errno = saved_errno;
875 return rc;
876}
877
0f4977c6
PG
878int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
879 char *interfacename)
2e0d2b3d
PG
880{
881 int ret, save_errno, ret2;
882
883 ret = vrf_switch_to_netns(vrf_id);
884 if (ret < 0)
996c9314
LB
885 zlog_err("%s: Can't switch to VRF %u (%s)", __func__, vrf_id,
886 safe_strerror(errno));
2e0d2b3d
PG
887 ret = sockunion_socket(su);
888 save_errno = errno;
889 ret2 = vrf_switchback_to_initial();
890 if (ret2 < 0)
996c9314
LB
891 zlog_err("%s: Can't switchback from VRF %u (%s)", __func__,
892 vrf_id, safe_strerror(errno));
2e0d2b3d 893 errno = save_errno;
0f4977c6
PG
894
895 if (ret <= 0)
896 return ret;
897 ret2 = vrf_bind(vrf_id, ret, interfacename);
898 if (ret2 < 0) {
899 close(ret);
900 ret = ret2;
901 }
2e0d2b3d
PG
902 return ret;
903}