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>