Annotation of embedaddon/quagga/lib/vrf.c, revision 1.1
1.1 ! misho 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: *
! 17: * You should have received a copy of the GNU General Public License
! 18: * along with GNU Zebra; see the file COPYING. If not, write to the
! 19: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
! 20: * Boston, MA 02111-1307, USA.
! 21: */
! 22:
! 23: #include <zebra.h>
! 24:
! 25: #ifdef HAVE_NETNS
! 26: #undef _GNU_SOURCE
! 27: #define _GNU_SOURCE
! 28:
! 29: #include <sched.h>
! 30: #endif
! 31:
! 32: #include "if.h"
! 33: #include "vrf.h"
! 34: #include "prefix.h"
! 35: #include "table.h"
! 36: #include "log.h"
! 37: #include "memory.h"
! 38: #include "command.h"
! 39: #include "vty.h"
! 40:
! 41:
! 42: #ifndef CLONE_NEWNET
! 43: #define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */
! 44: #endif
! 45:
! 46: #ifndef HAVE_SETNS
! 47: static inline int setns(int fd, int nstype)
! 48: {
! 49: #ifdef __NR_setns
! 50: return syscall(__NR_setns, fd, nstype);
! 51: #else
! 52: errno = ENOSYS;
! 53: return -1;
! 54: #endif
! 55: }
! 56: #endif /* HAVE_SETNS */
! 57:
! 58: #define VRF_RUN_DIR "/var/run/netns"
! 59:
! 60: #ifdef HAVE_NETNS
! 61:
! 62: #define VRF_DEFAULT_NAME "/proc/self/ns/net"
! 63: static int have_netns_enabled = -1;
! 64:
! 65: #else /* !HAVE_NETNS */
! 66:
! 67: #define VRF_DEFAULT_NAME "Default-IP-Routing-Table"
! 68:
! 69: #endif /* HAVE_NETNS */
! 70:
! 71: static int have_netns(void)
! 72: {
! 73: #ifdef HAVE_NETNS
! 74: if (have_netns_enabled < 0)
! 75: {
! 76: int fd = open (VRF_DEFAULT_NAME, O_RDONLY);
! 77:
! 78: if (fd < 0)
! 79: have_netns_enabled = 0;
! 80: else
! 81: {
! 82: have_netns_enabled = 1;
! 83: close(fd);
! 84: }
! 85: }
! 86: return have_netns_enabled;
! 87: #else
! 88: return 0;
! 89: #endif
! 90: }
! 91:
! 92: struct vrf
! 93: {
! 94: /* Identifier, same as the vector index */
! 95: vrf_id_t vrf_id;
! 96: /* Name */
! 97: char *name;
! 98: /* File descriptor */
! 99: int fd;
! 100:
! 101: /* Master list of interfaces belonging to this VRF */
! 102: struct list *iflist;
! 103:
! 104: /* User data */
! 105: void *info;
! 106: };
! 107:
! 108: /* Holding VRF hooks */
! 109: struct vrf_master
! 110: {
! 111: int (*vrf_new_hook) (vrf_id_t, void **);
! 112: int (*vrf_delete_hook) (vrf_id_t, void **);
! 113: int (*vrf_enable_hook) (vrf_id_t, void **);
! 114: int (*vrf_disable_hook) (vrf_id_t, void **);
! 115: } vrf_master = {0,};
! 116:
! 117: /* VRF table */
! 118: struct route_table *vrf_table = NULL;
! 119:
! 120: static int vrf_is_enabled (struct vrf *vrf);
! 121: static int vrf_enable (struct vrf *vrf);
! 122: static void vrf_disable (struct vrf *vrf);
! 123:
! 124:
! 125: /* Build the table key */
! 126: static void
! 127: vrf_build_key (vrf_id_t vrf_id, struct prefix *p)
! 128: {
! 129: p->family = AF_INET;
! 130: p->prefixlen = IPV4_MAX_BITLEN;
! 131: p->u.prefix4.s_addr = vrf_id;
! 132: }
! 133:
! 134: /* Get a VRF. If not found, create one. */
! 135: static struct vrf *
! 136: vrf_get (vrf_id_t vrf_id)
! 137: {
! 138: struct prefix p;
! 139: struct route_node *rn;
! 140: struct vrf *vrf;
! 141:
! 142: vrf_build_key (vrf_id, &p);
! 143: rn = route_node_get (vrf_table, &p);
! 144: if (rn->info)
! 145: {
! 146: vrf = (struct vrf *)rn->info;
! 147: route_unlock_node (rn); /* get */
! 148: return vrf;
! 149: }
! 150:
! 151: vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
! 152: vrf->vrf_id = vrf_id;
! 153: vrf->fd = -1;
! 154: rn->info = vrf;
! 155:
! 156: /* Initialize interfaces. */
! 157: if_init (vrf_id, &vrf->iflist);
! 158:
! 159: zlog_info ("VRF %u is created.", vrf_id);
! 160:
! 161: if (vrf_master.vrf_new_hook)
! 162: (*vrf_master.vrf_new_hook) (vrf_id, &vrf->info);
! 163:
! 164: return vrf;
! 165: }
! 166:
! 167: /* Delete a VRF. This is called in vrf_terminate(). */
! 168: static void
! 169: vrf_delete (struct vrf *vrf)
! 170: {
! 171: zlog_info ("VRF %u is to be deleted.", vrf->vrf_id);
! 172:
! 173: vrf_disable (vrf);
! 174:
! 175: if (vrf_master.vrf_delete_hook)
! 176: (*vrf_master.vrf_delete_hook) (vrf->vrf_id, &vrf->info);
! 177:
! 178: if_terminate (vrf->vrf_id, &vrf->iflist);
! 179:
! 180: if (vrf->name)
! 181: XFREE (MTYPE_VRF_NAME, vrf->name);
! 182:
! 183: XFREE (MTYPE_VRF, vrf);
! 184: }
! 185:
! 186: /* Look up a VRF by identifier. */
! 187: static struct vrf *
! 188: vrf_lookup (vrf_id_t vrf_id)
! 189: {
! 190: struct prefix p;
! 191: struct route_node *rn;
! 192: struct vrf *vrf = NULL;
! 193:
! 194: vrf_build_key (vrf_id, &p);
! 195: rn = route_node_lookup (vrf_table, &p);
! 196: if (rn)
! 197: {
! 198: vrf = (struct vrf *)rn->info;
! 199: route_unlock_node (rn); /* lookup */
! 200: }
! 201: return vrf;
! 202: }
! 203:
! 204: /*
! 205: * Check whether the VRF is enabled - that is, whether the VRF
! 206: * is ready to allocate resources. Currently there's only one
! 207: * type of resource: socket.
! 208: */
! 209: static int
! 210: vrf_is_enabled (struct vrf *vrf)
! 211: {
! 212: if (have_netns())
! 213: return vrf && vrf->fd >= 0;
! 214: else
! 215: return vrf && vrf->fd == -2 && vrf->vrf_id == VRF_DEFAULT;
! 216: }
! 217:
! 218: /*
! 219: * Enable a VRF - that is, let the VRF be ready to use.
! 220: * The VRF_ENABLE_HOOK callback will be called to inform
! 221: * that they can allocate resources in this VRF.
! 222: *
! 223: * RETURN: 1 - enabled successfully; otherwise, 0.
! 224: */
! 225: static int
! 226: vrf_enable (struct vrf *vrf)
! 227: {
! 228:
! 229: if (!vrf_is_enabled (vrf))
! 230: {
! 231: if (have_netns()) {
! 232: vrf->fd = open (vrf->name, O_RDONLY);
! 233: } else {
! 234: vrf->fd = -2; /* Remember that vrf_enable_hook has been called */
! 235: errno = -ENOTSUP;
! 236: }
! 237:
! 238: if (!vrf_is_enabled (vrf))
! 239: {
! 240: zlog_err ("Can not enable VRF %u: %s!",
! 241: vrf->vrf_id, safe_strerror (errno));
! 242: return 0;
! 243: }
! 244:
! 245: if (have_netns())
! 246: zlog_info ("VRF %u is associated with NETNS %s.",
! 247: vrf->vrf_id, vrf->name);
! 248:
! 249: zlog_info ("VRF %u is enabled.", vrf->vrf_id);
! 250: if (vrf_master.vrf_enable_hook)
! 251: (*vrf_master.vrf_enable_hook) (vrf->vrf_id, &vrf->info);
! 252: }
! 253:
! 254: return 1;
! 255: }
! 256:
! 257: /*
! 258: * Disable a VRF - that is, let the VRF be unusable.
! 259: * The VRF_DELETE_HOOK callback will be called to inform
! 260: * that they must release the resources in the VRF.
! 261: */
! 262: static void
! 263: vrf_disable (struct vrf *vrf)
! 264: {
! 265: if (vrf_is_enabled (vrf))
! 266: {
! 267: zlog_info ("VRF %u is to be disabled.", vrf->vrf_id);
! 268:
! 269: if (vrf_master.vrf_disable_hook)
! 270: (*vrf_master.vrf_disable_hook) (vrf->vrf_id, &vrf->info);
! 271:
! 272: if (have_netns())
! 273: close (vrf->fd);
! 274:
! 275: vrf->fd = -1;
! 276: }
! 277: }
! 278:
! 279:
! 280: /* Add a VRF hook. Please add hooks before calling vrf_init(). */
! 281: void
! 282: vrf_add_hook (int type, int (*func)(vrf_id_t, void **))
! 283: {
! 284: switch (type) {
! 285: case VRF_NEW_HOOK:
! 286: vrf_master.vrf_new_hook = func;
! 287: break;
! 288: case VRF_DELETE_HOOK:
! 289: vrf_master.vrf_delete_hook = func;
! 290: break;
! 291: case VRF_ENABLE_HOOK:
! 292: vrf_master.vrf_enable_hook = func;
! 293: break;
! 294: case VRF_DISABLE_HOOK:
! 295: vrf_master.vrf_disable_hook = func;
! 296: break;
! 297: default:
! 298: break;
! 299: }
! 300: }
! 301:
! 302: /* Return the iterator of the first VRF. */
! 303: vrf_iter_t
! 304: vrf_first (void)
! 305: {
! 306: struct route_node *rn;
! 307:
! 308: for (rn = route_top (vrf_table); rn; rn = route_next (rn))
! 309: if (rn->info)
! 310: {
! 311: route_unlock_node (rn); /* top/next */
! 312: return (vrf_iter_t)rn;
! 313: }
! 314: return VRF_ITER_INVALID;
! 315: }
! 316:
! 317: /* Return the next VRF iterator to the given iterator. */
! 318: vrf_iter_t
! 319: vrf_next (vrf_iter_t iter)
! 320: {
! 321: struct route_node *rn = NULL;
! 322:
! 323: /* Lock it first because route_next() will unlock it. */
! 324: if (iter != VRF_ITER_INVALID)
! 325: rn = route_next (route_lock_node ((struct route_node *)iter));
! 326:
! 327: for (; rn; rn = route_next (rn))
! 328: if (rn->info)
! 329: {
! 330: route_unlock_node (rn); /* next */
! 331: return (vrf_iter_t)rn;
! 332: }
! 333: return VRF_ITER_INVALID;
! 334: }
! 335:
! 336: /* Return the VRF iterator of the given VRF ID. If it does not exist,
! 337: * the iterator of the next existing VRF is returned. */
! 338: vrf_iter_t
! 339: vrf_iterator (vrf_id_t vrf_id)
! 340: {
! 341: struct prefix p;
! 342: struct route_node *rn;
! 343:
! 344: vrf_build_key (vrf_id, &p);
! 345: rn = route_node_get (vrf_table, &p);
! 346: if (rn->info)
! 347: {
! 348: /* OK, the VRF exists. */
! 349: route_unlock_node (rn); /* get */
! 350: return (vrf_iter_t)rn;
! 351: }
! 352:
! 353: /* Find the next VRF. */
! 354: for (rn = route_next (rn); rn; rn = route_next (rn))
! 355: if (rn->info)
! 356: {
! 357: route_unlock_node (rn); /* next */
! 358: return (vrf_iter_t)rn;
! 359: }
! 360:
! 361: return VRF_ITER_INVALID;
! 362: }
! 363:
! 364: /* Obtain the VRF ID from the given VRF iterator. */
! 365: vrf_id_t
! 366: vrf_iter2id (vrf_iter_t iter)
! 367: {
! 368: struct route_node *rn = (struct route_node *) iter;
! 369: return (rn && rn->info) ? ((struct vrf *)rn->info)->vrf_id : VRF_DEFAULT;
! 370: }
! 371:
! 372: /* Obtain the data pointer from the given VRF iterator. */
! 373: void *
! 374: vrf_iter2info (vrf_iter_t iter)
! 375: {
! 376: struct route_node *rn = (struct route_node *) iter;
! 377: return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL;
! 378: }
! 379:
! 380: /* Obtain the interface list from the given VRF iterator. */
! 381: struct list *
! 382: vrf_iter2iflist (vrf_iter_t iter)
! 383: {
! 384: struct route_node *rn = (struct route_node *) iter;
! 385: return (rn && rn->info) ? ((struct vrf *)rn->info)->iflist : NULL;
! 386: }
! 387:
! 388: /* Get the data pointer of the specified VRF. If not found, create one. */
! 389: void *
! 390: vrf_info_get (vrf_id_t vrf_id)
! 391: {
! 392: struct vrf *vrf = vrf_get (vrf_id);
! 393: return vrf->info;
! 394: }
! 395:
! 396: /* Look up the data pointer of the specified VRF. */
! 397: void *
! 398: vrf_info_lookup (vrf_id_t vrf_id)
! 399: {
! 400: struct vrf *vrf = vrf_lookup (vrf_id);
! 401: return vrf ? vrf->info : NULL;
! 402: }
! 403:
! 404: /* Look up the interface list in a VRF. */
! 405: struct list *
! 406: vrf_iflist (vrf_id_t vrf_id)
! 407: {
! 408: struct vrf * vrf = vrf_lookup (vrf_id);
! 409: return vrf ? vrf->iflist : NULL;
! 410: }
! 411:
! 412: /* Get the interface list of the specified VRF. Create one if not find. */
! 413: struct list *
! 414: vrf_iflist_get (vrf_id_t vrf_id)
! 415: {
! 416: struct vrf * vrf = vrf_get (vrf_id);
! 417: return vrf->iflist;
! 418: }
! 419:
! 420: /*
! 421: * VRF bit-map
! 422: */
! 423:
! 424: #define VRF_BITMAP_NUM_OF_GROUPS 8
! 425: #define VRF_BITMAP_NUM_OF_BITS_IN_GROUP \
! 426: (UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS)
! 427: #define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
! 428: (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
! 429:
! 430: #define VRF_BITMAP_GROUP(_id) \
! 431: ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
! 432: #define VRF_BITMAP_BIT_OFFSET(_id) \
! 433: ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
! 434:
! 435: #define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) \
! 436: ((_bit_offset) / CHAR_BIT)
! 437: #define VRF_BITMAP_FLAG(_bit_offset) \
! 438: (((u_char)1) << ((_bit_offset) % CHAR_BIT))
! 439:
! 440: struct vrf_bitmap
! 441: {
! 442: u_char *groups[VRF_BITMAP_NUM_OF_GROUPS];
! 443: };
! 444:
! 445: vrf_bitmap_t
! 446: vrf_bitmap_init (void)
! 447: {
! 448: return (vrf_bitmap_t) XCALLOC (MTYPE_VRF_BITMAP, sizeof (struct vrf_bitmap));
! 449: }
! 450:
! 451: void
! 452: vrf_bitmap_free (vrf_bitmap_t bmap)
! 453: {
! 454: struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
! 455: int i;
! 456:
! 457: if (bmap == VRF_BITMAP_NULL)
! 458: return;
! 459:
! 460: for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
! 461: if (bm->groups[i])
! 462: XFREE (MTYPE_VRF_BITMAP, bm->groups[i]);
! 463:
! 464: XFREE (MTYPE_VRF_BITMAP, bm);
! 465: }
! 466:
! 467: void
! 468: vrf_bitmap_set (vrf_bitmap_t bmap, vrf_id_t vrf_id)
! 469: {
! 470: struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
! 471: u_char group = VRF_BITMAP_GROUP (vrf_id);
! 472: u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
! 473:
! 474: if (bmap == VRF_BITMAP_NULL)
! 475: return;
! 476:
! 477: if (bm->groups[group] == NULL)
! 478: bm->groups[group] = XCALLOC (MTYPE_VRF_BITMAP,
! 479: VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
! 480:
! 481: SET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
! 482: VRF_BITMAP_FLAG (offset));
! 483: }
! 484:
! 485: void
! 486: vrf_bitmap_unset (vrf_bitmap_t bmap, vrf_id_t vrf_id)
! 487: {
! 488: struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
! 489: u_char group = VRF_BITMAP_GROUP (vrf_id);
! 490: u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
! 491:
! 492: if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
! 493: return;
! 494:
! 495: UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
! 496: VRF_BITMAP_FLAG (offset));
! 497: }
! 498:
! 499: int
! 500: vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id)
! 501: {
! 502: struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
! 503: u_char group = VRF_BITMAP_GROUP (vrf_id);
! 504: u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
! 505:
! 506: if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
! 507: return 0;
! 508:
! 509: return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
! 510: VRF_BITMAP_FLAG (offset)) ? 1 : 0;
! 511: }
! 512:
! 513: /*
! 514: * VRF realization with NETNS
! 515: */
! 516:
! 517: static char *
! 518: vrf_netns_pathname (struct vty *vty, const char *name)
! 519: {
! 520: static char pathname[PATH_MAX];
! 521: char *result;
! 522:
! 523: if (name[0] == '/') /* absolute pathname */
! 524: result = realpath (name, pathname);
! 525: else /* relevant pathname */
! 526: {
! 527: char tmp_name[PATH_MAX];
! 528: snprintf (tmp_name, PATH_MAX, "%s/%s", VRF_RUN_DIR, name);
! 529: result = realpath (tmp_name, pathname);
! 530: }
! 531:
! 532: if (! result)
! 533: {
! 534: vty_out (vty, "Invalid pathname: %s%s", safe_strerror (errno),
! 535: VTY_NEWLINE);
! 536: return NULL;
! 537: }
! 538: return pathname;
! 539: }
! 540:
! 541: DEFUN (vrf_netns,
! 542: vrf_netns_cmd,
! 543: "vrf <1-65535> netns NAME",
! 544: "Enable a VRF\n"
! 545: "Specify the VRF identifier\n"
! 546: "Associate with a NETNS\n"
! 547: "The file name in " VRF_RUN_DIR ", or a full pathname\n")
! 548: {
! 549: vrf_id_t vrf_id = VRF_DEFAULT;
! 550: struct vrf *vrf = NULL;
! 551: char *pathname = vrf_netns_pathname (vty, argv[1]);
! 552:
! 553: if (!pathname)
! 554: return CMD_WARNING;
! 555:
! 556: VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
! 557: vrf = vrf_get (vrf_id);
! 558:
! 559: if (vrf->name && strcmp (vrf->name, pathname) != 0)
! 560: {
! 561: vty_out (vty, "VRF %u is already configured with NETNS %s%s",
! 562: vrf->vrf_id, vrf->name, VTY_NEWLINE);
! 563: return CMD_WARNING;
! 564: }
! 565:
! 566: if (!vrf->name)
! 567: vrf->name = XSTRDUP (MTYPE_VRF_NAME, pathname);
! 568:
! 569: if (!vrf_enable (vrf))
! 570: {
! 571: vty_out (vty, "Can not associate VRF %u with NETNS %s%s",
! 572: vrf->vrf_id, vrf->name, VTY_NEWLINE);
! 573: return CMD_WARNING;
! 574: }
! 575:
! 576: return CMD_SUCCESS;
! 577: }
! 578:
! 579: DEFUN (no_vrf_netns,
! 580: no_vrf_netns_cmd,
! 581: "no vrf <1-65535> netns NAME",
! 582: NO_STR
! 583: "Enable a VRF\n"
! 584: "Specify the VRF identifier\n"
! 585: "Associate with a NETNS\n"
! 586: "The file name in " VRF_RUN_DIR ", or a full pathname\n")
! 587: {
! 588: vrf_id_t vrf_id = VRF_DEFAULT;
! 589: struct vrf *vrf = NULL;
! 590: char *pathname = vrf_netns_pathname (vty, argv[1]);
! 591:
! 592: if (!pathname)
! 593: return CMD_WARNING;
! 594:
! 595: VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
! 596: vrf = vrf_lookup (vrf_id);
! 597:
! 598: if (!vrf)
! 599: {
! 600: vty_out (vty, "VRF %u is not found%s", vrf_id, VTY_NEWLINE);
! 601: return CMD_SUCCESS;
! 602: }
! 603:
! 604: if (vrf->name && strcmp (vrf->name, pathname) != 0)
! 605: {
! 606: vty_out (vty, "Incorrect NETNS file name%s", VTY_NEWLINE);
! 607: return CMD_WARNING;
! 608: }
! 609:
! 610: vrf_disable (vrf);
! 611:
! 612: if (vrf->name)
! 613: {
! 614: XFREE (MTYPE_VRF_NAME, vrf->name);
! 615: vrf->name = NULL;
! 616: }
! 617:
! 618: return CMD_SUCCESS;
! 619: }
! 620:
! 621: /* VRF node. */
! 622: static struct cmd_node vrf_node =
! 623: {
! 624: VRF_NODE,
! 625: "", /* VRF node has no interface. */
! 626: 1
! 627: };
! 628:
! 629: /* VRF configuration write function. */
! 630: static int
! 631: vrf_config_write (struct vty *vty)
! 632: {
! 633: struct route_node *rn;
! 634: struct vrf *vrf;
! 635: int write = 0;
! 636:
! 637: for (rn = route_top (vrf_table); rn; rn = route_next (rn))
! 638: if ((vrf = rn->info) != NULL &&
! 639: vrf->vrf_id != VRF_DEFAULT && vrf->name)
! 640: {
! 641: vty_out (vty, "vrf %u netns %s%s", vrf->vrf_id, vrf->name, VTY_NEWLINE);
! 642: write++;
! 643: }
! 644:
! 645: return write;
! 646: }
! 647:
! 648: /* Initialize VRF module. */
! 649: void
! 650: vrf_init (void)
! 651: {
! 652: struct vrf *default_vrf;
! 653:
! 654: /* Allocate VRF table. */
! 655: vrf_table = route_table_init ();
! 656:
! 657: /* The default VRF always exists. */
! 658: default_vrf = vrf_get (VRF_DEFAULT);
! 659: if (!default_vrf)
! 660: {
! 661: zlog_err ("vrf_init: failed to create the default VRF!");
! 662: exit (1);
! 663: }
! 664:
! 665: /* Set the default VRF name. */
! 666: default_vrf->name = XSTRDUP (MTYPE_VRF_NAME, VRF_DEFAULT_NAME);
! 667:
! 668: /* Enable the default VRF. */
! 669: if (!vrf_enable (default_vrf))
! 670: {
! 671: zlog_err ("vrf_init: failed to enable the default VRF!");
! 672: exit (1);
! 673: }
! 674:
! 675: if (have_netns())
! 676: {
! 677: /* Install VRF commands. */
! 678: install_node (&vrf_node, vrf_config_write);
! 679: install_element (CONFIG_NODE, &vrf_netns_cmd);
! 680: install_element (CONFIG_NODE, &no_vrf_netns_cmd);
! 681: }
! 682: }
! 683:
! 684: /* Terminate VRF module. */
! 685: void
! 686: vrf_terminate (void)
! 687: {
! 688: struct route_node *rn;
! 689: struct vrf *vrf;
! 690:
! 691: for (rn = route_top (vrf_table); rn; rn = route_next (rn))
! 692: if ((vrf = rn->info) != NULL)
! 693: vrf_delete (vrf);
! 694:
! 695: route_table_finish (vrf_table);
! 696: vrf_table = NULL;
! 697: }
! 698:
! 699: /* Create a socket for the VRF. */
! 700: int
! 701: vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id)
! 702: {
! 703: struct vrf *vrf = vrf_lookup (vrf_id);
! 704: int ret = -1;
! 705:
! 706: if (!vrf_is_enabled (vrf))
! 707: {
! 708: errno = ENOSYS;
! 709: return -1;
! 710: }
! 711:
! 712: if (have_netns())
! 713: {
! 714: ret = (vrf_id != VRF_DEFAULT) ? setns (vrf->fd, CLONE_NEWNET) : 0;
! 715: if (ret >= 0)
! 716: {
! 717: ret = socket (domain, type, protocol);
! 718: if (vrf_id != VRF_DEFAULT)
! 719: setns (vrf_lookup (VRF_DEFAULT)->fd, CLONE_NEWNET);
! 720: }
! 721: }
! 722: else
! 723: ret = socket (domain, type, protocol);
! 724:
! 725: return ret;
! 726: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>