Annotation of embedaddon/quagga/ripngd/ripng_interface.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Interface related function for RIPng.
        !             3:  * Copyright (C) 1998 Kunihiro Ishiguro
        !             4:  *
        !             5:  * This file is part of GNU Zebra.
        !             6:  *
        !             7:  * GNU Zebra is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2, or (at your option) any
        !            10:  * 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 Free
        !            19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            20:  * 02111-1307, USA.  
        !            21:  */
        !            22: 
        !            23: #include <zebra.h>
        !            24: 
        !            25: #include "linklist.h"
        !            26: #include "if.h"
        !            27: #include "prefix.h"
        !            28: #include "memory.h"
        !            29: #include "network.h"
        !            30: #include "filter.h"
        !            31: #include "log.h"
        !            32: #include "stream.h"
        !            33: #include "zclient.h"
        !            34: #include "command.h"
        !            35: #include "table.h"
        !            36: #include "thread.h"
        !            37: #include "privs.h"
        !            38: 
        !            39: #include "ripngd/ripngd.h"
        !            40: #include "ripngd/ripng_debug.h"
        !            41: 
        !            42: /* If RFC2133 definition is used. */
        !            43: #ifndef IPV6_JOIN_GROUP
        !            44: #define IPV6_JOIN_GROUP  IPV6_ADD_MEMBERSHIP 
        !            45: #endif
        !            46: #ifndef IPV6_LEAVE_GROUP
        !            47: #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP 
        !            48: #endif
        !            49: 
        !            50: extern struct zebra_privs_t ripngd_privs;
        !            51: 
        !            52: /* Static utility function. */
        !            53: static void ripng_enable_apply (struct interface *);
        !            54: static void ripng_passive_interface_apply (struct interface *);
        !            55: static int ripng_enable_if_lookup (const char *);
        !            56: static int ripng_enable_network_lookup2 (struct connected *);
        !            57: static void ripng_enable_apply_all (void);
        !            58: 
        !            59: /* Join to the all rip routers multicast group. */
        !            60: static int
        !            61: ripng_multicast_join (struct interface *ifp)
        !            62: {
        !            63:   int ret;
        !            64:   struct ipv6_mreq mreq;
        !            65:   int save_errno;
        !            66: 
        !            67:   if (if_is_up (ifp) && if_is_multicast (ifp)) {
        !            68:     memset (&mreq, 0, sizeof (mreq));
        !            69:     inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
        !            70:     mreq.ipv6mr_interface = ifp->ifindex;
        !            71: 
        !            72:     /*
        !            73:      * NetBSD 1.6.2 requires root to join groups on gif(4).
        !            74:      * While this is bogus, privs are available and easy to use
        !            75:      * for this call as a workaround.
        !            76:      */
        !            77:     if (ripngd_privs.change (ZPRIVS_RAISE))
        !            78:       zlog_err ("ripng_multicast_join: could not raise privs");
        !            79: 
        !            80:     ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
        !            81:                      (char *) &mreq, sizeof (mreq));
        !            82:     save_errno = errno;
        !            83: 
        !            84:     if (ripngd_privs.change (ZPRIVS_LOWER))
        !            85:       zlog_err ("ripng_multicast_join: could not lower privs");
        !            86: 
        !            87:     if (ret < 0 && save_errno == EADDRINUSE)
        !            88:       {
        !            89:        /*
        !            90:         * Group is already joined.  This occurs due to sloppy group
        !            91:         * management, in particular declining to leave the group on
        !            92:         * an interface that has just gone down.
        !            93:         */
        !            94:        zlog_warn ("ripng join on %s EADDRINUSE (ignoring)\n", ifp->name);
        !            95:        return 0;               /* not an error */
        !            96:       }
        !            97: 
        !            98:     if (ret < 0)
        !            99:       zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s",
        !           100:                 safe_strerror (save_errno));
        !           101: 
        !           102:     if (IS_RIPNG_DEBUG_EVENT)
        !           103:       zlog_debug ("RIPng %s join to all-rip-routers multicast group", ifp->name);
        !           104: 
        !           105:     if (ret < 0)
        !           106:       return -1;
        !           107:   }
        !           108:   return 0;
        !           109: }
        !           110: 
        !           111: /* Leave from the all rip routers multicast group. */
        !           112: static int
        !           113: ripng_multicast_leave (struct interface *ifp)
        !           114: {
        !           115:   int ret;
        !           116:   struct ipv6_mreq mreq;
        !           117: 
        !           118:   if (if_is_up (ifp) && if_is_multicast (ifp)) {
        !           119:     memset (&mreq, 0, sizeof (mreq));
        !           120:     inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
        !           121:     mreq.ipv6mr_interface = ifp->ifindex;
        !           122: 
        !           123:     ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
        !           124:                      (char *) &mreq, sizeof (mreq));
        !           125:     if (ret < 0)
        !           126:       zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", safe_strerror (errno));
        !           127: 
        !           128:     if (IS_RIPNG_DEBUG_EVENT)
        !           129:       zlog_debug ("RIPng %s leave from all-rip-routers multicast group",
        !           130:                 ifp->name);
        !           131: 
        !           132:     if (ret < 0)
        !           133:       return -1;
        !           134:   }
        !           135: 
        !           136:   return 0;
        !           137: }
        !           138: 
        !           139: /* How many link local IPv6 address could be used on the interface ? */
        !           140: static int
        !           141: ripng_if_ipv6_lladdress_check (struct interface *ifp)
        !           142: {
        !           143:   struct listnode *nn;
        !           144:   struct connected *connected;
        !           145:   int count = 0;
        !           146: 
        !           147:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, connected))
        !           148:     {
        !           149:       struct prefix *p;
        !           150:       p = connected->address;
        !           151: 
        !           152:       if ((p->family == AF_INET6) &&
        !           153:           IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6))
        !           154:         count++;
        !           155:     }
        !           156: 
        !           157:   return count;
        !           158: }
        !           159: 
        !           160: static int
        !           161: ripng_if_down (struct interface *ifp)
        !           162: {
        !           163:   struct route_node *rp;
        !           164:   struct ripng_info *rinfo;
        !           165:   struct ripng_interface *ri;
        !           166: 
        !           167:   if (ripng)
        !           168:     {
        !           169:       for (rp = route_top (ripng->table); rp; rp = route_next (rp))
        !           170:        if ((rinfo = rp->info) != NULL)
        !           171:          {
        !           172:            /* Routes got through this interface. */
        !           173:            if (rinfo->ifindex == ifp->ifindex
        !           174:                && rinfo->type == ZEBRA_ROUTE_RIPNG
        !           175:                && rinfo->sub_type == RIPNG_ROUTE_RTE)
        !           176:              {
        !           177:                ripng_zebra_ipv6_delete ((struct prefix_ipv6 *) &rp->p,
        !           178:                                         &rinfo->nexthop,
        !           179:                                         rinfo->ifindex);
        !           180: 
        !           181:                ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
        !           182:                                           (struct prefix_ipv6 *)&rp->p,
        !           183:                                           rinfo->ifindex);
        !           184:              }
        !           185:            else
        !           186:              {
        !           187:                /* All redistributed routes got through this interface,
        !           188:                 * but the static and system ones are kept. */
        !           189:                if ((rinfo->ifindex == ifp->ifindex) &&
        !           190:                    (rinfo->type != ZEBRA_ROUTE_STATIC) &&
        !           191:                    (rinfo->type != ZEBRA_ROUTE_SYSTEM))
        !           192:                  ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
        !           193:                                             (struct prefix_ipv6 *) &rp->p,
        !           194:                                             rinfo->ifindex);
        !           195:              }
        !           196:          }
        !           197:     }
        !           198: 
        !           199:   ri = ifp->info;
        !           200:   
        !           201:   if (ri->running)
        !           202:    {
        !           203:      if (IS_RIPNG_DEBUG_EVENT)
        !           204:        zlog_debug ("turn off %s", ifp->name);
        !           205: 
        !           206:      /* Leave from multicast group. */
        !           207:      ripng_multicast_leave (ifp);
        !           208: 
        !           209:      ri->running = 0;
        !           210:    }
        !           211: 
        !           212:   return 0;
        !           213: }
        !           214: 
        !           215: /* Inteface link up message processing. */
        !           216: int
        !           217: ripng_interface_up (int command, struct zclient *zclient, zebra_size_t length)
        !           218: {
        !           219:   struct stream *s;
        !           220:   struct interface *ifp;
        !           221: 
        !           222:   /* zebra_interface_state_read() updates interface structure in iflist. */
        !           223:   s = zclient->ibuf;
        !           224:   ifp = zebra_interface_state_read (s);
        !           225: 
        !           226:   if (ifp == NULL)
        !           227:     return 0;
        !           228: 
        !           229:   if (IS_RIPNG_DEBUG_ZEBRA)
        !           230:     zlog_debug ("interface up %s index %d flags %llx metric %d mtu %d",
        !           231:               ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
        !           232:               ifp->metric, ifp->mtu6);
        !           233: 
        !           234:   /* Check if this interface is RIPng enabled or not. */
        !           235:   ripng_enable_apply (ifp);
        !           236: 
        !           237:   /* Check for a passive interface. */
        !           238:   ripng_passive_interface_apply (ifp);
        !           239: 
        !           240:   /* Apply distribute list to the all interface. */
        !           241:   ripng_distribute_update_interface (ifp);
        !           242: 
        !           243:   return 0;
        !           244: }
        !           245: 
        !           246: /* Inteface link down message processing. */
        !           247: int
        !           248: ripng_interface_down (int command, struct zclient *zclient,
        !           249:                      zebra_size_t length)
        !           250: {
        !           251:   struct stream *s;
        !           252:   struct interface *ifp;
        !           253: 
        !           254:   /* zebra_interface_state_read() updates interface structure in iflist. */
        !           255:   s = zclient->ibuf;
        !           256:   ifp = zebra_interface_state_read (s);
        !           257: 
        !           258:   if (ifp == NULL)
        !           259:     return 0;
        !           260: 
        !           261:   ripng_if_down (ifp);
        !           262: 
        !           263:   if (IS_RIPNG_DEBUG_ZEBRA)
        !           264:     zlog_debug ("interface down %s index %d flags %#llx metric %d mtu %d",
        !           265:                ifp->name, ifp->ifindex,
        !           266:                (unsigned long long) ifp->flags, ifp->metric, ifp->mtu6);
        !           267: 
        !           268:   return 0;
        !           269: }
        !           270: 
        !           271: /* Inteface addition message from zebra. */
        !           272: int
        !           273: ripng_interface_add (int command, struct zclient *zclient, zebra_size_t length)
        !           274: {
        !           275:   struct interface *ifp;
        !           276: 
        !           277:   ifp = zebra_interface_add_read (zclient->ibuf);
        !           278: 
        !           279:   if (IS_RIPNG_DEBUG_ZEBRA)
        !           280:     zlog_debug ("RIPng interface add %s index %d flags %#llx metric %d mtu %d",
        !           281:                ifp->name, ifp->ifindex, (unsigned long long) ifp->flags,
        !           282:                ifp->metric, ifp->mtu6);
        !           283: 
        !           284:   /* Check is this interface is RIP enabled or not.*/
        !           285:   ripng_enable_apply (ifp);
        !           286: 
        !           287:   /* Apply distribute list to the interface. */
        !           288:   ripng_distribute_update_interface (ifp);
        !           289: 
        !           290:   /* Check interface routemap. */
        !           291:   ripng_if_rmap_update_interface (ifp);
        !           292: 
        !           293:   return 0;
        !           294: }
        !           295: 
        !           296: int
        !           297: ripng_interface_delete (int command, struct zclient *zclient,
        !           298:                        zebra_size_t length)
        !           299: {
        !           300:   struct interface *ifp;
        !           301:   struct stream *s;
        !           302: 
        !           303:   s = zclient->ibuf;
        !           304:   /*  zebra_interface_state_read() updates interface structure in iflist */
        !           305:   ifp = zebra_interface_state_read(s);
        !           306: 
        !           307:   if (ifp == NULL)
        !           308:     return 0;
        !           309: 
        !           310:   if (if_is_up (ifp)) {
        !           311:     ripng_if_down(ifp);
        !           312:   }
        !           313: 
        !           314:   zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
        !           315:             ifp->name, ifp->ifindex, (unsigned long long) ifp->flags,
        !           316:            ifp->metric, ifp->mtu6);
        !           317: 
        !           318:   /* To support pseudo interface do not free interface structure.  */
        !           319:   /* if_delete(ifp); */
        !           320:   ifp->ifindex = IFINDEX_INTERNAL;
        !           321: 
        !           322:   return 0;
        !           323: }
        !           324: 
        !           325: void
        !           326: ripng_interface_clean (void)
        !           327: {
        !           328:   struct listnode *node, *nnode;
        !           329:   struct interface *ifp;
        !           330:   struct ripng_interface *ri;
        !           331: 
        !           332:   for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
        !           333:     {
        !           334:       ri = ifp->info;
        !           335: 
        !           336:       ri->enable_network = 0;
        !           337:       ri->enable_interface = 0;
        !           338:       ri->running = 0;
        !           339: 
        !           340:       if (ri->t_wakeup)
        !           341:         {
        !           342:           thread_cancel (ri->t_wakeup);
        !           343:           ri->t_wakeup = NULL;
        !           344:         }
        !           345:     }
        !           346: }
        !           347: 
        !           348: void
        !           349: ripng_interface_reset (void)
        !           350: {
        !           351:   struct listnode *node;
        !           352:   struct interface *ifp;
        !           353:   struct ripng_interface *ri;
        !           354: 
        !           355:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
        !           356:     {
        !           357:       ri = ifp->info;
        !           358: 
        !           359:       ri->enable_network = 0;
        !           360:       ri->enable_interface = 0;
        !           361:       ri->running = 0;
        !           362: 
        !           363:       ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
        !           364:       ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON;
        !           365: 
        !           366:       ri->list[RIPNG_FILTER_IN] = NULL;
        !           367:       ri->list[RIPNG_FILTER_OUT] = NULL;
        !           368: 
        !           369:       ri->prefix[RIPNG_FILTER_IN] = NULL;
        !           370:       ri->prefix[RIPNG_FILTER_OUT] = NULL;
        !           371: 
        !           372:       if (ri->t_wakeup)
        !           373:         {
        !           374:           thread_cancel (ri->t_wakeup);
        !           375:           ri->t_wakeup = NULL;
        !           376:         }
        !           377: 
        !           378:       ri->passive = 0;
        !           379:     }
        !           380: }
        !           381: 
        !           382: static void
        !           383: ripng_apply_address_add (struct connected *ifc) {
        !           384:   struct prefix_ipv6 address;
        !           385:   struct prefix *p;
        !           386: 
        !           387:   if (!ripng)
        !           388:     return;
        !           389: 
        !           390:   if (! if_is_up(ifc->ifp))
        !           391:     return;
        !           392: 
        !           393:   p = ifc->address;
        !           394: 
        !           395:   memset (&address, 0, sizeof (address));
        !           396:   address.family = p->family;
        !           397:   address.prefix = p->u.prefix6;
        !           398:   address.prefixlen = p->prefixlen;
        !           399:   apply_mask_ipv6(&address);
        !           400: 
        !           401:   /* Check if this interface is RIP enabled or not
        !           402:      or  Check if this address's prefix is RIP enabled */
        !           403:   if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) ||
        !           404:       (ripng_enable_network_lookup2(ifc) >= 0))
        !           405:     ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
        !           406:                            &address, ifc->ifp->ifindex, NULL);
        !           407: 
        !           408: }
        !           409: 
        !           410: int
        !           411: ripng_interface_address_add (int command, struct zclient *zclient,
        !           412:                             zebra_size_t length)
        !           413: {
        !           414:   struct connected *c;
        !           415:   struct prefix *p;
        !           416: 
        !           417:   c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, 
        !           418:                                     zclient->ibuf);
        !           419: 
        !           420:   if (c == NULL)
        !           421:     return 0;
        !           422: 
        !           423:   p = c->address;
        !           424: 
        !           425:   if (p->family == AF_INET6)
        !           426:     {
        !           427:       struct ripng_interface *ri = c->ifp->info;
        !           428:       
        !           429:       if (IS_RIPNG_DEBUG_ZEBRA)
        !           430:        zlog_debug ("RIPng connected address %s/%d add",
        !           431:                   inet6_ntoa(p->u.prefix6),
        !           432:                   p->prefixlen);
        !           433:       
        !           434:       /* Check is this prefix needs to be redistributed. */
        !           435:       ripng_apply_address_add(c);
        !           436: 
        !           437:       /* Let's try once again whether the interface could be activated */
        !           438:       if (!ri->running) {
        !           439:         /* Check if this interface is RIP enabled or not.*/
        !           440:         ripng_enable_apply (c->ifp);
        !           441: 
        !           442:         /* Apply distribute list to the interface. */
        !           443:         ripng_distribute_update_interface (c->ifp);
        !           444: 
        !           445:         /* Check interface routemap. */
        !           446:         ripng_if_rmap_update_interface (c->ifp);
        !           447:       }
        !           448: 
        !           449:     }
        !           450: 
        !           451:   return 0;
        !           452: }
        !           453: 
        !           454: static void
        !           455: ripng_apply_address_del (struct connected *ifc) {
        !           456:   struct prefix_ipv6 address;
        !           457:   struct prefix *p;
        !           458: 
        !           459:   if (!ripng)
        !           460:     return;
        !           461: 
        !           462:   if (! if_is_up(ifc->ifp))
        !           463:     return;
        !           464: 
        !           465:   p = ifc->address;
        !           466: 
        !           467:   memset (&address, 0, sizeof (address));
        !           468:   address.family = p->family;
        !           469:   address.prefix = p->u.prefix6;
        !           470:   address.prefixlen = p->prefixlen;
        !           471:   apply_mask_ipv6(&address);
        !           472: 
        !           473:   ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
        !           474:                             &address, ifc->ifp->ifindex);
        !           475: }
        !           476: 
        !           477: int
        !           478: ripng_interface_address_delete (int command, struct zclient *zclient,
        !           479:                                zebra_size_t length)
        !           480: {
        !           481:   struct connected *ifc;
        !           482:   struct prefix *p;
        !           483:   char buf[INET6_ADDRSTRLEN];
        !           484: 
        !           485:   ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE, 
        !           486:                                       zclient->ibuf);
        !           487:   
        !           488:   if (ifc)
        !           489:     {
        !           490:       p = ifc->address;
        !           491: 
        !           492:       if (p->family == AF_INET6)
        !           493:        {
        !           494:          if (IS_RIPNG_DEBUG_ZEBRA)
        !           495:            zlog_debug ("RIPng connected address %s/%d delete",
        !           496:                       inet_ntop (AF_INET6, &p->u.prefix6, buf,
        !           497:                                  INET6_ADDRSTRLEN),
        !           498:                       p->prefixlen);
        !           499: 
        !           500:          /* Check wether this prefix needs to be removed. */
        !           501:          ripng_apply_address_del(ifc);
        !           502:        }
        !           503:       connected_free (ifc);
        !           504:     }
        !           505: 
        !           506:   return 0;
        !           507: }
        !           508: 
        !           509: /* RIPng enable interface vector. */
        !           510: vector ripng_enable_if;
        !           511: 
        !           512: /* RIPng enable network table. */
        !           513: struct route_table *ripng_enable_network;
        !           514: 
        !           515: /* Lookup RIPng enable network. */
        !           516: /* Check wether the interface has at least a connected prefix that
        !           517:  * is within the ripng_enable_network table. */
        !           518: static int
        !           519: ripng_enable_network_lookup_if (struct interface *ifp)
        !           520: {
        !           521:   struct listnode *node;
        !           522:   struct connected *connected;
        !           523:   struct prefix_ipv6 address;
        !           524: 
        !           525:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
        !           526:     {
        !           527:       struct prefix *p; 
        !           528:       struct route_node *node;
        !           529: 
        !           530:       p = connected->address;
        !           531: 
        !           532:       if (p->family == AF_INET6)
        !           533:         {
        !           534:           address.family = AF_INET6;
        !           535:           address.prefix = p->u.prefix6;
        !           536:           address.prefixlen = IPV6_MAX_BITLEN;
        !           537: 
        !           538:           node = route_node_match (ripng_enable_network,
        !           539:                                    (struct prefix *)&address);
        !           540:           if (node)
        !           541:             {
        !           542:               route_unlock_node (node);
        !           543:               return 1;
        !           544:             }
        !           545:         }
        !           546:     }
        !           547:   return -1;
        !           548: }
        !           549: 
        !           550: /* Check wether connected is within the ripng_enable_network table. */
        !           551: static int
        !           552: ripng_enable_network_lookup2 (struct connected *connected)
        !           553: {
        !           554:   struct prefix_ipv6 address;
        !           555:   struct prefix *p;
        !           556: 
        !           557:   p = connected->address;
        !           558: 
        !           559:   if (p->family == AF_INET6) {
        !           560:     struct route_node *node;
        !           561: 
        !           562:     address.family = p->family;
        !           563:     address.prefix = p->u.prefix6;
        !           564:     address.prefixlen = IPV6_MAX_BITLEN;
        !           565: 
        !           566:     /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */
        !           567:     node = route_node_match (ripng_enable_network,
        !           568:                              (struct prefix *)&address);
        !           569: 
        !           570:     if (node) {
        !           571:       route_unlock_node (node);
        !           572:       return 1;
        !           573:     }
        !           574:   }
        !           575: 
        !           576:   return -1;
        !           577: }
        !           578: 
        !           579: /* Add RIPng enable network. */
        !           580: static int
        !           581: ripng_enable_network_add (struct prefix *p)
        !           582: {
        !           583:   struct route_node *node;
        !           584: 
        !           585:   node = route_node_get (ripng_enable_network, p);
        !           586: 
        !           587:   if (node->info)
        !           588:     {
        !           589:       route_unlock_node (node);
        !           590:       return -1;
        !           591:     }
        !           592:   else
        !           593:     node->info = (char *) "enabled";
        !           594: 
        !           595:   /* XXX: One should find a better solution than a generic one */
        !           596:   ripng_enable_apply_all();
        !           597: 
        !           598:   return 1;
        !           599: }
        !           600: 
        !           601: /* Delete RIPng enable network. */
        !           602: static int
        !           603: ripng_enable_network_delete (struct prefix *p)
        !           604: {
        !           605:   struct route_node *node;
        !           606: 
        !           607:   node = route_node_lookup (ripng_enable_network, p);
        !           608:   if (node)
        !           609:     {
        !           610:       node->info = NULL;
        !           611: 
        !           612:       /* Unlock info lock. */
        !           613:       route_unlock_node (node);
        !           614: 
        !           615:       /* Unlock lookup lock. */
        !           616:       route_unlock_node (node);
        !           617: 
        !           618:       return 1;
        !           619:     }
        !           620:   return -1;
        !           621: }
        !           622: 
        !           623: /* Lookup function. */
        !           624: static int
        !           625: ripng_enable_if_lookup (const char *ifname)
        !           626: {
        !           627:   unsigned int i;
        !           628:   char *str;
        !           629: 
        !           630:   for (i = 0; i < vector_active (ripng_enable_if); i++)
        !           631:     if ((str = vector_slot (ripng_enable_if, i)) != NULL)
        !           632:       if (strcmp (str, ifname) == 0)
        !           633:        return i;
        !           634:   return -1;
        !           635: }
        !           636: 
        !           637: /* Add interface to ripng_enable_if. */
        !           638: static int
        !           639: ripng_enable_if_add (const char *ifname)
        !           640: {
        !           641:   int ret;
        !           642: 
        !           643:   ret = ripng_enable_if_lookup (ifname);
        !           644:   if (ret >= 0)
        !           645:     return -1;
        !           646: 
        !           647:   vector_set (ripng_enable_if, strdup (ifname));
        !           648: 
        !           649:   ripng_enable_apply_all();
        !           650: 
        !           651:   return 1;
        !           652: }
        !           653: 
        !           654: /* Delete interface from ripng_enable_if. */
        !           655: static int
        !           656: ripng_enable_if_delete (const char *ifname)
        !           657: {
        !           658:   int index;
        !           659:   char *str;
        !           660: 
        !           661:   index = ripng_enable_if_lookup (ifname);
        !           662:   if (index < 0)
        !           663:     return -1;
        !           664: 
        !           665:   str = vector_slot (ripng_enable_if, index);
        !           666:   free (str);
        !           667:   vector_unset (ripng_enable_if, index);
        !           668: 
        !           669:   ripng_enable_apply_all();
        !           670: 
        !           671:   return 1;
        !           672: }
        !           673: 
        !           674: /* Wake up interface. */
        !           675: static int
        !           676: ripng_interface_wakeup (struct thread *t)
        !           677: {
        !           678:   struct interface *ifp;
        !           679:   struct ripng_interface *ri;
        !           680: 
        !           681:   /* Get interface. */
        !           682:   ifp = THREAD_ARG (t);
        !           683: 
        !           684:   ri = ifp->info;
        !           685:   ri->t_wakeup = NULL;
        !           686: 
        !           687:   /* Join to multicast group. */
        !           688:   if (ripng_multicast_join (ifp) < 0) {
        !           689:     zlog_err ("multicast join failed, interface %s not running", ifp->name);
        !           690:     return 0;
        !           691:   }
        !           692:     
        !           693:   /* Set running flag. */
        !           694:   ri->running = 1;
        !           695: 
        !           696:   /* Send RIP request to the interface. */
        !           697:   ripng_request (ifp);
        !           698: 
        !           699:   return 0;
        !           700: }
        !           701: 
        !           702: static void
        !           703: ripng_connect_set (struct interface *ifp, int set)
        !           704: {
        !           705:   struct listnode *node, *nnode;
        !           706:   struct connected *connected;
        !           707:   struct prefix_ipv6 address;
        !           708: 
        !           709:   for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
        !           710:     {
        !           711:       struct prefix *p;
        !           712:       p = connected->address;
        !           713: 
        !           714:       if (p->family != AF_INET6)
        !           715:         continue;
        !           716: 
        !           717:       address.family = AF_INET6;
        !           718:       address.prefix = p->u.prefix6;
        !           719:       address.prefixlen = p->prefixlen;
        !           720:       apply_mask_ipv6 (&address);
        !           721: 
        !           722:       if (set) {
        !           723:         /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
        !           724:         if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) ||
        !           725:             (ripng_enable_network_lookup2(connected) >= 0))
        !           726:           ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
        !           727:                                   &address, connected->ifp->ifindex, NULL);
        !           728:       } else {
        !           729:         ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
        !           730:                                    &address, connected->ifp->ifindex);
        !           731:         if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT))
        !           732:           ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE,
        !           733:                                   &address, connected->ifp->ifindex, NULL);
        !           734:       }
        !           735:     }
        !           736: }
        !           737: 
        !           738: /* Check RIPng is enabed on this interface. */
        !           739: void
        !           740: ripng_enable_apply (struct interface *ifp)
        !           741: {
        !           742:   int ret;
        !           743:   struct ripng_interface *ri = NULL;
        !           744: 
        !           745:   /* Check interface. */
        !           746:   if (! if_is_up (ifp))
        !           747:     return;
        !           748:   
        !           749:   ri = ifp->info;
        !           750: 
        !           751:   /* Is this interface a candidate for RIPng ? */
        !           752:   ret = ripng_enable_network_lookup_if (ifp);
        !           753: 
        !           754:   /* If the interface is matched. */
        !           755:   if (ret > 0)
        !           756:     ri->enable_network = 1;
        !           757:   else
        !           758:     ri->enable_network = 0;
        !           759: 
        !           760:   /* Check interface name configuration. */
        !           761:   ret = ripng_enable_if_lookup (ifp->name);
        !           762:   if (ret >= 0)
        !           763:     ri->enable_interface = 1;
        !           764:   else
        !           765:     ri->enable_interface = 0;
        !           766: 
        !           767:   /* any candidate interface MUST have a link-local IPv6 address */
        !           768:   if ((! ripng_if_ipv6_lladdress_check (ifp)) &&
        !           769:       (ri->enable_network || ri->enable_interface)) {
        !           770:     ri->enable_network = 0;
        !           771:     ri->enable_interface = 0;
        !           772:     zlog_warn("Interface %s does not have any link-local address",
        !           773:               ifp->name);
        !           774:   }
        !           775: 
        !           776:   /* Update running status of the interface. */
        !           777:   if (ri->enable_network || ri->enable_interface)
        !           778:     {
        !           779:        {
        !           780:          if (IS_RIPNG_DEBUG_EVENT)
        !           781:            zlog_debug ("RIPng turn on %s", ifp->name);
        !           782: 
        !           783:          /* Add interface wake up thread. */
        !           784:          if (! ri->t_wakeup)
        !           785:            ri->t_wakeup = thread_add_timer (master, ripng_interface_wakeup,
        !           786:                                             ifp, 1);
        !           787: 
        !           788:          ripng_connect_set (ifp, 1);
        !           789:        }
        !           790:     }
        !           791:   else
        !           792:     {
        !           793:       if (ri->running)
        !           794:        {
        !           795:          /* Might as well clean up the route table as well
        !           796:           * ripng_if_down sets to 0 ri->running, and displays "turn off %s"
        !           797:           **/
        !           798:          ripng_if_down(ifp);
        !           799: 
        !           800:          ripng_connect_set (ifp, 0);
        !           801:        }
        !           802:     }
        !           803: }
        !           804: 
        !           805: /* Set distribute list to all interfaces. */
        !           806: static void
        !           807: ripng_enable_apply_all (void)
        !           808: {
        !           809:   struct interface *ifp;
        !           810:   struct listnode *node;
        !           811: 
        !           812:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
        !           813:     ripng_enable_apply (ifp);
        !           814: }
        !           815: 
        !           816: /* Clear all network and neighbor configuration */
        !           817: void
        !           818: ripng_clean_network ()
        !           819: {
        !           820:   unsigned int i;
        !           821:   char *str;
        !           822:   struct route_node *rn;
        !           823: 
        !           824:   /* ripng_enable_network */
        !           825:   for (rn = route_top (ripng_enable_network); rn; rn = route_next (rn))
        !           826:     if (rn->info) {
        !           827:       rn->info = NULL;
        !           828:       route_unlock_node(rn);
        !           829:     }
        !           830: 
        !           831:   /* ripng_enable_if */
        !           832:   for (i = 0; i < vector_active (ripng_enable_if); i++)
        !           833:     if ((str = vector_slot (ripng_enable_if, i)) != NULL) {
        !           834:       free (str);
        !           835:       vector_slot (ripng_enable_if, i) = NULL;
        !           836:     }
        !           837: }
        !           838: 
        !           839: /* Vector to store passive-interface name. */
        !           840: vector Vripng_passive_interface;
        !           841: 
        !           842: /* Utility function for looking up passive interface settings. */
        !           843: static int
        !           844: ripng_passive_interface_lookup (const char *ifname)
        !           845: {
        !           846:   unsigned int i;
        !           847:   char *str;
        !           848: 
        !           849:   for (i = 0; i < vector_active (Vripng_passive_interface); i++)
        !           850:     if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
        !           851:       if (strcmp (str, ifname) == 0)
        !           852:        return i;
        !           853:   return -1;
        !           854: }
        !           855: 
        !           856: void
        !           857: ripng_passive_interface_apply (struct interface *ifp)
        !           858: {
        !           859:   int ret;
        !           860:   struct ripng_interface *ri;
        !           861: 
        !           862:   ri = ifp->info;
        !           863: 
        !           864:   ret = ripng_passive_interface_lookup (ifp->name);
        !           865:   if (ret < 0)
        !           866:     ri->passive = 0;
        !           867:   else
        !           868:     ri->passive = 1;
        !           869: }
        !           870: 
        !           871: static void
        !           872: ripng_passive_interface_apply_all (void)
        !           873: {
        !           874:   struct interface *ifp;
        !           875:   struct listnode *node;
        !           876: 
        !           877:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
        !           878:     ripng_passive_interface_apply (ifp);
        !           879: }
        !           880: 
        !           881: /* Passive interface. */
        !           882: static int
        !           883: ripng_passive_interface_set (struct vty *vty, const char *ifname)
        !           884: {
        !           885:   if (ripng_passive_interface_lookup (ifname) >= 0)
        !           886:     return CMD_WARNING;
        !           887: 
        !           888:   vector_set (Vripng_passive_interface, strdup (ifname));
        !           889: 
        !           890:   ripng_passive_interface_apply_all ();
        !           891: 
        !           892:   return CMD_SUCCESS;
        !           893: }
        !           894: 
        !           895: static int
        !           896: ripng_passive_interface_unset (struct vty *vty, const char *ifname)
        !           897: {
        !           898:   int i;
        !           899:   char *str;
        !           900: 
        !           901:   i = ripng_passive_interface_lookup (ifname);
        !           902:   if (i < 0)
        !           903:     return CMD_WARNING;
        !           904: 
        !           905:   str = vector_slot (Vripng_passive_interface, i);
        !           906:   free (str);
        !           907:   vector_unset (Vripng_passive_interface, i);
        !           908: 
        !           909:   ripng_passive_interface_apply_all ();
        !           910: 
        !           911:   return CMD_SUCCESS;
        !           912: }
        !           913: 
        !           914: /* Free all configured RIP passive-interface settings. */
        !           915: void
        !           916: ripng_passive_interface_clean (void)
        !           917: {
        !           918:   unsigned int i;
        !           919:   char *str;
        !           920: 
        !           921:   for (i = 0; i < vector_active (Vripng_passive_interface); i++)
        !           922:     if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
        !           923:       {
        !           924:        free (str);
        !           925:        vector_slot (Vripng_passive_interface, i) = NULL;
        !           926:       }
        !           927:   ripng_passive_interface_apply_all ();
        !           928: }
        !           929: 
        !           930: /* Write RIPng enable network and interface to the vty. */
        !           931: int
        !           932: ripng_network_write (struct vty *vty, int config_mode)
        !           933: {
        !           934:   unsigned int i;
        !           935:   const char *ifname;
        !           936:   struct route_node *node;
        !           937:   char buf[BUFSIZ];
        !           938: 
        !           939:   /* Write enable network. */
        !           940:   for (node = route_top (ripng_enable_network); node; node = route_next (node))
        !           941:     if (node->info)
        !           942:       {
        !           943:        struct prefix *p = &node->p;
        !           944:        vty_out (vty, "%s%s/%d%s", 
        !           945:                 config_mode ? " network " : "    ",
        !           946:                 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
        !           947:                 p->prefixlen,
        !           948:                 VTY_NEWLINE);
        !           949: 
        !           950:       }
        !           951:   
        !           952:   /* Write enable interface. */
        !           953:   for (i = 0; i < vector_active (ripng_enable_if); i++)
        !           954:     if ((ifname = vector_slot (ripng_enable_if, i)) != NULL)
        !           955:       vty_out (vty, "%s%s%s",
        !           956:               config_mode ? " network " : "    ",
        !           957:               ifname,
        !           958:               VTY_NEWLINE);
        !           959: 
        !           960:   /* Write passive interface. */
        !           961:   if (config_mode)
        !           962:     for (i = 0; i < vector_active (Vripng_passive_interface); i++)
        !           963:       if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
        !           964:         vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
        !           965: 
        !           966:   return 0;
        !           967: }
        !           968: 
        !           969: /* RIPng enable on specified interface or matched network. */
        !           970: DEFUN (ripng_network,
        !           971:        ripng_network_cmd,
        !           972:        "network IF_OR_ADDR",
        !           973:        "RIPng enable on specified interface or network.\n"
        !           974:        "Interface or address")
        !           975: {
        !           976:   int ret;
        !           977:   struct prefix p;
        !           978: 
        !           979:   ret = str2prefix (argv[0], &p);
        !           980: 
        !           981:   /* Given string is IPv6 network or interface name. */
        !           982:   if (ret)
        !           983:     ret = ripng_enable_network_add (&p);
        !           984:   else
        !           985:     ret = ripng_enable_if_add (argv[0]);
        !           986: 
        !           987:   if (ret < 0)
        !           988:     {
        !           989:       vty_out (vty, "There is same network configuration %s%s", argv[0],
        !           990:               VTY_NEWLINE);
        !           991:       return CMD_WARNING;
        !           992:     }
        !           993: 
        !           994:   return CMD_SUCCESS;
        !           995: }
        !           996: 
        !           997: /* RIPng enable on specified interface or matched network. */
        !           998: DEFUN (no_ripng_network,
        !           999:        no_ripng_network_cmd,
        !          1000:        "no network IF_OR_ADDR",
        !          1001:        NO_STR
        !          1002:        "RIPng enable on specified interface or network.\n"
        !          1003:        "Interface or address")
        !          1004: {
        !          1005:   int ret;
        !          1006:   struct prefix p;
        !          1007: 
        !          1008:   ret = str2prefix (argv[0], &p);
        !          1009: 
        !          1010:   /* Given string is interface name. */
        !          1011:   if (ret)
        !          1012:     ret = ripng_enable_network_delete (&p);
        !          1013:   else
        !          1014:     ret = ripng_enable_if_delete (argv[0]);
        !          1015: 
        !          1016:   if (ret < 0)
        !          1017:     {
        !          1018:       vty_out (vty, "can't find network %s%s", argv[0],
        !          1019:               VTY_NEWLINE);
        !          1020:       return CMD_WARNING;
        !          1021:     }
        !          1022:   
        !          1023:   return CMD_SUCCESS;
        !          1024: }
        !          1025: 
        !          1026: DEFUN (ipv6_ripng_split_horizon,
        !          1027:        ipv6_ripng_split_horizon_cmd,
        !          1028:        "ipv6 ripng split-horizon",
        !          1029:        IPV6_STR
        !          1030:        "Routing Information Protocol\n"
        !          1031:        "Perform split horizon\n")
        !          1032: {
        !          1033:   struct interface *ifp;
        !          1034:   struct ripng_interface *ri;
        !          1035: 
        !          1036:   ifp = vty->index;
        !          1037:   ri = ifp->info;
        !          1038: 
        !          1039:   ri->split_horizon = RIPNG_SPLIT_HORIZON;
        !          1040:   return CMD_SUCCESS;
        !          1041: }
        !          1042: 
        !          1043: DEFUN (ipv6_ripng_split_horizon_poisoned_reverse,
        !          1044:        ipv6_ripng_split_horizon_poisoned_reverse_cmd,
        !          1045:        "ipv6 ripng split-horizon poisoned-reverse",
        !          1046:        IPV6_STR
        !          1047:        "Routing Information Protocol\n"
        !          1048:        "Perform split horizon\n"
        !          1049:        "With poisoned-reverse\n")
        !          1050: {
        !          1051:   struct interface *ifp;
        !          1052:   struct ripng_interface *ri;
        !          1053: 
        !          1054:   ifp = vty->index;
        !          1055:   ri = ifp->info;
        !          1056: 
        !          1057:   ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE;
        !          1058:   return CMD_SUCCESS;
        !          1059: }
        !          1060: 
        !          1061: DEFUN (no_ipv6_ripng_split_horizon,
        !          1062:        no_ipv6_ripng_split_horizon_cmd,
        !          1063:        "no ipv6 ripng split-horizon",
        !          1064:        NO_STR
        !          1065:        IPV6_STR
        !          1066:        "Routing Information Protocol\n"
        !          1067:        "Perform split horizon\n")
        !          1068: {
        !          1069:   struct interface *ifp;
        !          1070:   struct ripng_interface *ri;
        !          1071: 
        !          1072:   ifp = vty->index;
        !          1073:   ri = ifp->info;
        !          1074: 
        !          1075:   ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
        !          1076:   return CMD_SUCCESS;
        !          1077: }
        !          1078: 
        !          1079: ALIAS (no_ipv6_ripng_split_horizon,
        !          1080:        no_ipv6_ripng_split_horizon_poisoned_reverse_cmd,
        !          1081:        "no ipv6 ripng split-horizon poisoned-reverse",
        !          1082:        NO_STR
        !          1083:        IPV6_STR
        !          1084:        "Routing Information Protocol\n"
        !          1085:        "Perform split horizon\n"
        !          1086:        "With poisoned-reverse\n")
        !          1087: 
        !          1088: DEFUN (ripng_passive_interface,
        !          1089:        ripng_passive_interface_cmd,
        !          1090:        "passive-interface IFNAME",
        !          1091:        "Suppress routing updates on an interface\n"
        !          1092:        "Interface name\n")
        !          1093: {
        !          1094:   return ripng_passive_interface_set (vty, argv[0]);
        !          1095: }
        !          1096: 
        !          1097: DEFUN (no_ripng_passive_interface,
        !          1098:        no_ripng_passive_interface_cmd,
        !          1099:        "no passive-interface IFNAME",
        !          1100:        NO_STR
        !          1101:        "Suppress routing updates on an interface\n"
        !          1102:        "Interface name\n")
        !          1103: {
        !          1104:   return ripng_passive_interface_unset (vty, argv[0]);
        !          1105: }
        !          1106: 
        !          1107: static struct ripng_interface *
        !          1108: ri_new (void)
        !          1109: {
        !          1110:   struct ripng_interface *ri;
        !          1111:   ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface));
        !          1112: 
        !          1113:   /* Set default split-horizon behavior.  If the interface is Frame
        !          1114:      Relay or SMDS is enabled, the default value for split-horizon is
        !          1115:      off.  But currently Zebra does detect Frame Relay or SMDS
        !          1116:      interface.  So all interface is set to split horizon.  */
        !          1117:   ri->split_horizon_default = RIPNG_SPLIT_HORIZON;
        !          1118:   ri->split_horizon = ri->split_horizon_default;
        !          1119: 
        !          1120:   return ri;
        !          1121: }
        !          1122: 
        !          1123: static int
        !          1124: ripng_if_new_hook (struct interface *ifp)
        !          1125: {
        !          1126:   ifp->info = ri_new ();
        !          1127:   return 0;
        !          1128: }
        !          1129: 
        !          1130: /* Called when interface structure deleted. */
        !          1131: static int
        !          1132: ripng_if_delete_hook (struct interface *ifp)
        !          1133: {
        !          1134:   XFREE (MTYPE_IF, ifp->info);
        !          1135:   ifp->info = NULL;
        !          1136:   return 0;
        !          1137: }
        !          1138: 
        !          1139: /* Configuration write function for ripngd. */
        !          1140: static int
        !          1141: interface_config_write (struct vty *vty)
        !          1142: {
        !          1143:   struct listnode *node;
        !          1144:   struct interface *ifp;
        !          1145:   struct ripng_interface *ri;
        !          1146:   int write = 0;
        !          1147: 
        !          1148:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
        !          1149:     {
        !          1150:       ri = ifp->info;
        !          1151: 
        !          1152:       /* Do not display the interface if there is no
        !          1153:        * configuration about it.
        !          1154:        **/
        !          1155:       if ((!ifp->desc) &&
        !          1156:           (ri->split_horizon == ri->split_horizon_default))
        !          1157:         continue;
        !          1158: 
        !          1159:       vty_out (vty, "interface %s%s", ifp->name,
        !          1160:               VTY_NEWLINE);
        !          1161:       if (ifp->desc)
        !          1162:        vty_out (vty, " description %s%s", ifp->desc,
        !          1163:                 VTY_NEWLINE);
        !          1164: 
        !          1165:       /* Split horizon. */
        !          1166:       if (ri->split_horizon != ri->split_horizon_default)
        !          1167:        {
        !          1168:           switch (ri->split_horizon) {
        !          1169:           case RIPNG_SPLIT_HORIZON:
        !          1170:             vty_out (vty, " ipv6 ripng split-horizon%s", VTY_NEWLINE);
        !          1171:             break;
        !          1172:           case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
        !          1173:             vty_out (vty, " ipv6 ripng split-horizon poisoned-reverse%s",
        !          1174:                           VTY_NEWLINE);
        !          1175:             break;
        !          1176:           case RIPNG_NO_SPLIT_HORIZON:
        !          1177:           default:
        !          1178:             vty_out (vty, " no ipv6 ripng split-horizon%s", VTY_NEWLINE);
        !          1179:             break;
        !          1180:           }
        !          1181:        }
        !          1182: 
        !          1183:       vty_out (vty, "!%s", VTY_NEWLINE);
        !          1184: 
        !          1185:       write++;
        !          1186:     }
        !          1187:   return write;
        !          1188: }
        !          1189: 
        !          1190: /* ripngd's interface node. */
        !          1191: static struct cmd_node interface_node =
        !          1192: {
        !          1193:   INTERFACE_NODE,
        !          1194:   "%s(config-if)# ",
        !          1195:   1 /* VTYSH */
        !          1196: };
        !          1197: 
        !          1198: /* Initialization of interface. */
        !          1199: void
        !          1200: ripng_if_init ()
        !          1201: {
        !          1202:   /* Interface initialize. */
        !          1203:   iflist = list_new ();
        !          1204:   if_add_hook (IF_NEW_HOOK, ripng_if_new_hook);
        !          1205:   if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook);
        !          1206: 
        !          1207:   /* RIPng enable network init. */
        !          1208:   ripng_enable_network = route_table_init ();
        !          1209: 
        !          1210:   /* RIPng enable interface init. */
        !          1211:   ripng_enable_if = vector_init (1);
        !          1212: 
        !          1213:   /* RIPng passive interface. */
        !          1214:   Vripng_passive_interface = vector_init (1);
        !          1215: 
        !          1216:   /* Install interface node. */
        !          1217:   install_node (&interface_node, interface_config_write);
        !          1218:   
        !          1219:   /* Install commands. */
        !          1220:   install_element (CONFIG_NODE, &interface_cmd);
        !          1221:   install_element (CONFIG_NODE, &no_interface_cmd);
        !          1222:   install_default (INTERFACE_NODE);
        !          1223:   install_element (INTERFACE_NODE, &interface_desc_cmd);
        !          1224:   install_element (INTERFACE_NODE, &no_interface_desc_cmd);
        !          1225: 
        !          1226:   install_element (RIPNG_NODE, &ripng_network_cmd);
        !          1227:   install_element (RIPNG_NODE, &no_ripng_network_cmd);
        !          1228:   install_element (RIPNG_NODE, &ripng_passive_interface_cmd);
        !          1229:   install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd);
        !          1230: 
        !          1231:   install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
        !          1232:   install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_poisoned_reverse_cmd);
        !          1233:   install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd);
        !          1234:   install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_poisoned_reverse_cmd);
        !          1235: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>