Annotation of embedaddon/quagga/ripngd/ripng_interface.c, revision 1.1.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>