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

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

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