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

1.1       misho       1: /* RIPng daemon
                      2:  * Copyright (C) 1998, 1999 Kunihiro Ishiguro
                      3:  *
                      4:  * This file is part of GNU Zebra.
                      5:  *
                      6:  * GNU Zebra is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2, or (at your option) any
                      9:  * later version.
                     10:  *
                     11:  * GNU Zebra is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU General Public License
                     17:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
                     18:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     19:  * 02111-1307, USA.  
                     20:  */
                     21: 
                     22: #include <zebra.h>
                     23: 
                     24: #include "prefix.h"
                     25: #include "filter.h"
                     26: #include "log.h"
                     27: #include "thread.h"
                     28: #include "memory.h"
                     29: #include "if.h"
                     30: #include "stream.h"
                     31: #include "table.h"
                     32: #include "command.h"
                     33: #include "sockopt.h"
                     34: #include "distribute.h"
                     35: #include "plist.h"
                     36: #include "routemap.h"
                     37: #include "if_rmap.h"
                     38: #include "privs.h"
                     39: 
                     40: #include "ripngd/ripngd.h"
                     41: #include "ripngd/ripng_route.h"
                     42: #include "ripngd/ripng_debug.h"
                     43: #include "ripngd/ripng_nexthop.h"
                     44: 
                     45: /* RIPng structure which includes many parameters related to RIPng
                     46:    protocol. If ripng couldn't active or ripng doesn't configured,
                     47:    ripng->fd must be negative value. */
                     48: struct ripng *ripng = NULL;
                     49: 
                     50: enum
                     51: {
                     52:   ripng_all_route,
                     53:   ripng_changed_route,
                     54: };
                     55: 
                     56: extern struct zebra_privs_t ripngd_privs;
                     57: 
                     58: /* Prototypes. */
                     59: void
                     60: ripng_output_process (struct interface *, struct sockaddr_in6 *, int);
                     61: 
                     62: int
                     63: ripng_triggered_update (struct thread *);
                     64: 
                     65: /* RIPng next hop specification. */
                     66: struct ripng_nexthop
                     67: {
                     68:   enum ripng_nexthop_type
                     69:   {
                     70:     RIPNG_NEXTHOP_UNSPEC,
                     71:     RIPNG_NEXTHOP_ADDRESS
                     72:   } flag;
                     73:   struct in6_addr address;
                     74: };
                     75: 
                     76: static int
                     77: ripng_route_rte (struct ripng_info *rinfo)
                     78: {
                     79:   return (rinfo->type == ZEBRA_ROUTE_RIPNG && rinfo->sub_type == RIPNG_ROUTE_RTE);
                     80: }
                     81: 
                     82: /* Allocate new ripng information. */
                     83: struct ripng_info *
                     84: ripng_info_new ()
                     85: {
                     86:   struct ripng_info *new;
                     87: 
                     88:   new = XCALLOC (MTYPE_RIPNG_ROUTE, sizeof (struct ripng_info));
                     89:   return new;
                     90: }
                     91: 
                     92: /* Free ripng information. */
                     93: void
                     94: ripng_info_free (struct ripng_info *rinfo)
                     95: {
                     96:   XFREE (MTYPE_RIPNG_ROUTE, rinfo);
                     97: }
                     98: 
                     99: /* Create ripng socket. */
                    100: static int 
                    101: ripng_make_socket (void)
                    102: {
                    103:   int ret;
                    104:   int sock;
                    105:   struct sockaddr_in6 ripaddr;
                    106: 
                    107:   sock = socket (AF_INET6, SOCK_DGRAM, 0);
                    108:   if (sock < 0)
                    109:     {
                    110:       zlog (NULL, LOG_ERR, "Can't make ripng socket");
                    111:       return sock;
                    112:     }
                    113: 
                    114:   ret = setsockopt_so_recvbuf (sock, 8096);
                    115:   if (ret < 0)
                    116:     return ret;
                    117:   ret = setsockopt_ipv6_pktinfo (sock, 1);
                    118:   if (ret < 0)
                    119:     return ret;
1.1.1.2 ! misho     120: #ifdef IPTOS_PREC_INTERNETCONTROL
        !           121:   ret = setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL);
        !           122:   if (ret < 0)
        !           123:     return ret;
        !           124: #endif
1.1       misho     125:   ret = setsockopt_ipv6_multicast_hops (sock, 255);
                    126:   if (ret < 0)
                    127:     return ret;
                    128:   ret = setsockopt_ipv6_multicast_loop (sock, 0);
                    129:   if (ret < 0)
                    130:     return ret;
                    131:   ret = setsockopt_ipv6_hoplimit (sock, 1);
                    132:   if (ret < 0)
                    133:     return ret;
                    134: 
                    135:   memset (&ripaddr, 0, sizeof (ripaddr));
                    136:   ripaddr.sin6_family = AF_INET6;
                    137: #ifdef SIN6_LEN
                    138:   ripaddr.sin6_len = sizeof (struct sockaddr_in6);
                    139: #endif /* SIN6_LEN */
                    140:   ripaddr.sin6_port = htons (RIPNG_PORT_DEFAULT);
                    141: 
                    142:   if (ripngd_privs.change (ZPRIVS_RAISE))
                    143:     zlog_err ("ripng_make_socket: could not raise privs");
                    144:   
                    145:   ret = bind (sock, (struct sockaddr *) &ripaddr, sizeof (ripaddr));
                    146:   if (ret < 0)
                    147:   {
                    148:     zlog (NULL, LOG_ERR, "Can't bind ripng socket: %s.", safe_strerror (errno));
                    149:     if (ripngd_privs.change (ZPRIVS_LOWER))
                    150:       zlog_err ("ripng_make_socket: could not lower privs");
                    151:     return ret;
                    152:   }
                    153:   if (ripngd_privs.change (ZPRIVS_LOWER))
                    154:     zlog_err ("ripng_make_socket: could not lower privs");
                    155:   return sock;
                    156: }
                    157: 
                    158: /* Send RIPng packet. */
                    159: int
                    160: ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to, 
                    161:                   struct interface *ifp)
                    162: {
                    163:   int ret;
                    164:   struct msghdr msg;
                    165:   struct iovec iov;
                    166:   struct cmsghdr  *cmsgptr;
                    167:   char adata [256];
                    168:   struct in6_pktinfo *pkt;
                    169:   struct sockaddr_in6 addr;
                    170: 
                    171:   if (IS_RIPNG_DEBUG_SEND) {
                    172:     if (to)
                    173:       zlog_debug ("send to %s", inet6_ntoa (to->sin6_addr));
                    174:     zlog_debug ("  send interface %s", ifp->name);
                    175:     zlog_debug ("  send packet size %d", bufsize);
                    176:   }
                    177: 
                    178:   memset (&addr, 0, sizeof (struct sockaddr_in6));
                    179:   addr.sin6_family = AF_INET6;
                    180: #ifdef SIN6_LEN
                    181:   addr.sin6_len = sizeof (struct sockaddr_in6);
                    182: #endif /* SIN6_LEN */
                    183:   addr.sin6_flowinfo = htonl (RIPNG_PRIORITY_DEFAULT);
                    184: 
                    185:   /* When destination is specified. */
                    186:   if (to != NULL)
                    187:     {
                    188:       addr.sin6_addr = to->sin6_addr;
                    189:       addr.sin6_port = to->sin6_port;
                    190:     }
                    191:   else
                    192:     {
                    193:       inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr);
                    194:       addr.sin6_port = htons (RIPNG_PORT_DEFAULT);
                    195:     }
                    196: 
                    197:   msg.msg_name = (void *) &addr;
                    198:   msg.msg_namelen = sizeof (struct sockaddr_in6);
                    199:   msg.msg_iov = &iov;
                    200:   msg.msg_iovlen = 1;
                    201:   msg.msg_control = (void *) adata;
                    202:   msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
                    203: 
                    204:   iov.iov_base = buf;
                    205:   iov.iov_len = bufsize;
                    206: 
                    207:   cmsgptr = (struct cmsghdr *)adata;
                    208:   cmsgptr->cmsg_len = CMSG_LEN(sizeof (struct in6_pktinfo));
                    209:   cmsgptr->cmsg_level = IPPROTO_IPV6;
                    210:   cmsgptr->cmsg_type = IPV6_PKTINFO;
                    211: 
                    212:   pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
                    213:   memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
                    214:   pkt->ipi6_ifindex = ifp->ifindex;
                    215: 
                    216:   ret = sendmsg (ripng->sock, &msg, 0);
                    217: 
                    218:   if (ret < 0) {
                    219:     if (to)
                    220:       zlog_err ("RIPng send fail on %s to %s: %s", ifp->name, 
                    221:                 inet6_ntoa (to->sin6_addr), safe_strerror (errno));
                    222:     else
                    223:       zlog_err ("RIPng send fail on %s: %s", ifp->name, safe_strerror (errno));
                    224:   }
                    225: 
                    226:   return ret;
                    227: }
                    228: 
                    229: /* Receive UDP RIPng packet from socket. */
                    230: static int
                    231: ripng_recv_packet (int sock, u_char *buf, int bufsize,
                    232:                   struct sockaddr_in6 *from, unsigned int *ifindex, 
                    233:                   int *hoplimit)
                    234: {
                    235:   int ret;
                    236:   struct msghdr msg;
                    237:   struct iovec iov;
                    238:   struct cmsghdr  *cmsgptr;
                    239:   struct in6_addr dst;
                    240: 
                    241:   /* Ancillary data.  This store cmsghdr and in6_pktinfo.  But at this
                    242:      point I can't determine size of cmsghdr */
                    243:   char adata[1024];
                    244: 
                    245:   /* Fill in message and iovec. */
                    246:   msg.msg_name = (void *) from;
                    247:   msg.msg_namelen = sizeof (struct sockaddr_in6);
                    248:   msg.msg_iov = &iov;
                    249:   msg.msg_iovlen = 1;
                    250:   msg.msg_control = (void *) adata;
                    251:   msg.msg_controllen = sizeof adata;
                    252:   iov.iov_base = buf;
                    253:   iov.iov_len = bufsize;
                    254: 
                    255:   /* If recvmsg fail return minus value. */
                    256:   ret = recvmsg (sock, &msg, 0);
                    257:   if (ret < 0)
                    258:     return ret;
                    259: 
                    260:   for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
                    261:        cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) 
                    262:     {
                    263:       /* I want interface index which this packet comes from. */
                    264:       if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
                    265:          cmsgptr->cmsg_type == IPV6_PKTINFO) 
                    266:        {
                    267:          struct in6_pktinfo *ptr;
                    268:          
                    269:          ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
                    270:          *ifindex = ptr->ipi6_ifindex;
                    271:          dst = ptr->ipi6_addr;
                    272: 
                    273:          if (*ifindex == 0)
                    274:            zlog_warn ("Interface index returned by IPV6_PKTINFO is zero");
                    275:         }
                    276: 
                    277:       /* Incoming packet's multicast hop limit. */
                    278:       if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
                    279:          cmsgptr->cmsg_type == IPV6_HOPLIMIT)
                    280:        {
                    281:          int *phoplimit = (int *) CMSG_DATA (cmsgptr);
                    282:          *hoplimit = *phoplimit;
                    283:        }
                    284:     }
                    285: 
                    286:   /* Hoplimit check shold be done when destination address is
                    287:      multicast address. */
                    288:   if (! IN6_IS_ADDR_MULTICAST (&dst))
                    289:     *hoplimit = -1;
                    290: 
                    291:   return ret;
                    292: }
                    293: 
                    294: /* Dump rip packet */
                    295: void
                    296: ripng_packet_dump (struct ripng_packet *packet, int size, const char *sndrcv)
                    297: {
                    298:   caddr_t lim;
                    299:   struct rte *rte;
                    300:   const char *command_str;
                    301: 
                    302:   /* Set command string. */
                    303:   if (packet->command == RIPNG_REQUEST)
                    304:     command_str = "request";
                    305:   else if (packet->command == RIPNG_RESPONSE)
                    306:     command_str = "response";
                    307:   else
                    308:     command_str = "unknown";
                    309: 
                    310:   /* Dump packet header. */
                    311:   zlog_debug ("%s %s version %d packet size %d", 
                    312:             sndrcv, command_str, packet->version, size);
                    313: 
                    314:   /* Dump each routing table entry. */
                    315:   rte = packet->rte;
                    316: 
                    317:   for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
                    318:     {
                    319:       if (rte->metric == RIPNG_METRIC_NEXTHOP)
                    320:        zlog_debug ("  nexthop %s/%d", inet6_ntoa (rte->addr), rte->prefixlen);
                    321:       else
                    322:        zlog_debug ("  %s/%d metric %d tag %d", 
                    323:                   inet6_ntoa (rte->addr), rte->prefixlen, 
                    324:                   rte->metric, ntohs (rte->tag));
                    325:     }
                    326: }
                    327: 
                    328: /* RIPng next hop address RTE (Route Table Entry). */
                    329: static void
                    330: ripng_nexthop_rte (struct rte *rte,
                    331:                   struct sockaddr_in6 *from,
                    332:                   struct ripng_nexthop *nexthop)
                    333: {
                    334:   char buf[INET6_BUFSIZ];
                    335: 
                    336:   /* Logging before checking RTE. */
                    337:   if (IS_RIPNG_DEBUG_RECV)
                    338:     zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d",
                    339:               inet6_ntoa (rte->addr), ntohs (rte->tag), rte->prefixlen);
                    340: 
                    341:   /* RFC2080 2.1.1 Next Hop: 
                    342:    The route tag and prefix length in the next hop RTE must be
                    343:    set to zero on sending and ignored on receiption.  */
                    344:   if (ntohs (rte->tag) != 0)
                    345:     zlog_warn ("RIPng nexthop RTE with non zero tag value %d from %s",
                    346:               ntohs (rte->tag), inet6_ntoa (from->sin6_addr));
                    347: 
                    348:   if (rte->prefixlen != 0)
                    349:     zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
                    350:               rte->prefixlen, inet6_ntoa (from->sin6_addr));
                    351: 
                    352:   /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
                    353:    next hop RTE indicates that the next hop address should be the
                    354:    originator of the RIPng advertisement.  An address specified as a
                    355:    next hop must be a link-local address.  */
                    356:   if (IN6_IS_ADDR_UNSPECIFIED (&rte->addr))
                    357:     {
                    358:       nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
                    359:       memset (&nexthop->address, 0, sizeof (struct in6_addr));
                    360:       return;
                    361:     }
                    362: 
                    363:   if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
                    364:     {
                    365:       nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
                    366:       IPV6_ADDR_COPY (&nexthop->address, &rte->addr);
                    367:       return;
                    368:     }
                    369: 
                    370:   /* The purpose of the next hop RTE is to eliminate packets being
                    371:    routed through extra hops in the system.  It is particularly useful
                    372:    when RIPng is not being run on all of the routers on a network.
                    373:    Note that next hop RTE is "advisory".  That is, if the provided
                    374:    information is ignored, a possibly sub-optimal, but absolutely
                    375:    valid, route may be taken.  If the received next hop address is not
                    376:    a link-local address, it should be treated as 0:0:0:0:0:0:0:0.  */
                    377:   zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s",
                    378:             inet6_ntoa (rte->addr),
                    379:             inet_ntop (AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ));
                    380: 
                    381:   nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
                    382:   memset (&nexthop->address, 0, sizeof (struct in6_addr));
                    383: 
                    384:   return;
                    385: }
                    386: 
                    387: /* If ifp has same link-local address then return 1. */
                    388: static int
                    389: ripng_lladdr_check (struct interface *ifp, struct in6_addr *addr)
                    390: {
                    391:   struct listnode *node;
                    392:   struct connected *connected;
                    393:   struct prefix *p;
                    394: 
                    395:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
                    396:     {
                    397:       p = connected->address;
                    398: 
                    399:       if (p->family == AF_INET6 &&
                    400:           IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6) &&
                    401:           IN6_ARE_ADDR_EQUAL (&p->u.prefix6, addr))
                    402:         return 1;
                    403:     }
                    404:   return 0;
                    405: }
                    406: 
                    407: /* RIPng route garbage collect timer. */
                    408: static int
                    409: ripng_garbage_collect (struct thread *t)
                    410: {
                    411:   struct ripng_info *rinfo;
                    412:   struct route_node *rp;
                    413: 
                    414:   rinfo = THREAD_ARG (t);
                    415:   rinfo->t_garbage_collect = NULL;
                    416: 
                    417:   /* Off timeout timer. */
                    418:   RIPNG_TIMER_OFF (rinfo->t_timeout);
                    419:   
                    420:   /* Get route_node pointer. */
                    421:   rp = rinfo->rp;
                    422: 
                    423:   /* Unlock route_node. */
                    424:   rp->info = NULL;
                    425:   route_unlock_node (rp);
                    426: 
                    427:   /* Free RIPng routing information. */
                    428:   ripng_info_free (rinfo);
                    429: 
                    430:   return 0;
                    431: }
                    432: 
                    433: /* Timeout RIPng routes. */
                    434: static int
                    435: ripng_timeout (struct thread *t)
                    436: {
                    437:   struct ripng_info *rinfo;
                    438:   struct route_node *rp;
                    439: 
                    440:   rinfo = THREAD_ARG (t);
                    441:   rinfo->t_timeout = NULL;
                    442: 
                    443:   /* Get route_node pointer. */
                    444:   rp = rinfo->rp;
                    445: 
                    446:   /* - The garbage-collection timer is set for 120 seconds. */
                    447:   RIPNG_TIMER_ON (rinfo->t_garbage_collect, ripng_garbage_collect, 
                    448:                  ripng->garbage_time);
                    449: 
                    450:   /* Delete this route from the kernel. */
                    451:   ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
                    452:                                rinfo->ifindex);
                    453:   /* - The metric for the route is set to 16 (infinity).  This causes
                    454:      the route to be removed from service. */
                    455:   rinfo->metric = RIPNG_METRIC_INFINITY;
                    456:   rinfo->flags &= ~RIPNG_RTF_FIB;
                    457: 
                    458:   /* Aggregate count decrement. */
                    459:   ripng_aggregate_decrement (rp, rinfo);
                    460: 
                    461:   /* - The route change flag is to indicate that this entry has been
                    462:      changed. */
                    463:   rinfo->flags |= RIPNG_RTF_CHANGED;
                    464: 
                    465:   /* - The output process is signalled to trigger a response. */
                    466:   ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
                    467: 
                    468:   return 0;
                    469: }
                    470: 
                    471: static void
                    472: ripng_timeout_update (struct ripng_info *rinfo)
                    473: {
                    474:   if (rinfo->metric != RIPNG_METRIC_INFINITY)
                    475:     {
                    476:       RIPNG_TIMER_OFF (rinfo->t_timeout);
                    477:       RIPNG_TIMER_ON (rinfo->t_timeout, ripng_timeout, ripng->timeout_time);
                    478:     }
                    479: }
                    480: 
                    481: static int
                    482: ripng_incoming_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
                    483: {
                    484:   struct distribute *dist;
                    485:   struct access_list *alist;
                    486:   struct prefix_list *plist;
                    487: 
                    488:   /* Input distribute-list filtering. */
                    489:   if (ri->list[RIPNG_FILTER_IN])
                    490:     {
                    491:       if (access_list_apply (ri->list[RIPNG_FILTER_IN], 
                    492:                             (struct prefix *) p) == FILTER_DENY)
                    493:        {
                    494:          if (IS_RIPNG_DEBUG_PACKET)
                    495:            zlog_debug ("%s/%d filtered by distribute in",
                    496:                       inet6_ntoa (p->prefix), p->prefixlen);
                    497:          return -1;
                    498:        }
                    499:     }
                    500:   if (ri->prefix[RIPNG_FILTER_IN])
                    501:     {
                    502:       if (prefix_list_apply (ri->prefix[RIPNG_FILTER_IN], 
                    503:                             (struct prefix *) p) == PREFIX_DENY)
                    504:        {
                    505:          if (IS_RIPNG_DEBUG_PACKET)
                    506:            zlog_debug ("%s/%d filtered by prefix-list in",
                    507:                       inet6_ntoa (p->prefix), p->prefixlen);
                    508:          return -1;
                    509:        }
                    510:     }
                    511: 
                    512:   /* All interface filter check. */
                    513:   dist = distribute_lookup (NULL);
                    514:   if (dist)
                    515:     {
                    516:       if (dist->list[DISTRIBUTE_IN])
                    517:        {
                    518:          alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
                    519:            
                    520:          if (alist)
                    521:            {
                    522:              if (access_list_apply (alist,
                    523:                                     (struct prefix *) p) == FILTER_DENY)
                    524:                {
                    525:                  if (IS_RIPNG_DEBUG_PACKET)
                    526:                    zlog_debug ("%s/%d filtered by distribute in",
                    527:                               inet6_ntoa (p->prefix), p->prefixlen);
                    528:                  return -1;
                    529:                }
                    530:            }
                    531:        }
                    532:       if (dist->prefix[DISTRIBUTE_IN])
                    533:        {
                    534:          plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
                    535:          
                    536:          if (plist)
                    537:            {
                    538:              if (prefix_list_apply (plist,
                    539:                                     (struct prefix *) p) == PREFIX_DENY)
                    540:                {
                    541:                  if (IS_RIPNG_DEBUG_PACKET)
                    542:                    zlog_debug ("%s/%d filtered by prefix-list in",
                    543:                               inet6_ntoa (p->prefix), p->prefixlen);
                    544:                  return -1;
                    545:                }
                    546:            }
                    547:        }
                    548:     }
                    549:   return 0;
                    550: }
                    551: 
                    552: static int
                    553: ripng_outgoing_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
                    554: {
                    555:   struct distribute *dist;
                    556:   struct access_list *alist;
                    557:   struct prefix_list *plist;
                    558: 
                    559:   if (ri->list[RIPNG_FILTER_OUT])
                    560:     {
                    561:       if (access_list_apply (ri->list[RIPNG_FILTER_OUT],
                    562:                             (struct prefix *) p) == FILTER_DENY)
                    563:        {
                    564:          if (IS_RIPNG_DEBUG_PACKET)
                    565:            zlog_debug ("%s/%d is filtered by distribute out",
                    566:                       inet6_ntoa (p->prefix), p->prefixlen);
                    567:          return -1;
                    568:        }
                    569:     }
                    570:   if (ri->prefix[RIPNG_FILTER_OUT])
                    571:     {
                    572:       if (prefix_list_apply (ri->prefix[RIPNG_FILTER_OUT],
                    573:                             (struct prefix *) p) == PREFIX_DENY)
                    574:        {
                    575:          if (IS_RIPNG_DEBUG_PACKET)
                    576:            zlog_debug ("%s/%d is filtered by prefix-list out",
                    577:                       inet6_ntoa (p->prefix), p->prefixlen);
                    578:          return -1;
                    579:        }
                    580:     }
                    581: 
                    582:   /* All interface filter check. */
                    583:   dist = distribute_lookup (NULL);
                    584:   if (dist)
                    585:     {
                    586:       if (dist->list[DISTRIBUTE_OUT])
                    587:        {
                    588:          alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
                    589:            
                    590:          if (alist)
                    591:            {
                    592:              if (access_list_apply (alist,
                    593:                                     (struct prefix *) p) == FILTER_DENY)
                    594:                {
                    595:                  if (IS_RIPNG_DEBUG_PACKET)
                    596:                    zlog_debug ("%s/%d filtered by distribute out",
                    597:                               inet6_ntoa (p->prefix), p->prefixlen);
                    598:                  return -1;
                    599:                }
                    600:            }
                    601:        }
                    602:       if (dist->prefix[DISTRIBUTE_OUT])
                    603:        {
                    604:          plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
                    605:          
                    606:          if (plist)
                    607:            {
                    608:              if (prefix_list_apply (plist,
                    609:                                     (struct prefix *) p) == PREFIX_DENY)
                    610:                {
                    611:                  if (IS_RIPNG_DEBUG_PACKET)
                    612:                    zlog_debug ("%s/%d filtered by prefix-list out",
                    613:                               inet6_ntoa (p->prefix), p->prefixlen);
                    614:                  return -1;
                    615:                }
                    616:            }
                    617:        }
                    618:     }
                    619:   return 0;
                    620: }
                    621: 
                    622: /* Process RIPng route according to RFC2080. */
                    623: static void
                    624: ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
                    625:                     struct ripng_nexthop *ripng_nexthop,
                    626:                     struct interface *ifp)
                    627: {
                    628:   int ret;
                    629:   struct prefix_ipv6 p;
                    630:   struct route_node *rp;
                    631:   struct ripng_info *rinfo;
                    632:   struct ripng_interface *ri;
                    633:   struct in6_addr *nexthop;
                    634:   u_char oldmetric;
                    635:   int same = 0;
                    636: 
                    637:   /* Make prefix structure. */
                    638:   memset (&p, 0, sizeof (struct prefix_ipv6));
                    639:   p.family = AF_INET6;
                    640:   /* p.prefix = rte->addr; */
                    641:   IPV6_ADDR_COPY (&p.prefix, &rte->addr);
                    642:   p.prefixlen = rte->prefixlen;
                    643: 
                    644:   /* Make sure mask is applied. */
                    645:   /* XXX We have to check the prefix is valid or not before call
                    646:      apply_mask_ipv6. */
                    647:   apply_mask_ipv6 (&p);
                    648: 
                    649:   /* Apply input filters. */
                    650:   ri = ifp->info;
                    651: 
                    652:   ret = ripng_incoming_filter (&p, ri);
                    653:   if (ret < 0)
                    654:     return;
                    655: 
                    656:   /* Modify entry. */
                    657:   if (ri->routemap[RIPNG_FILTER_IN])
                    658:     {
                    659:       int ret;
                    660:       struct ripng_info newinfo;
                    661: 
                    662:       memset (&newinfo, 0, sizeof (struct ripng_info));
                    663:       newinfo.type = ZEBRA_ROUTE_RIPNG;
                    664:       newinfo.sub_type = RIPNG_ROUTE_RTE;
                    665:       if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
                    666:         newinfo.nexthop = ripng_nexthop->address;
                    667:       else
                    668:         newinfo.nexthop = from->sin6_addr;
                    669:       newinfo.from   = from->sin6_addr;
                    670:       newinfo.ifindex = ifp->ifindex;
                    671:       newinfo.metric = rte->metric;
                    672:       newinfo.metric_out = rte->metric; /* XXX */
                    673:       newinfo.tag    = ntohs(rte->tag); /* XXX */
                    674: 
                    675:       ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN], 
                    676:                             (struct prefix *)&p, RMAP_RIPNG, &newinfo);
                    677: 
                    678:       if (ret == RMAP_DENYMATCH)
                    679:        {
                    680:          if (IS_RIPNG_DEBUG_PACKET)
                    681:            zlog_debug ("RIPng %s/%d is filtered by route-map in",
                    682:                       inet6_ntoa (p.prefix), p.prefixlen);
                    683:          return;
                    684:        }
                    685: 
                    686:       /* Get back the object */
                    687:       if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) {
                    688:        if (! IPV6_ADDR_SAME(&newinfo.nexthop, &ripng_nexthop->address) ) {
                    689:          /* the nexthop get changed by the routemap */
                    690:          if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop))
                    691:            ripng_nexthop->address = newinfo.nexthop;
                    692:          else
                    693:            ripng_nexthop->address = in6addr_any;
                    694:        }
                    695:       } else {
                    696:        if (! IPV6_ADDR_SAME(&newinfo.nexthop, &from->sin6_addr) ) {
                    697:          /* the nexthop get changed by the routemap */
                    698:          if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) {
                    699:            ripng_nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
                    700:            ripng_nexthop->address = newinfo.nexthop;
                    701:          }
                    702:        }
                    703:       }
                    704:       rte->tag     = htons(newinfo.tag_out); /* XXX */
                    705:       rte->metric  = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
                    706:     }
                    707: 
                    708:   /* Once the entry has been validated, update the metric by
                    709:    * adding the cost of the network on wich the message
                    710:    * arrived. If the result is greater than infinity, use infinity
                    711:    * (RFC2453 Sec. 3.9.2)
                    712:    **/
                    713:  
                    714:   /* Zebra ripngd can handle offset-list in. */
                    715:   ret = ripng_offset_list_apply_in (&p, ifp, &rte->metric);
                    716: 
                    717:   /* If offset-list does not modify the metric use interface's
                    718:    * one. */
                    719:   if (! ret)
                    720:     rte->metric += ifp->metric;
                    721: 
                    722:   if (rte->metric > RIPNG_METRIC_INFINITY)
                    723:     rte->metric = RIPNG_METRIC_INFINITY;
                    724: 
                    725:   /* Set nexthop pointer. */
                    726:   if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
                    727:     nexthop = &ripng_nexthop->address;
                    728:   else
                    729:     nexthop = &from->sin6_addr;
                    730: 
                    731:   /* Lookup RIPng routing table. */
                    732:   rp = route_node_get (ripng->table, (struct prefix *) &p);
                    733: 
                    734:   /* Sanity check */
                    735:   rinfo = rp->info;
                    736:   if (rinfo)
                    737:     {
                    738:       /* Redistributed route check. */
                    739:       if (rinfo->type != ZEBRA_ROUTE_RIPNG
                    740:          && rinfo->metric != RIPNG_METRIC_INFINITY)
                    741:        return;
                    742: 
                    743:       /* Local static route. */
                    744:       if (rinfo->type == ZEBRA_ROUTE_RIPNG
                    745:          && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
                    746:              (rinfo->sub_type == RIPNG_ROUTE_DEFAULT))
                    747:          && rinfo->metric != RIPNG_METRIC_INFINITY)
                    748:        return;
                    749:     }
                    750: 
                    751:   if (rp->info == NULL)
                    752:     {
                    753:       /* Now, check to see whether there is already an explicit route
                    754:         for the destination prefix.  If there is no such route, add
                    755:         this route to the routing table, unless the metric is
                    756:         infinity (there is no point in adding a route which
                    757:         unusable). */
                    758:       if (rte->metric != RIPNG_METRIC_INFINITY)
                    759:        {
                    760:          rinfo = ripng_info_new ();
                    761:          
                    762:          /* - Setting the destination prefix and length to those in
                    763:             the RTE. */
                    764:          rp->info = rinfo;
                    765:          rinfo->rp = rp;
                    766: 
                    767:          /* - Setting the metric to the newly calculated metric (as
                    768:             described above). */
                    769:          rinfo->metric = rte->metric;
                    770:          rinfo->tag = ntohs (rte->tag);
                    771: 
                    772:          /* - Set the next hop address to be the address of the router
                    773:             from which the datagram came or the next hop address
                    774:             specified by a next hop RTE. */
                    775:          IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
                    776:          IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
                    777:          rinfo->ifindex = ifp->ifindex;
                    778: 
                    779:          /* - Initialize the timeout for the route.  If the
                    780:             garbage-collection timer is running for this route, stop it. */
                    781:          ripng_timeout_update (rinfo);
                    782: 
                    783:          /* - Set the route change flag. */
                    784:          rinfo->flags |= RIPNG_RTF_CHANGED;
                    785: 
                    786:          /* - Signal the output process to trigger an update (see section
                    787:             2.5). */
                    788:          ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
                    789: 
                    790:          /* Finally, route goes into the kernel. */
                    791:          rinfo->type = ZEBRA_ROUTE_RIPNG;
                    792:          rinfo->sub_type = RIPNG_ROUTE_RTE;
                    793: 
                    794:          ripng_zebra_ipv6_add (&p, &rinfo->nexthop, rinfo->ifindex,
                    795:                                rinfo->metric);
                    796:          rinfo->flags |= RIPNG_RTF_FIB;
                    797: 
                    798:          /* Aggregate check. */
                    799:          ripng_aggregate_increment (rp, rinfo);
                    800:        }
                    801:     }
                    802:   else
                    803:     {
                    804:       rinfo = rp->info;
                    805:          
                    806:       /* If there is an existing route, compare the next hop address
                    807:         to the address of the router from which the datagram came.
                    808:         If this datagram is from the same router as the existing
                    809:         route, reinitialize the timeout.  */
                    810:       same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) 
                    811:              && (rinfo->ifindex == ifp->ifindex));
                    812: 
                    813:       if (same)
                    814:        ripng_timeout_update (rinfo);
                    815: 
                    816:       /* Next, compare the metrics.  If the datagram is from the same
                    817:         router as the existing route, and the new metric is different
                    818:         than the old one; or, if the new metric is lower than the old
                    819:         one; do the following actions: */
                    820:       if ((same && rinfo->metric != rte->metric) ||
                    821:          rte->metric < rinfo->metric)
                    822:        {
                    823:          /* - Adopt the route from the datagram.  That is, put the
                    824:             new metric in, and adjust the next hop address (if
                    825:             necessary). */
                    826:          oldmetric = rinfo->metric;
                    827:          rinfo->metric = rte->metric;
                    828:          rinfo->tag = ntohs (rte->tag);
                    829:          IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
                    830:          rinfo->ifindex = ifp->ifindex;
                    831: 
                    832:          /* Should a new route to this network be established
                    833:             while the garbage-collection timer is running, the
                    834:             new route will replace the one that is about to be
                    835:             deleted.  In this case the garbage-collection timer
                    836:             must be cleared. */
                    837: 
                    838:          if (oldmetric == RIPNG_METRIC_INFINITY &&
                    839:              rinfo->metric < RIPNG_METRIC_INFINITY)
                    840:            {
                    841:              rinfo->type = ZEBRA_ROUTE_RIPNG;
                    842:              rinfo->sub_type = RIPNG_ROUTE_RTE;
                    843: 
                    844:              RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
                    845: 
                    846:              if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
                    847:                IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
                    848: 
                    849:              ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex, rinfo->metric);
                    850:              rinfo->flags |= RIPNG_RTF_FIB;
                    851: 
                    852:              /* The aggregation counter needs to be updated because
                    853:                     the prefixes, which are into the gc, have been
                    854:                         removed from the aggregator (see ripng_timout). */
                    855:                  ripng_aggregate_increment (rp, rinfo);
                    856:            }
                    857: 
                    858:          /* Update nexthop and/or metric value.  */
                    859:          if (oldmetric != RIPNG_METRIC_INFINITY)
                    860:            {
                    861:              ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
                    862:              ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex, rinfo->metric);
                    863:              rinfo->flags |= RIPNG_RTF_FIB;
                    864: 
                    865:              if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
                    866:                IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
                    867:            }
                    868: 
                    869:          /* - Set the route change flag and signal the output process
                    870:             to trigger an update. */
                    871:          rinfo->flags |= RIPNG_RTF_CHANGED;
                    872:          ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
                    873: 
                    874:          /* - If the new metric is infinity, start the deletion
                    875:             process (described above); */
                    876:          if (rinfo->metric == RIPNG_METRIC_INFINITY)
                    877:            {
                    878:              /* If the new metric is infinity, the deletion process
                    879:                 begins for the route, which is no longer used for
                    880:                 routing packets.  Note that the deletion process is
                    881:                 started only when the metric is first set to
                    882:                 infinity.  If the metric was already infinity, then a
                    883:                 new deletion process is not started. */
                    884:              if (oldmetric != RIPNG_METRIC_INFINITY)
                    885:                {
                    886:                  /* - The garbage-collection timer is set for 120 seconds. */
                    887:                  RIPNG_TIMER_ON (rinfo->t_garbage_collect, 
                    888:                                  ripng_garbage_collect, ripng->garbage_time);
                    889:                  RIPNG_TIMER_OFF (rinfo->t_timeout);
                    890: 
                    891:                  /* - The metric for the route is set to 16
                    892:                     (infinity).  This causes the route to be removed
                    893:                     from service.*/
                    894:                  ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
                    895:                  rinfo->flags &= ~RIPNG_RTF_FIB;
                    896: 
                    897:                  /* Aggregate count decrement. */
                    898:                  ripng_aggregate_decrement (rp, rinfo);
                    899: 
                    900:                  /* - The route change flag is to indicate that this
                    901:                     entry has been changed. */
                    902:                  /* - The output process is signalled to trigger a
                    903:                      response. */
                    904:                  ;  /* Above processes are already done previously. */
                    905:                }
                    906:            }
                    907:          else
                    908:            {
                    909:              /* otherwise, re-initialize the timeout. */
                    910:              ripng_timeout_update (rinfo);
                    911:            }
                    912:        }
                    913:       /* Unlock tempolary lock of the route. */
                    914:       route_unlock_node (rp);
                    915:     }
                    916: }
                    917: 
                    918: /* Add redistributed route to RIPng table. */
                    919: void
                    920: ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, 
                    921:                        unsigned int ifindex, struct in6_addr *nexthop)
                    922: {
                    923:   struct route_node *rp;
                    924:   struct ripng_info *rinfo;
                    925: 
                    926:   /* Redistribute route  */
                    927:   if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
                    928:     return;
                    929:   if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
                    930:     return;
                    931: #if defined (MUSICA) || defined (LINUX)
                    932:   /* XXX As long as the RIPng redistribution is applied to all the connected
                    933:    *     routes, one needs to filter the ::/96 prefixes.
                    934:    *     However it could be a wanted case, it will be removed soon.
                    935:    */
                    936:   if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
                    937:       (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
                    938:     return;
                    939: #endif /* MUSICA or LINUX */
                    940: 
                    941:   rp = route_node_get (ripng->table, (struct prefix *) p);
                    942:   rinfo = rp->info;
                    943: 
                    944:   if (rinfo)
                    945:     {
                    946:       if (rinfo->type == ZEBRA_ROUTE_CONNECT
                    947:           && rinfo->sub_type == RIPNG_ROUTE_INTERFACE
                    948:          && rinfo->metric != RIPNG_METRIC_INFINITY) {
                    949:         route_unlock_node (rp);
                    950:           return;
                    951:       }
                    952: 
                    953:       /* Manually configured RIPng route check.
                    954:        * They have the precedence on all the other entries.
                    955:        **/
                    956:       if (rinfo->type == ZEBRA_ROUTE_RIPNG
                    957:           && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
                    958:               (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) ) {
                    959:         if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) &&
                    960:                                           (sub_type != RIPNG_ROUTE_DEFAULT))) {
                    961:          route_unlock_node (rp);
                    962:          return;
                    963:        }
                    964:       }
                    965:       
                    966:       RIPNG_TIMER_OFF (rinfo->t_timeout);
                    967:       RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
                    968: 
                    969:       /* Tells the other daemons about the deletion of
                    970:        * this RIPng route
                    971:        **/
                    972:       if (ripng_route_rte (rinfo))
                    973:        ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
                    974:                               rinfo->metric);
                    975: 
                    976:       rp->info = NULL;
                    977:       ripng_info_free (rinfo);
                    978: 
                    979:       route_unlock_node (rp);
                    980: 
                    981:     }
                    982: 
                    983:   rinfo = ripng_info_new ();
                    984: 
                    985:   rinfo->type = type;
                    986:   rinfo->sub_type = sub_type;
                    987:   rinfo->ifindex = ifindex;
                    988:   rinfo->metric = 1;
                    989:   rinfo->rp = rp;
                    990:   
                    991:   if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop))
                    992:     rinfo->nexthop = *nexthop;
                    993:   
                    994:   rinfo->flags |= RIPNG_RTF_FIB;
                    995:   rp->info = rinfo;
                    996: 
                    997:   /* Aggregate check. */
                    998:   ripng_aggregate_increment (rp, rinfo);
                    999: 
                   1000:   rinfo->flags |= RIPNG_RTF_CHANGED;
                   1001: 
                   1002:   if (IS_RIPNG_DEBUG_EVENT) {
                   1003:     if (!nexthop)
                   1004:       zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
                   1005:                  inet6_ntoa(p->prefix), p->prefixlen,
                   1006:                  ifindex2ifname(ifindex));
                   1007:     else
                   1008:       zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
                   1009:                  inet6_ntoa(p->prefix), p->prefixlen, inet6_ntoa(*nexthop),
                   1010:                  ifindex2ifname(ifindex));
                   1011:   }
                   1012: 
                   1013:   ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
                   1014: }
                   1015: 
                   1016: /* Delete redistributed route to RIPng table. */
                   1017: void
                   1018: ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, 
                   1019:                           unsigned int ifindex)
                   1020: {
                   1021:   struct route_node *rp;
                   1022:   struct ripng_info *rinfo;
                   1023: 
                   1024:   if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
                   1025:     return;
                   1026:   if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
                   1027:     return;
                   1028: #if defined (MUSICA) || defined (LINUX)
                   1029:   /* XXX As long as the RIPng redistribution is applied to all the connected
                   1030:    *     routes, one needs to filter the ::/96 prefixes.
                   1031:    *     However it could be a wanted case, it will be removed soon.
                   1032:    */
                   1033:   if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
                   1034:       (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
                   1035:     return;
                   1036: #endif /* MUSICA or LINUX */
                   1037: 
                   1038:   rp = route_node_lookup (ripng->table, (struct prefix *) p);
                   1039: 
                   1040:   if (rp)
                   1041:     {
                   1042:       rinfo = rp->info;
                   1043: 
                   1044:       if (rinfo != NULL
                   1045:          && rinfo->type == type 
                   1046:          && rinfo->sub_type == sub_type 
                   1047:          && rinfo->ifindex == ifindex)
                   1048:        {
                   1049:          /* Perform poisoned reverse. */
                   1050:          rinfo->metric = RIPNG_METRIC_INFINITY;
                   1051:          RIPNG_TIMER_ON (rinfo->t_garbage_collect, 
                   1052:                        ripng_garbage_collect, ripng->garbage_time);
                   1053:          RIPNG_TIMER_OFF (rinfo->t_timeout);
                   1054: 
                   1055:          /* Aggregate count decrement. */
                   1056:          ripng_aggregate_decrement (rp, rinfo);
                   1057: 
                   1058:          rinfo->flags |= RIPNG_RTF_CHANGED;
                   1059:          
                   1060:           if (IS_RIPNG_DEBUG_EVENT)
                   1061:             zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
                   1062:                        inet6_ntoa(p->prefix), p->prefixlen,
                   1063:                        ifindex2ifname(ifindex));
                   1064: 
                   1065:          ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
                   1066:        }
                   1067:     }
                   1068: }
                   1069: 
                   1070: /* Withdraw redistributed route. */
                   1071: void
                   1072: ripng_redistribute_withdraw (int type)
                   1073: {
                   1074:   struct route_node *rp;
                   1075:   struct ripng_info *rinfo;
                   1076: 
                   1077:   if (!ripng)
                   1078:     return;
                   1079:   
                   1080:   for (rp = route_top (ripng->table); rp; rp = route_next (rp))
                   1081:     if ((rinfo = rp->info) != NULL)
                   1082:       {
                   1083:        if ((rinfo->type == type)
                   1084:            && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE))
                   1085:          {
                   1086:            /* Perform poisoned reverse. */
                   1087:            rinfo->metric = RIPNG_METRIC_INFINITY;
                   1088:            RIPNG_TIMER_ON (rinfo->t_garbage_collect, 
                   1089:                          ripng_garbage_collect, ripng->garbage_time);
                   1090:            RIPNG_TIMER_OFF (rinfo->t_timeout);
                   1091: 
                   1092:            /* Aggregate count decrement. */
                   1093:            ripng_aggregate_decrement (rp, rinfo);
                   1094: 
                   1095:            rinfo->flags |= RIPNG_RTF_CHANGED;
                   1096: 
                   1097:            if (IS_RIPNG_DEBUG_EVENT) {
                   1098:              struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p;
                   1099: 
                   1100:              zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
                   1101:                         inet6_ntoa(p->prefix), p->prefixlen,
                   1102:                         ifindex2ifname(rinfo->ifindex));
                   1103:            }
                   1104: 
                   1105:            ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
                   1106:          }
                   1107:       }
                   1108: }
                   1109: 
                   1110: /* RIP routing information. */
                   1111: static void
                   1112: ripng_response_process (struct ripng_packet *packet, int size, 
                   1113:                        struct sockaddr_in6 *from, struct interface *ifp,
                   1114:                        int hoplimit)
                   1115: {
                   1116:   caddr_t lim;
                   1117:   struct rte *rte;
                   1118:   struct ripng_nexthop nexthop;
                   1119: 
                   1120:   /* RFC2080 2.4.2  Response Messages:
                   1121:    The Response must be ignored if it is not from the RIPng port.  */
                   1122:   if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT)
                   1123:     {
                   1124:       zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
                   1125:                 ntohs (from->sin6_port), inet6_ntoa (from->sin6_addr));
                   1126:       ripng_peer_bad_packet (from);
                   1127:       return;
                   1128:     }
                   1129: 
                   1130:   /* The datagram's IPv6 source address should be checked to see
                   1131:    whether the datagram is from a valid neighbor; the source of the
                   1132:    datagram must be a link-local address.  */
                   1133:   if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr))
                   1134:    {
                   1135:       zlog_warn ("RIPng packet comes from non link local address %s",
                   1136:                 inet6_ntoa (from->sin6_addr));
                   1137:       ripng_peer_bad_packet (from);
                   1138:       return;
                   1139:     }
                   1140: 
                   1141:   /* It is also worth checking to see whether the response is from one
                   1142:    of the router's own addresses.  Interfaces on broadcast networks
                   1143:    may receive copies of their own multicasts immediately.  If a
                   1144:    router processes its own output as new input, confusion is likely,
                   1145:    and such datagrams must be ignored. */
                   1146:   if (ripng_lladdr_check (ifp, &from->sin6_addr))
                   1147:     {
                   1148:       zlog_warn ("RIPng packet comes from my own link local address %s",
                   1149:                 inet6_ntoa (from->sin6_addr));
                   1150:       ripng_peer_bad_packet (from);
                   1151:       return;
                   1152:     }
                   1153: 
                   1154:   /* As an additional check, periodic advertisements must have their
                   1155:    hop counts set to 255, and inbound, multicast packets sent from the
                   1156:    RIPng port (i.e. periodic advertisement or triggered update
                   1157:    packets) must be examined to ensure that the hop count is 255. */
                   1158:   if (hoplimit >= 0 && hoplimit != 255)
                   1159:     {
                   1160:       zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
                   1161:                 hoplimit, inet6_ntoa (from->sin6_addr));
                   1162:       ripng_peer_bad_packet (from);
                   1163:       return;
                   1164:     }
                   1165: 
                   1166:   /* Update RIPng peer. */
                   1167:   ripng_peer_update (from, packet->version);
                   1168:   
                   1169:   /* Reset nexthop. */
                   1170:   memset (&nexthop, 0, sizeof (struct ripng_nexthop));
                   1171:   nexthop.flag = RIPNG_NEXTHOP_UNSPEC;
                   1172: 
                   1173:   /* Set RTE pointer. */
                   1174:   rte = packet->rte;
                   1175: 
                   1176:   for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++) 
                   1177:     {
                   1178:       /* First of all, we have to check this RTE is next hop RTE or
                   1179:          not.  Next hop RTE is completely different with normal RTE so
                   1180:          we need special treatment. */
                   1181:       if (rte->metric == RIPNG_METRIC_NEXTHOP)
                   1182:        {
                   1183:          ripng_nexthop_rte (rte, from, &nexthop);
                   1184:          continue;
                   1185:        }
                   1186: 
                   1187:       /* RTE information validation. */
                   1188: 
                   1189:       /* - is the destination prefix valid (e.g., not a multicast
                   1190:          prefix and not a link-local address) A link-local address
                   1191:          should never be present in an RTE. */
                   1192:       if (IN6_IS_ADDR_MULTICAST (&rte->addr))
                   1193:        {
                   1194:          zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
                   1195:                     inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
                   1196:          ripng_peer_bad_route (from);
                   1197:          continue;
                   1198:        }
                   1199:       if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
                   1200:        {
                   1201:          zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
                   1202:                     inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
                   1203:          ripng_peer_bad_route (from);
                   1204:          continue;
                   1205:        }
                   1206:       if (IN6_IS_ADDR_LOOPBACK (&rte->addr))
                   1207:        {
                   1208:          zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
                   1209:                     inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
                   1210:          ripng_peer_bad_route (from);
                   1211:          continue;
                   1212:        }
                   1213: 
                   1214:       /* - is the prefix length valid (i.e., between 0 and 128,
                   1215:          inclusive) */
                   1216:       if (rte->prefixlen > 128)
                   1217:        {
                   1218:          zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
                   1219:                     inet6_ntoa (rte->addr), rte->prefixlen,
                   1220:                     inet6_ntoa (from->sin6_addr), ifp->name);
                   1221:          ripng_peer_bad_route (from);
                   1222:          continue;
                   1223:        }
                   1224: 
                   1225:       /* - is the metric valid (i.e., between 1 and 16, inclusive) */
                   1226:       if (! (rte->metric >= 1 && rte->metric <= 16))
                   1227:        {
                   1228:          zlog_warn ("Invalid metric %d from %s%%%s", rte->metric,
                   1229:                     inet6_ntoa (from->sin6_addr), ifp->name);
                   1230:          ripng_peer_bad_route (from);
                   1231:          continue;
                   1232:        }
                   1233: 
                   1234:       /* Vincent: XXX Should we compute the direclty reachable nexthop
                   1235:        * for our RIPng network ?
                   1236:        **/
                   1237: 
                   1238:       /* Routing table updates. */
                   1239:       ripng_route_process (rte, from, &nexthop, ifp);
                   1240:     }
                   1241: }
                   1242: 
                   1243: /* Response to request message. */
                   1244: static void
                   1245: ripng_request_process (struct ripng_packet *packet,int size, 
                   1246:                       struct sockaddr_in6 *from, struct interface *ifp)
                   1247: {
                   1248:   caddr_t lim;
                   1249:   struct rte *rte;
                   1250:   struct prefix_ipv6 p;
                   1251:   struct route_node *rp;
                   1252:   struct ripng_info *rinfo;
                   1253:   struct ripng_interface *ri;
                   1254: 
                   1255:   /* Does not reponse to the requests on the loopback interfaces */
                   1256:   if (if_is_loopback (ifp))
                   1257:     return;
                   1258: 
                   1259:   /* Check RIPng process is enabled on this interface. */
                   1260:   ri = ifp->info;
                   1261:   if (! ri->running)
                   1262:     return;
                   1263: 
                   1264:   /* When passive interface is specified, suppress responses */
                   1265:   if (ri->passive)
                   1266:     return;
                   1267: 
                   1268:   /* RIPng peer update. */
                   1269:   ripng_peer_update (from, packet->version);
                   1270: 
                   1271:   lim = ((caddr_t) packet) + size;
                   1272:   rte = packet->rte;
                   1273: 
                   1274:   /* The Request is processed entry by entry.  If there are no
                   1275:      entries, no response is given. */
                   1276:   if (lim == (caddr_t) rte)
                   1277:     return;
                   1278: 
                   1279:   /* There is one special case.  If there is exactly one entry in the
                   1280:      request, and it has a destination prefix of zero, a prefix length
                   1281:      of zero, and a metric of infinity (i.e., 16), then this is a
                   1282:      request to send the entire routing table.  In that case, a call
                   1283:      is made to the output process to send the routing table to the
                   1284:      requesting address/port. */
                   1285:   if (lim == ((caddr_t) (rte + 1)) &&
                   1286:       IN6_IS_ADDR_UNSPECIFIED (&rte->addr) &&
                   1287:       rte->prefixlen == 0 &&
                   1288:       rte->metric == RIPNG_METRIC_INFINITY)
                   1289:     {  
                   1290:       /* All route with split horizon */
                   1291:       ripng_output_process (ifp, from, ripng_all_route);
                   1292:     }
                   1293:   else
                   1294:     {
                   1295:       /* Except for this special case, processing is quite simple.
                   1296:         Examine the list of RTEs in the Request one by one.  For each
                   1297:         entry, look up the destination in the router's routing
                   1298:         database and, if there is a route, put that route's metric in
                   1299:         the metric field of the RTE.  If there is no explicit route
                   1300:         to the specified destination, put infinity in the metric
                   1301:         field.  Once all the entries have been filled in, change the
                   1302:         command from Request to Response and send the datagram back
                   1303:         to the requestor. */
                   1304:       memset (&p, 0, sizeof (struct prefix_ipv6));
                   1305:       p.family = AF_INET6;
                   1306: 
                   1307:       for (; ((caddr_t) rte) < lim; rte++)
                   1308:        {
                   1309:          p.prefix = rte->addr;
                   1310:          p.prefixlen = rte->prefixlen;
                   1311:          apply_mask_ipv6 (&p);
                   1312:          
                   1313:          rp = route_node_lookup (ripng->table, (struct prefix *) &p);
                   1314: 
                   1315:          if (rp)
                   1316:            {
                   1317:              rinfo = rp->info;
                   1318:              rte->metric = rinfo->metric;
                   1319:              route_unlock_node (rp);
                   1320:            }
                   1321:          else
                   1322:            rte->metric = RIPNG_METRIC_INFINITY;
                   1323:        }
                   1324:       packet->command = RIPNG_RESPONSE;
                   1325: 
                   1326:       ripng_send_packet ((caddr_t) packet, size, from, ifp);
                   1327:     }
                   1328: }
                   1329: 
                   1330: /* First entry point of reading RIPng packet. */
                   1331: static int
                   1332: ripng_read (struct thread *thread)
                   1333: {
                   1334:   int len;
                   1335:   int sock;
                   1336:   struct sockaddr_in6 from;
                   1337:   struct ripng_packet *packet;
                   1338:   unsigned int ifindex;
                   1339:   struct interface *ifp;
                   1340:   int hoplimit = -1;
                   1341: 
                   1342:   /* Check ripng is active and alive. */
                   1343:   assert (ripng != NULL);
                   1344:   assert (ripng->sock >= 0);
                   1345: 
                   1346:   /* Fetch thread data and set read pointer to empty for event
                   1347:      managing.  `sock' sould be same as ripng->sock. */
                   1348:   sock = THREAD_FD (thread);
                   1349:   ripng->t_read = NULL;
                   1350: 
                   1351:   /* Add myself to the next event. */
                   1352:   ripng_event (RIPNG_READ, sock);
                   1353: 
                   1354:   /* Read RIPng packet. */
                   1355:   len = ripng_recv_packet (sock, STREAM_DATA (ripng->ibuf), 
                   1356:                           STREAM_SIZE (ripng->ibuf), &from, &ifindex,
                   1357:                           &hoplimit);
                   1358:   if (len < 0) 
                   1359:     {
                   1360:       zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno));
                   1361:       return len;
                   1362:     }
                   1363: 
                   1364:   /* Check RTE boundary.  RTE size (Packet length - RIPng header size
                   1365:      (4)) must be multiple size of one RTE size (20). */
                   1366:   if (((len - 4) % 20) != 0)
                   1367:     {
                   1368:       zlog_warn ("RIPng invalid packet size %d from %s", len,
                   1369:                 inet6_ntoa (from.sin6_addr));
                   1370:       ripng_peer_bad_packet (&from);
                   1371:       return 0;
                   1372:     }
                   1373: 
                   1374:   packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf);
                   1375:   ifp = if_lookup_by_index (ifindex);
                   1376: 
                   1377:   /* RIPng packet received. */
                   1378:   if (IS_RIPNG_DEBUG_EVENT)
                   1379:     zlog_debug ("RIPng packet received from %s port %d on %s",
                   1380:               inet6_ntoa (from.sin6_addr), ntohs (from.sin6_port), 
                   1381:               ifp ? ifp->name : "unknown");
                   1382: 
                   1383:   /* Logging before packet checking. */
                   1384:   if (IS_RIPNG_DEBUG_RECV)
                   1385:     ripng_packet_dump (packet, len, "RECV");
                   1386: 
                   1387:   /* Packet comes from unknown interface. */
                   1388:   if (ifp == NULL)
                   1389:     {
                   1390:       zlog_warn ("RIPng packet comes from unknown interface %d", ifindex);
                   1391:       return 0;
                   1392:     }
                   1393: 
                   1394:   /* Packet version mismatch checking. */
                   1395:   if (packet->version != ripng->version) 
                   1396:     {
                   1397:       zlog_warn ("RIPng packet version %d doesn't fit to my version %d", 
                   1398:                 packet->version, ripng->version);
                   1399:       ripng_peer_bad_packet (&from);
                   1400:       return 0;
                   1401:     }
                   1402: 
                   1403:   /* Process RIPng packet. */
                   1404:   switch (packet->command)
                   1405:     {
                   1406:     case RIPNG_REQUEST:
                   1407:       ripng_request_process (packet, len, &from, ifp);
                   1408:       break;
                   1409:     case RIPNG_RESPONSE:
                   1410:       ripng_response_process (packet, len, &from, ifp, hoplimit);
                   1411:       break;
                   1412:     default:
                   1413:       zlog_warn ("Invalid RIPng command %d", packet->command);
                   1414:       ripng_peer_bad_packet (&from);
                   1415:       break;
                   1416:     }
                   1417:   return 0;
                   1418: }
                   1419: 
                   1420: /* Walk down the RIPng routing table then clear changed flag. */
                   1421: static void
                   1422: ripng_clear_changed_flag (void)
                   1423: {
                   1424:   struct route_node *rp;
                   1425:   struct ripng_info *rinfo;
                   1426: 
                   1427:   for (rp = route_top (ripng->table); rp; rp = route_next (rp))
                   1428:     if ((rinfo = rp->info) != NULL)
                   1429:       if (rinfo->flags & RIPNG_RTF_CHANGED)
                   1430:        rinfo->flags &= ~RIPNG_RTF_CHANGED;
                   1431: }
                   1432: 
                   1433: /* Regular update of RIPng route.  Send all routing formation to RIPng
                   1434:    enabled interface. */
                   1435: static int
                   1436: ripng_update (struct thread *t)
                   1437: {
                   1438:   struct listnode *node;
                   1439:   struct interface *ifp;
                   1440:   struct ripng_interface *ri;
                   1441: 
                   1442:   /* Clear update timer thread. */
                   1443:   ripng->t_update = NULL;
                   1444: 
                   1445:   /* Logging update event. */
                   1446:   if (IS_RIPNG_DEBUG_EVENT)
                   1447:     zlog_debug ("RIPng update timer expired!");
                   1448: 
                   1449:   /* Supply routes to each interface. */
                   1450:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                   1451:     {
                   1452:       ri = ifp->info;
                   1453: 
                   1454:       if (if_is_loopback (ifp) || ! if_is_up (ifp))
                   1455:        continue;
                   1456: 
                   1457:       if (! ri->running)
                   1458:        continue;
                   1459: 
                   1460:       /* When passive interface is specified, suppress announce to the
                   1461:          interface. */
                   1462:       if (ri->passive)
                   1463:        continue;
                   1464: 
                   1465: #if RIPNG_ADVANCED
                   1466:       if (ri->ri_send == RIPNG_SEND_OFF)
                   1467:        {
                   1468:          if (IS_RIPNG_DEBUG_EVENT)
                   1469:            zlog (NULL, LOG_DEBUG, 
                   1470:                  "[Event] RIPng send to if %d is suppressed by config",
                   1471:                 ifp->ifindex);
                   1472:          continue;
                   1473:        }
                   1474: #endif /* RIPNG_ADVANCED */
                   1475: 
                   1476:       ripng_output_process (ifp, NULL, ripng_all_route);
                   1477:     }
                   1478: 
                   1479:   /* Triggered updates may be suppressed if a regular update is due by
                   1480:      the time the triggered update would be sent. */
                   1481:   if (ripng->t_triggered_interval)
                   1482:     {
                   1483:       thread_cancel (ripng->t_triggered_interval);
                   1484:       ripng->t_triggered_interval = NULL;
                   1485:     }
                   1486:   ripng->trigger = 0;
                   1487: 
                   1488:   /* Reset flush event. */
                   1489:   ripng_event (RIPNG_UPDATE_EVENT, 0);
                   1490: 
                   1491:   return 0;
                   1492: }
                   1493: 
                   1494: /* Triggered update interval timer. */
                   1495: static int
                   1496: ripng_triggered_interval (struct thread *t)
                   1497: {
                   1498:   ripng->t_triggered_interval = NULL;
                   1499: 
                   1500:   if (ripng->trigger)
                   1501:     {
                   1502:       ripng->trigger = 0;
                   1503:       ripng_triggered_update (t);
                   1504:     }
                   1505:   return 0;
                   1506: }     
                   1507: 
                   1508: /* Execute triggered update. */
                   1509: int
                   1510: ripng_triggered_update (struct thread *t)
                   1511: {
                   1512:   struct listnode *node;
                   1513:   struct interface *ifp;
                   1514:   struct ripng_interface *ri;
                   1515:   int interval;
                   1516: 
                   1517:   ripng->t_triggered_update = NULL;
                   1518: 
                   1519:   /* Cancel interval timer. */
                   1520:   if (ripng->t_triggered_interval)
                   1521:     {
                   1522:       thread_cancel (ripng->t_triggered_interval);
                   1523:       ripng->t_triggered_interval = NULL;
                   1524:     }
                   1525:   ripng->trigger = 0;
                   1526: 
                   1527:   /* Logging triggered update. */
                   1528:   if (IS_RIPNG_DEBUG_EVENT)
                   1529:     zlog_debug ("RIPng triggered update!");
                   1530: 
                   1531:   /* Split Horizon processing is done when generating triggered
                   1532:      updates as well as normal updates (see section 2.6). */
                   1533:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                   1534:     {
                   1535:       ri = ifp->info;
                   1536: 
                   1537:       if (if_is_loopback (ifp) || ! if_is_up (ifp))
                   1538:        continue;
                   1539: 
                   1540:       if (! ri->running)
                   1541:        continue;
                   1542: 
                   1543:       /* When passive interface is specified, suppress announce to the
                   1544:          interface. */
                   1545:       if (ri->passive)
                   1546:        continue;
                   1547: 
                   1548:       ripng_output_process (ifp, NULL, ripng_changed_route);
                   1549:     }
                   1550: 
                   1551:   /* Once all of the triggered updates have been generated, the route
                   1552:      change flags should be cleared. */
                   1553:   ripng_clear_changed_flag ();
                   1554: 
                   1555:   /* After a triggered update is sent, a timer should be set for a
                   1556:      random interval between 1 and 5 seconds.  If other changes that
                   1557:      would trigger updates occur before the timer expires, a single
                   1558:      update is triggered when the timer expires. */
                   1559:   interval = (random () % 5) + 1;
                   1560: 
                   1561:   ripng->t_triggered_interval = 
                   1562:     thread_add_timer (master, ripng_triggered_interval, NULL, interval);
                   1563: 
                   1564:   return 0;
                   1565: }
                   1566: 
                   1567: /* Write routing table entry to the stream and return next index of
                   1568:    the routing table entry in the stream. */
                   1569: int
                   1570: ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,
                   1571:                 struct in6_addr *nexthop, u_int16_t tag, u_char metric)
                   1572: {
                   1573:   /* RIPng packet header. */
                   1574:   if (num == 0)
                   1575:     {
                   1576:       stream_putc (s, RIPNG_RESPONSE);
                   1577:       stream_putc (s, RIPNG_V1);
                   1578:       stream_putw (s, 0);
                   1579:     }
                   1580: 
                   1581:   /* Write routing table entry. */
                   1582:   if (!nexthop)
                   1583:     stream_write (s, (u_char *) &p->prefix, sizeof (struct in6_addr));
                   1584:   else
                   1585:     stream_write (s, (u_char *) nexthop, sizeof (struct in6_addr));
                   1586:   stream_putw (s, tag);
                   1587:   if (p)
                   1588:     stream_putc (s, p->prefixlen);
                   1589:   else
                   1590:     stream_putc (s, 0);
                   1591:   stream_putc (s, metric);
                   1592: 
                   1593:   return ++num;
                   1594: }
                   1595: 
                   1596: /* Send RESPONSE message to specified destination. */
                   1597: void
                   1598: ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to,
                   1599:                      int route_type)
                   1600: {
                   1601:   int ret;
                   1602:   struct route_node *rp;
                   1603:   struct ripng_info *rinfo;
                   1604:   struct ripng_interface *ri;
                   1605:   struct ripng_aggregate *aggregate;
                   1606:   struct prefix_ipv6 *p;
                   1607:   struct list * ripng_rte_list;
                   1608: 
                   1609:   if (IS_RIPNG_DEBUG_EVENT) {
                   1610:     if (to)
                   1611:       zlog_debug ("RIPng update routes to neighbor %s",
                   1612:                  inet6_ntoa(to->sin6_addr));
                   1613:     else
                   1614:       zlog_debug ("RIPng update routes on interface %s", ifp->name);
                   1615:   }
                   1616: 
                   1617:   /* Get RIPng interface. */
                   1618:   ri = ifp->info;
                   1619:  
                   1620:   ripng_rte_list = ripng_rte_new();
                   1621:  
                   1622:   for (rp = route_top (ripng->table); rp; rp = route_next (rp))
                   1623:     {
                   1624:       if ((rinfo = rp->info) != NULL && rinfo->suppress == 0)
                   1625:        {
                   1626:          /* If no route-map are applied, the RTE will be these following
                   1627:           * informations.
                   1628:           */
                   1629:          p = (struct prefix_ipv6 *) &rp->p;
                   1630:          rinfo->metric_out = rinfo->metric;
                   1631:          rinfo->tag_out    = rinfo->tag;
                   1632:          memset(&rinfo->nexthop_out, 0, sizeof(rinfo->nexthop_out));
                   1633:          /* In order to avoid some local loops,
                   1634:           * if the RIPng route has a nexthop via this interface, keep the nexthop,
                   1635:           * otherwise set it to 0. The nexthop should not be propagated
                   1636:           * beyond the local broadcast/multicast area in order
                   1637:           * to avoid an IGP multi-level recursive look-up.
                   1638:           */
                   1639:          if (rinfo->ifindex == ifp->ifindex)
                   1640:            rinfo->nexthop_out = rinfo->nexthop;
                   1641: 
                   1642:          /* Apply output filters. */
                   1643:          ret = ripng_outgoing_filter (p, ri);
                   1644:          if (ret < 0)
                   1645:            continue;
                   1646: 
                   1647:          /* Changed route only output. */
                   1648:          if (route_type == ripng_changed_route &&
                   1649:              (! (rinfo->flags & RIPNG_RTF_CHANGED)))
                   1650:            continue;
                   1651: 
                   1652:          /* Split horizon. */
                   1653:          if (ri->split_horizon == RIPNG_SPLIT_HORIZON)
                   1654:          {
                   1655:            /* We perform split horizon for RIPng routes. */
                   1656:            if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
                   1657:                rinfo->ifindex == ifp->ifindex)
                   1658:              continue;
                   1659:          }
                   1660: 
                   1661:          /* Preparation for route-map. */
                   1662:          rinfo->metric_set = 0;
                   1663:          /* nexthop_out,
                   1664:           * metric_out
                   1665:           * and tag_out are already initialized.
                   1666:           */
                   1667: 
                   1668:          /* Interface route-map */
                   1669:          if (ri->routemap[RIPNG_FILTER_OUT])
                   1670:            {
                   1671:              int ret;
                   1672: 
                   1673:              ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT], 
                   1674:                                     (struct prefix *) p, RMAP_RIPNG, 
                   1675:                                     rinfo);
                   1676: 
                   1677:              if (ret == RMAP_DENYMATCH)
                   1678:                {
                   1679:                  if (IS_RIPNG_DEBUG_PACKET)
                   1680:                    zlog_debug ("RIPng %s/%d is filtered by route-map out",
                   1681:                               inet6_ntoa (p->prefix), p->prefixlen);
                   1682:                  continue;
                   1683:                }
                   1684: 
                   1685:            }
                   1686: 
                   1687:          /* Redistribute route-map. */
                   1688:          if (ripng->route_map[rinfo->type].name)
                   1689:            {
                   1690:              int ret;
                   1691: 
                   1692:              ret = route_map_apply (ripng->route_map[rinfo->type].map,
                   1693:                                     (struct prefix *) p, RMAP_RIPNG,
                   1694:                                     rinfo);
                   1695: 
                   1696:              if (ret == RMAP_DENYMATCH)
                   1697:                {
                   1698:                  if (IS_RIPNG_DEBUG_PACKET)
                   1699:                    zlog_debug ("RIPng %s/%d is filtered by route-map",
                   1700:                               inet6_ntoa (p->prefix), p->prefixlen);
                   1701:                  continue;
                   1702:                }
                   1703:            }
                   1704: 
                   1705:          /* When the route-map does not set metric. */
                   1706:          if (! rinfo->metric_set)
                   1707:            {
                   1708:              /* If the redistribute metric is set. */
                   1709:              if (ripng->route_map[rinfo->type].metric_config
                   1710:                  && rinfo->metric != RIPNG_METRIC_INFINITY)
                   1711:                {
                   1712:                  rinfo->metric_out = ripng->route_map[rinfo->type].metric;
                   1713:                }
                   1714:              else
                   1715:                {
                   1716:                  /* If the route is not connected or localy generated
                   1717:                     one, use default-metric value */
                   1718:                  if (rinfo->type != ZEBRA_ROUTE_RIPNG
                   1719:                      && rinfo->type != ZEBRA_ROUTE_CONNECT
                   1720:                      && rinfo->metric != RIPNG_METRIC_INFINITY)
                   1721:                    rinfo->metric_out = ripng->default_metric;
                   1722:                }
                   1723:            }
                   1724: 
                   1725:           /* Apply offset-list */
                   1726:          if (rinfo->metric_out != RIPNG_METRIC_INFINITY)
                   1727:             ripng_offset_list_apply_out (p, ifp, &rinfo->metric_out);
                   1728: 
                   1729:           if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
                   1730:             rinfo->metric_out = RIPNG_METRIC_INFINITY;
                   1731: 
                   1732:          /* Perform split-horizon with poisoned reverse 
                   1733:           * for RIPng routes.
                   1734:           **/
                   1735:          if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) {
                   1736:            if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
                   1737:                 rinfo->ifindex == ifp->ifindex)
                   1738:                 rinfo->metric_out = RIPNG_METRIC_INFINITY;
                   1739:          }
                   1740: 
                   1741:          /* Add RTE to the list */
                   1742:          ripng_rte_add(ripng_rte_list, p, rinfo, NULL);
                   1743:        }
                   1744: 
                   1745:       /* Process the aggregated RTE entry */
                   1746:       if ((aggregate = rp->aggregate) != NULL && 
                   1747:          aggregate->count > 0 && 
                   1748:          aggregate->suppress == 0)
                   1749:        {
                   1750:          /* If no route-map are applied, the RTE will be these following
                   1751:           * informations.
                   1752:           */
                   1753:          p = (struct prefix_ipv6 *) &rp->p;
                   1754:          aggregate->metric_set = 0;
                   1755:          aggregate->metric_out = aggregate->metric;
                   1756:          aggregate->tag_out    = aggregate->tag;
                   1757:          memset(&aggregate->nexthop_out, 0, sizeof(aggregate->nexthop_out));
                   1758: 
                   1759:          /* Apply output filters.*/
                   1760:          ret = ripng_outgoing_filter (p, ri);
                   1761:          if (ret < 0)
                   1762:            continue;
                   1763: 
                   1764:          /* Interface route-map */
                   1765:          if (ri->routemap[RIPNG_FILTER_OUT])
                   1766:            {
                   1767:              int ret;
                   1768:              struct ripng_info newinfo;
                   1769: 
                   1770:              /* let's cast the aggregate structure to ripng_info */
                   1771:              memset (&newinfo, 0, sizeof (struct ripng_info));
                   1772:              /* the nexthop is :: */
                   1773:              newinfo.metric = aggregate->metric;
                   1774:              newinfo.metric_out = aggregate->metric_out;
                   1775:              newinfo.tag = aggregate->tag;
                   1776:              newinfo.tag_out = aggregate->tag_out;
                   1777: 
                   1778:              ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT], 
                   1779:                                     (struct prefix *) p, RMAP_RIPNG, 
                   1780:                                     &newinfo);
                   1781: 
                   1782:              if (ret == RMAP_DENYMATCH)
                   1783:                {
                   1784:                  if (IS_RIPNG_DEBUG_PACKET)
                   1785:                    zlog_debug ("RIPng %s/%d is filtered by route-map out",
                   1786:                               inet6_ntoa (p->prefix), p->prefixlen);
                   1787:                  continue;
                   1788:                }
                   1789: 
                   1790:              aggregate->metric_out = newinfo.metric_out;
                   1791:              aggregate->tag_out = newinfo.tag_out;
                   1792:              if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out))
                   1793:                aggregate->nexthop_out = newinfo.nexthop_out;
                   1794:            }
                   1795: 
                   1796:          /* There is no redistribute routemap for the aggregated RTE */
                   1797: 
                   1798:          /* Changed route only output. */
                   1799:          /* XXX, vincent, in order to increase time convergence,
                   1800:           * it should be announced if a child has changed.
                   1801:           */
                   1802:          if (route_type == ripng_changed_route)
                   1803:            continue;
                   1804: 
                   1805:          /* Apply offset-list */
                   1806:          if (aggregate->metric_out != RIPNG_METRIC_INFINITY)
                   1807:            ripng_offset_list_apply_out (p, ifp, &aggregate->metric_out);
                   1808: 
                   1809:          if (aggregate->metric_out > RIPNG_METRIC_INFINITY)
                   1810:            aggregate->metric_out = RIPNG_METRIC_INFINITY;
                   1811: 
                   1812:          /* Add RTE to the list */
                   1813:          ripng_rte_add(ripng_rte_list, p, NULL, aggregate);
                   1814:        }
                   1815: 
                   1816:     }
                   1817: 
                   1818:   /* Flush the list */
                   1819:   ripng_rte_send(ripng_rte_list, ifp, to);
                   1820:   ripng_rte_free(ripng_rte_list);
                   1821: }
                   1822: 
                   1823: /* Create new RIPng instance and set it to global variable. */
                   1824: static int
                   1825: ripng_create (void)
                   1826: {
                   1827:   /* ripng should be NULL. */
                   1828:   assert (ripng == NULL);
                   1829: 
                   1830:   /* Allocaste RIPng instance. */
                   1831:   ripng = XCALLOC (MTYPE_RIPNG, sizeof (struct ripng));
                   1832: 
                   1833:   /* Default version and timer values. */
                   1834:   ripng->version = RIPNG_V1;
                   1835:   ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
                   1836:   ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
                   1837:   ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
                   1838:   ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
                   1839:   
                   1840:   /* Make buffer.  */
                   1841:   ripng->ibuf = stream_new (RIPNG_MAX_PACKET_SIZE * 5);
                   1842:   ripng->obuf = stream_new (RIPNG_MAX_PACKET_SIZE);
                   1843: 
                   1844:   /* Initialize RIPng routig table. */
                   1845:   ripng->table = route_table_init ();
                   1846:   ripng->route = route_table_init ();
                   1847:   ripng->aggregate = route_table_init ();
                   1848:  
                   1849:   /* Make socket. */
                   1850:   ripng->sock = ripng_make_socket ();
                   1851:   if (ripng->sock < 0)
                   1852:     return ripng->sock;
                   1853: 
                   1854:   /* Threads. */
                   1855:   ripng_event (RIPNG_READ, ripng->sock);
                   1856:   ripng_event (RIPNG_UPDATE_EVENT, 1);
                   1857: 
                   1858:   return 0;
                   1859: }
                   1860: 
                   1861: /* Send RIPng request to the interface. */
                   1862: int
                   1863: ripng_request (struct interface *ifp)
                   1864: {
                   1865:   struct rte *rte;
                   1866:   struct ripng_packet ripng_packet;
                   1867: 
                   1868:   /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
                   1869:   if (if_is_loopback(ifp))
                   1870:     return 0;
                   1871: 
                   1872:   /* If interface is down, don't send RIP packet. */
                   1873:   if (! if_is_up (ifp))
                   1874:     return 0;
                   1875: 
                   1876:   if (IS_RIPNG_DEBUG_EVENT)
                   1877:     zlog_debug ("RIPng send request to %s", ifp->name);
                   1878: 
                   1879:   memset (&ripng_packet, 0, sizeof (ripng_packet));
                   1880:   ripng_packet.command = RIPNG_REQUEST;
                   1881:   ripng_packet.version = RIPNG_V1;
                   1882:   rte = ripng_packet.rte;
                   1883:   rte->metric = RIPNG_METRIC_INFINITY;
                   1884: 
                   1885:   return ripng_send_packet ((caddr_t) &ripng_packet, sizeof (ripng_packet), 
                   1886:                            NULL, ifp);
                   1887: }
                   1888: 
                   1889: 
                   1890: static int
                   1891: ripng_update_jitter (int time)
                   1892: {
                   1893:   return ((rand () % (time + 1)) - (time / 2));
                   1894: }
                   1895: 
                   1896: void
                   1897: ripng_event (enum ripng_event event, int sock)
                   1898: {
                   1899:   int jitter = 0;
                   1900: 
                   1901:   switch (event)
                   1902:     {
                   1903:     case RIPNG_READ:
                   1904:       if (!ripng->t_read)
                   1905:        ripng->t_read = thread_add_read (master, ripng_read, NULL, sock);
                   1906:       break;
                   1907:     case RIPNG_UPDATE_EVENT:
                   1908:       if (ripng->t_update)
                   1909:        {
                   1910:          thread_cancel (ripng->t_update);
                   1911:          ripng->t_update = NULL;
                   1912:        }
                   1913:       /* Update timer jitter. */
                   1914:       jitter = ripng_update_jitter (ripng->update_time);
                   1915: 
                   1916:       ripng->t_update = 
                   1917:        thread_add_timer (master, ripng_update, NULL, 
                   1918:                          sock ? 2 : ripng->update_time + jitter);
                   1919:       break;
                   1920:     case RIPNG_TRIGGERED_UPDATE:
                   1921:       if (ripng->t_triggered_interval)
                   1922:        ripng->trigger = 1;
                   1923:       else if (! ripng->t_triggered_update)
                   1924:        ripng->t_triggered_update = 
                   1925:          thread_add_event (master, ripng_triggered_update, NULL, 0);
                   1926:       break;
                   1927:     default:
                   1928:       break;
                   1929:     }
                   1930: }
                   1931: 
                   1932: 
                   1933: /* Print out routes update time. */
                   1934: static void
                   1935: ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo)
                   1936: {
                   1937:   time_t clock;
                   1938:   struct tm *tm;
                   1939: #define TIME_BUF 25
                   1940:   char timebuf [TIME_BUF];
                   1941:   struct thread *thread;
                   1942:   
                   1943:   if ((thread = rinfo->t_timeout) != NULL)
                   1944:     {
                   1945:       clock = thread_timer_remain_second (thread);
                   1946:       tm = gmtime (&clock);
                   1947:       strftime (timebuf, TIME_BUF, "%M:%S", tm);
                   1948:       vty_out (vty, "%5s", timebuf);
                   1949:     }
                   1950:   else if ((thread = rinfo->t_garbage_collect) != NULL)
                   1951:     {
                   1952:       clock = thread_timer_remain_second (thread);
                   1953:       tm = gmtime (&clock);
                   1954:       strftime (timebuf, TIME_BUF, "%M:%S", tm);
                   1955:       vty_out (vty, "%5s", timebuf);
                   1956:     }
                   1957: }
                   1958: 
                   1959: static char *
                   1960: ripng_route_subtype_print (struct ripng_info *rinfo)
                   1961: {
                   1962:   static char str[3];
                   1963:   memset(str, 0, 3);
                   1964: 
                   1965:   if (rinfo->suppress)
                   1966:     strcat(str, "S");
                   1967: 
                   1968:   switch (rinfo->sub_type)
                   1969:     {
                   1970:        case RIPNG_ROUTE_RTE:
                   1971:          strcat(str, "n");
                   1972:          break;
                   1973:        case RIPNG_ROUTE_STATIC:
                   1974:          strcat(str, "s");
                   1975:          break;
                   1976:        case RIPNG_ROUTE_DEFAULT:
                   1977:          strcat(str, "d");
                   1978:          break;
                   1979:        case RIPNG_ROUTE_REDISTRIBUTE:
                   1980:          strcat(str, "r");
                   1981:          break;
                   1982:        case RIPNG_ROUTE_INTERFACE:
                   1983:          strcat(str, "i");
                   1984:          break;
                   1985:        default:
                   1986:          strcat(str, "?");
                   1987:          break;
                   1988:     }
                   1989:  
                   1990:   return str;
                   1991: }
                   1992: 
                   1993: DEFUN (show_ipv6_ripng,
                   1994:        show_ipv6_ripng_cmd,
                   1995:        "show ipv6 ripng",
                   1996:        SHOW_STR
                   1997:        IPV6_STR
                   1998:        "Show RIPng routes\n")
                   1999: {
                   2000:   struct route_node *rp;
                   2001:   struct ripng_info *rinfo;
                   2002:   struct ripng_aggregate *aggregate;
                   2003:   struct prefix_ipv6 *p;
                   2004:   int len;
                   2005: 
                   2006:   if (! ripng)
                   2007:     return CMD_SUCCESS;
                   2008: 
                   2009:   /* Header of display. */ 
                   2010:   vty_out (vty, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
                   2011:           "Sub-codes:%s"
                   2012:           "      (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
                   2013:           "      (i) - interface, (a/S) - aggregated/Suppressed%s%s"
                   2014:           "   Network      Next Hop                      Via     Metric Tag Time%s",
                   2015:           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
                   2016:           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
                   2017:   
                   2018:   for (rp = route_top (ripng->table); rp; rp = route_next (rp))
                   2019:     {
                   2020:       if ((aggregate = rp->aggregate) != NULL)
                   2021:        {
                   2022:          p = (struct prefix_ipv6 *) &rp->p;
                   2023: 
                   2024: #ifdef DEBUG
                   2025:          len = vty_out (vty, "R(a) %d/%d %s/%d ",
                   2026:                         aggregate->count, aggregate->suppress,
                   2027:                         inet6_ntoa (p->prefix), p->prefixlen);
                   2028: #else
                   2029:          len = vty_out (vty, "R(a) %s/%d ", 
                   2030:                         inet6_ntoa (p->prefix), p->prefixlen);
                   2031: #endif /* DEBUG */
                   2032:          vty_out (vty, "%s", VTY_NEWLINE);
                   2033:          vty_out (vty, "%*s", 18, " ");
                   2034: 
                   2035:          vty_out (vty, "%*s", 28, " ");
                   2036:          vty_out (vty, "self      %2d  %3d%s", aggregate->metric,
                   2037:                   aggregate->tag,
                   2038:                   VTY_NEWLINE);
                   2039:        }
                   2040: 
                   2041:       if ((rinfo = rp->info) != NULL)
                   2042:        {
                   2043:          p = (struct prefix_ipv6 *) &rp->p;
                   2044: 
                   2045: #ifdef DEBUG
                   2046:          len = vty_out (vty, "%c(%s) 0/%d %s/%d ",
                   2047:                         zebra_route_char(rinfo->type),
                   2048:                         ripng_route_subtype_print(rinfo),
                   2049:                         rinfo->suppress,
                   2050:                         inet6_ntoa (p->prefix), p->prefixlen);
                   2051: #else
                   2052:          len = vty_out (vty, "%c(%s) %s/%d ",
                   2053:                         zebra_route_char(rinfo->type),
                   2054:                         ripng_route_subtype_print(rinfo),
                   2055:                         inet6_ntoa (p->prefix), p->prefixlen);
                   2056: #endif /* DEBUG */
                   2057:          vty_out (vty, "%s", VTY_NEWLINE);
                   2058:          vty_out (vty, "%*s", 18, " ");
                   2059:          len = vty_out (vty, "%s", inet6_ntoa (rinfo->nexthop));
                   2060: 
                   2061:          len = 28 - len;
                   2062:          if (len > 0)
                   2063:            len = vty_out (vty, "%*s", len, " ");
                   2064: 
                   2065:          /* from */
                   2066:          if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && 
                   2067:            (rinfo->sub_type == RIPNG_ROUTE_RTE))
                   2068:          {
                   2069:            len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex));
                   2070:          } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
                   2071:          {
                   2072:            len = vty_out (vty, "kill");
                   2073:          } else
                   2074:            len = vty_out (vty, "self");
                   2075: 
                   2076:          len = 9 - len;
                   2077:          if (len > 0)
                   2078:            vty_out (vty, "%*s", len, " ");
                   2079: 
                   2080:          vty_out (vty, " %2d  %3d  ",
                   2081:                   rinfo->metric, rinfo->tag);
                   2082: 
                   2083:          /* time */
                   2084:          if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && 
                   2085:            (rinfo->sub_type == RIPNG_ROUTE_RTE))
                   2086:          {
                   2087:            /* RTE from remote RIP routers */
                   2088:            ripng_vty_out_uptime (vty, rinfo);
                   2089:          } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
                   2090:          {
                   2091:            /* poisonous reversed routes (gc) */
                   2092:            ripng_vty_out_uptime (vty, rinfo);
                   2093:          }
                   2094: 
                   2095:          vty_out (vty, "%s", VTY_NEWLINE);
                   2096:        }
                   2097:     }
                   2098: 
                   2099:   return CMD_SUCCESS;
                   2100: }
                   2101: 
                   2102: DEFUN (show_ipv6_ripng_status,
                   2103:        show_ipv6_ripng_status_cmd,
                   2104:        "show ipv6 ripng status",
                   2105:        SHOW_STR
                   2106:        IPV6_STR
                   2107:        "Show RIPng routes\n"
                   2108:        "IPv6 routing protocol process parameters and statistics\n")
                   2109: {
                   2110:   struct listnode *node;
                   2111:   struct interface *ifp;
                   2112: 
                   2113:   if (! ripng)
                   2114:     return CMD_SUCCESS;
                   2115: 
                   2116:   vty_out (vty, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE);
                   2117:   vty_out (vty, "  Sending updates every %ld seconds with +/-50%%,",
                   2118:            ripng->update_time);
                   2119:   vty_out (vty, " next due in %lu seconds%s",
                   2120:            thread_timer_remain_second (ripng->t_update),
                   2121:            VTY_NEWLINE);
                   2122:   vty_out (vty, "  Timeout after %ld seconds,", ripng->timeout_time);
                   2123:   vty_out (vty, " garbage collect after %ld seconds%s", ripng->garbage_time,
                   2124:            VTY_NEWLINE);
                   2125: 
                   2126:   /* Filtering status show. */
                   2127:   config_show_distribute (vty);
                   2128: 
                   2129:   /* Default metric information. */
                   2130:   vty_out (vty, "  Default redistribution metric is %d%s",
                   2131:            ripng->default_metric, VTY_NEWLINE);
                   2132: 
                   2133:   /* Redistribute information. */
                   2134:   vty_out (vty, "  Redistributing:");
                   2135:   ripng_redistribute_write (vty, 0);
                   2136:   vty_out (vty, "%s", VTY_NEWLINE);
                   2137: 
                   2138:   vty_out (vty, "  Default version control: send version %d,", ripng->version);
                   2139:   vty_out (vty, " receive version %d %s", ripng->version,
                   2140:            VTY_NEWLINE);
                   2141: 
                   2142:   vty_out (vty, "    Interface        Send  Recv%s", VTY_NEWLINE);
                   2143: 
                   2144:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                   2145:     {
                   2146:       struct ripng_interface *ri;
                   2147:       
                   2148:       ri = ifp->info;
                   2149: 
                   2150:       if (ri->enable_network || ri->enable_interface)
                   2151:        {
                   2152: 
                   2153:          vty_out (vty, "    %-17s%-3d   %-3d%s", ifp->name,
                   2154:                   ripng->version,
                   2155:                   ripng->version,
                   2156:                   VTY_NEWLINE);
                   2157:        }
                   2158:     }
                   2159: 
                   2160:   vty_out (vty, "  Routing for Networks:%s", VTY_NEWLINE);
                   2161:   ripng_network_write (vty, 0);
                   2162: 
                   2163:   vty_out (vty, "  Routing Information Sources:%s", VTY_NEWLINE);
                   2164:   vty_out (vty, "    Gateway          BadPackets BadRoutes  Distance Last Update%s", VTY_NEWLINE);
                   2165:   ripng_peer_display (vty);
                   2166: 
                   2167:   return CMD_SUCCESS;  
                   2168: }
                   2169: 
                   2170: DEFUN (router_ripng,
                   2171:        router_ripng_cmd,
                   2172:        "router ripng",
                   2173:        "Enable a routing process\n"
                   2174:        "Make RIPng instance command\n")
                   2175: {
                   2176:   int ret;
                   2177: 
                   2178:   vty->node = RIPNG_NODE;
                   2179: 
                   2180:   if (!ripng)
                   2181:     {
                   2182:       ret = ripng_create ();
                   2183: 
                   2184:       /* Notice to user we couldn't create RIPng. */
                   2185:       if (ret < 0)
                   2186:        {
                   2187:          zlog_warn ("can't create RIPng");
                   2188:          return CMD_WARNING;
                   2189:        }
                   2190:     }
                   2191: 
                   2192:   return CMD_SUCCESS;
                   2193: }
                   2194: 
                   2195: DEFUN (no_router_ripng,
                   2196:        no_router_ripng_cmd,
                   2197:        "no router ripng",
                   2198:        NO_STR
                   2199:        "Enable a routing process\n"
                   2200:        "Make RIPng instance command\n")
                   2201: {
                   2202:   if(ripng)
                   2203:     ripng_clean();
                   2204:   return CMD_SUCCESS;
                   2205: }
                   2206: 
                   2207: DEFUN (ripng_route,
                   2208:        ripng_route_cmd,
                   2209:        "route IPV6ADDR",
                   2210:        "Static route setup\n"
                   2211:        "Set static RIPng route announcement\n")
                   2212: {
                   2213:   int ret;
                   2214:   struct prefix_ipv6 p;
                   2215:   struct route_node *rp;
                   2216: 
                   2217:   ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
                   2218:   if (ret <= 0)
                   2219:     {
                   2220:       vty_out (vty, "Malformed address%s", VTY_NEWLINE);
                   2221:       return CMD_WARNING;
                   2222:     }
                   2223:   apply_mask_ipv6 (&p);
                   2224: 
                   2225:   rp = route_node_get (ripng->route, (struct prefix *) &p);
                   2226:   if (rp->info)
                   2227:     {
                   2228:       vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
                   2229:       route_unlock_node (rp);
                   2230:       return CMD_WARNING;
                   2231:     }
                   2232:   rp->info = (void *)1;
                   2233: 
                   2234:   ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL);
                   2235: 
                   2236:   return CMD_SUCCESS;
                   2237: }
                   2238: 
                   2239: DEFUN (no_ripng_route,
                   2240:        no_ripng_route_cmd,
                   2241:        "no route IPV6ADDR",
                   2242:        NO_STR
                   2243:        "Static route setup\n"
                   2244:        "Delete static RIPng route announcement\n")
                   2245: {
                   2246:   int ret;
                   2247:   struct prefix_ipv6 p;
                   2248:   struct route_node *rp;
                   2249: 
                   2250:   ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
                   2251:   if (ret <= 0)
                   2252:     {
                   2253:       vty_out (vty, "Malformed address%s", VTY_NEWLINE);
                   2254:       return CMD_WARNING;
                   2255:     }
                   2256:   apply_mask_ipv6 (&p);
                   2257: 
                   2258:   rp = route_node_lookup (ripng->route, (struct prefix *) &p);
                   2259:   if (! rp)
                   2260:     {
                   2261:       vty_out (vty, "Can't find static route.%s", VTY_NEWLINE);
                   2262:       return CMD_WARNING;
                   2263:     }
                   2264: 
                   2265:   ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
                   2266:   route_unlock_node (rp);
                   2267: 
                   2268:   rp->info = NULL;
                   2269:   route_unlock_node (rp);
                   2270: 
                   2271:   return CMD_SUCCESS;
                   2272: }
                   2273: 
                   2274: DEFUN (ripng_aggregate_address,
                   2275:        ripng_aggregate_address_cmd,
                   2276:        "aggregate-address X:X::X:X/M",
                   2277:        "Set aggregate RIPng route announcement\n"
                   2278:        "Aggregate network\n")
                   2279: {
                   2280:   int ret;
                   2281:   struct prefix p;
                   2282:   struct route_node *node;
                   2283: 
                   2284:   ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
                   2285:   if (ret <= 0)
                   2286:     {
                   2287:       vty_out (vty, "Malformed address%s", VTY_NEWLINE);
                   2288:       return CMD_WARNING;
                   2289:     }
                   2290: 
                   2291:   /* Check aggregate alredy exist or not. */
                   2292:   node = route_node_get (ripng->aggregate, &p);
                   2293:   if (node->info)
                   2294:     {
                   2295:       vty_out (vty, "There is already same aggregate route.%s", VTY_NEWLINE);
                   2296:       route_unlock_node (node);
                   2297:       return CMD_WARNING;
                   2298:     }
                   2299:   node->info = (void *)1;
                   2300: 
                   2301:   ripng_aggregate_add (&p);
                   2302: 
                   2303:   return CMD_SUCCESS;
                   2304: }
                   2305: 
                   2306: DEFUN (no_ripng_aggregate_address,
                   2307:        no_ripng_aggregate_address_cmd,
                   2308:        "no aggregate-address X:X::X:X/M",
                   2309:        NO_STR
                   2310:        "Delete aggregate RIPng route announcement\n"
                   2311:        "Aggregate network")
                   2312: {
                   2313:   int ret;
                   2314:   struct prefix p;
                   2315:   struct route_node *rn;
                   2316: 
                   2317:   ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &p);
                   2318:   if (ret <= 0)
                   2319:     {
                   2320:       vty_out (vty, "Malformed address%s", VTY_NEWLINE);
                   2321:       return CMD_WARNING;
                   2322:     }
                   2323: 
                   2324:   rn = route_node_lookup (ripng->aggregate, &p);
                   2325:   if (! rn)
                   2326:     {
                   2327:       vty_out (vty, "Can't find aggregate route.%s", VTY_NEWLINE);
                   2328:       return CMD_WARNING;
                   2329:     }
                   2330:   route_unlock_node (rn);
                   2331:   rn->info = NULL;
                   2332:   route_unlock_node (rn);
                   2333: 
                   2334:   ripng_aggregate_delete (&p);
                   2335: 
                   2336:   return CMD_SUCCESS;
                   2337: }
                   2338: 
                   2339: DEFUN (ripng_default_metric,
                   2340:        ripng_default_metric_cmd,
                   2341:        "default-metric <1-16>",
                   2342:        "Set a metric of redistribute routes\n"
                   2343:        "Default metric\n")
                   2344: {
                   2345:   if (ripng)
                   2346:     {
                   2347:       ripng->default_metric = atoi (argv[0]);
                   2348:     }
                   2349:   return CMD_SUCCESS;
                   2350: }
                   2351: 
                   2352: DEFUN (no_ripng_default_metric,
                   2353:        no_ripng_default_metric_cmd,
                   2354:        "no default-metric",
                   2355:        NO_STR
                   2356:        "Set a metric of redistribute routes\n"
                   2357:        "Default metric\n")
                   2358: {
                   2359:   if (ripng)
                   2360:     {
                   2361:       ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
                   2362:     }
                   2363:   return CMD_SUCCESS;
                   2364: }
                   2365: 
                   2366: ALIAS (no_ripng_default_metric,
                   2367:        no_ripng_default_metric_val_cmd,
                   2368:        "no default-metric <1-16>",
                   2369:        NO_STR
                   2370:        "Set a metric of redistribute routes\n"
                   2371:        "Default metric\n")
                   2372: 
                   2373: #if 0
                   2374: /* RIPng update timer setup. */
                   2375: DEFUN (ripng_update_timer,
                   2376:        ripng_update_timer_cmd,
                   2377:        "update-timer SECOND",
                   2378:        "Set RIPng update timer in seconds\n"
                   2379:        "Seconds\n")
                   2380: {
                   2381:   unsigned long update;
                   2382:   char *endptr = NULL;
                   2383: 
                   2384:   update = strtoul (argv[0], &endptr, 10);
                   2385:   if (update == ULONG_MAX || *endptr != '\0')
                   2386:     {
                   2387:       vty_out (vty, "update timer value error%s", VTY_NEWLINE);
                   2388:       return CMD_WARNING;
                   2389:     }
                   2390: 
                   2391:   ripng->update_time = update;
                   2392: 
                   2393:   ripng_event (RIPNG_UPDATE_EVENT, 0);
                   2394:   return CMD_SUCCESS;
                   2395: }
                   2396: 
                   2397: DEFUN (no_ripng_update_timer,
                   2398:        no_ripng_update_timer_cmd,
                   2399:        "no update-timer SECOND",
                   2400:        NO_STR
                   2401:        "Unset RIPng update timer in seconds\n"
                   2402:        "Seconds\n")
                   2403: {
                   2404:   ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
                   2405:   ripng_event (RIPNG_UPDATE_EVENT, 0);
                   2406:   return CMD_SUCCESS;
                   2407: }
                   2408: 
                   2409: /* RIPng timeout timer setup. */
                   2410: DEFUN (ripng_timeout_timer,
                   2411:        ripng_timeout_timer_cmd,
                   2412:        "timeout-timer SECOND",
                   2413:        "Set RIPng timeout timer in seconds\n"
                   2414:        "Seconds\n")
                   2415: {
                   2416:   unsigned long timeout;
                   2417:   char *endptr = NULL;
                   2418: 
                   2419:   timeout = strtoul (argv[0], &endptr, 10);
                   2420:   if (timeout == ULONG_MAX || *endptr != '\0')
                   2421:     {
                   2422:       vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
                   2423:       return CMD_WARNING;
                   2424:     }
                   2425: 
                   2426:   ripng->timeout_time = timeout;
                   2427: 
                   2428:   return CMD_SUCCESS;
                   2429: }
                   2430: 
                   2431: DEFUN (no_ripng_timeout_timer,
                   2432:        no_ripng_timeout_timer_cmd,
                   2433:        "no timeout-timer SECOND",
                   2434:        NO_STR
                   2435:        "Unset RIPng timeout timer in seconds\n"
                   2436:        "Seconds\n")
                   2437: {
                   2438:   ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
                   2439:   return CMD_SUCCESS;
                   2440: }
                   2441: 
                   2442: /* RIPng garbage timer setup. */
                   2443: DEFUN (ripng_garbage_timer,
                   2444:        ripng_garbage_timer_cmd,
                   2445:        "garbage-timer SECOND",
                   2446:        "Set RIPng garbage timer in seconds\n"
                   2447:        "Seconds\n")
                   2448: {
                   2449:   unsigned long garbage;
                   2450:   char *endptr = NULL;
                   2451: 
                   2452:   garbage = strtoul (argv[0], &endptr, 10);
                   2453:   if (garbage == ULONG_MAX || *endptr != '\0')
                   2454:     {
                   2455:       vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
                   2456:       return CMD_WARNING;
                   2457:     }
                   2458: 
                   2459:   ripng->garbage_time = garbage;
                   2460: 
                   2461:   return CMD_SUCCESS;
                   2462: }
                   2463: 
                   2464: DEFUN (no_ripng_garbage_timer,
                   2465:        no_ripng_garbage_timer_cmd,
                   2466:        "no garbage-timer SECOND",
                   2467:        NO_STR
                   2468:        "Unset RIPng garbage timer in seconds\n"
                   2469:        "Seconds\n")
                   2470: {
                   2471:   ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
                   2472:   return CMD_SUCCESS;
                   2473: }
                   2474: #endif /* 0 */
                   2475: 
                   2476: DEFUN (ripng_timers,
                   2477:        ripng_timers_cmd,
                   2478:        "timers basic <0-65535> <0-65535> <0-65535>",
                   2479:        "RIPng timers setup\n"
                   2480:        "Basic timer\n"
                   2481:        "Routing table update timer value in second. Default is 30.\n"
                   2482:        "Routing information timeout timer. Default is 180.\n"
                   2483:        "Garbage collection timer. Default is 120.\n")
                   2484: {
                   2485:   unsigned long update;
                   2486:   unsigned long timeout;
                   2487:   unsigned long garbage;
                   2488: 
1.1.1.2 ! misho    2489:   VTY_GET_INTEGER_RANGE("update timer", update, argv[0], 0, 65535);
        !          2490:   VTY_GET_INTEGER_RANGE("timeout timer", timeout, argv[1], 0, 65535);
        !          2491:   VTY_GET_INTEGER_RANGE("garbage timer", garbage, argv[2], 0, 65535);
1.1       misho    2492: 
                   2493:   /* Set each timer value. */
                   2494:   ripng->update_time = update;
                   2495:   ripng->timeout_time = timeout;
                   2496:   ripng->garbage_time = garbage;
                   2497: 
                   2498:   /* Reset update timer thread. */
                   2499:   ripng_event (RIPNG_UPDATE_EVENT, 0);
                   2500: 
                   2501:   return CMD_SUCCESS;
                   2502: }
                   2503: 
                   2504: DEFUN (no_ripng_timers,
                   2505:        no_ripng_timers_cmd,
                   2506:        "no timers basic",
                   2507:        NO_STR
                   2508:        "RIPng timers setup\n"
                   2509:        "Basic timer\n")
                   2510: {
                   2511:   /* Set each timer value to the default. */
                   2512:   ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
                   2513:   ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
                   2514:   ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
                   2515: 
                   2516:   /* Reset update timer thread. */
                   2517:   ripng_event (RIPNG_UPDATE_EVENT, 0);
                   2518: 
                   2519:   return CMD_SUCCESS;
                   2520: }
                   2521: 
                   2522: ALIAS (no_ripng_timers,
                   2523:        no_ripng_timers_val_cmd,
                   2524:        "no timers basic <0-65535> <0-65535> <0-65535>",
                   2525:        NO_STR
                   2526:        "RIPng timers setup\n"
                   2527:        "Basic timer\n"
                   2528:        "Routing table update timer value in second. Default is 30.\n"
                   2529:        "Routing information timeout timer. Default is 180.\n"
                   2530:        "Garbage collection timer. Default is 120.\n")
                   2531: 
                   2532: DEFUN (show_ipv6_protocols, show_ipv6_protocols_cmd,
                   2533:        "show ipv6 protocols",
                   2534:        SHOW_STR
                   2535:        IPV6_STR
                   2536:        "Routing protocol information")
                   2537: {
                   2538:   if (! ripng)
                   2539:     return CMD_SUCCESS;
                   2540: 
                   2541:   vty_out (vty, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE);
                   2542:   
                   2543:   vty_out (vty, "Sending updates every %ld seconds, next due in %d seconds%s",
                   2544:           ripng->update_time, 0,
                   2545:           VTY_NEWLINE);
                   2546: 
                   2547:   vty_out (vty, "Timerout after %ld seconds, garbage correct %ld%s",
                   2548:           ripng->timeout_time,
                   2549:           ripng->garbage_time,
                   2550:           VTY_NEWLINE);
                   2551: 
                   2552:   vty_out (vty, "Outgoing update filter list for all interfaces is not set");
                   2553:   vty_out (vty, "Incoming update filter list for all interfaces is not set");
                   2554: 
                   2555:   return CMD_SUCCESS;
                   2556: }
                   2557: 
                   2558: /* Please be carefull to use this command. */
                   2559: DEFUN (ripng_default_information_originate,
                   2560:        ripng_default_information_originate_cmd,
                   2561:        "default-information originate",
                   2562:        "Default route information\n"
                   2563:        "Distribute default route\n")
                   2564: {
                   2565:   struct prefix_ipv6 p;
                   2566: 
                   2567:   if (! ripng ->default_information) {
                   2568:     ripng->default_information = 1;
                   2569: 
                   2570:     str2prefix_ipv6 ("::/0", &p);
                   2571:     ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL);
                   2572:   }
                   2573: 
                   2574:   return CMD_SUCCESS;
                   2575: }
                   2576: 
                   2577: DEFUN (no_ripng_default_information_originate,
                   2578:        no_ripng_default_information_originate_cmd,
                   2579:        "no default-information originate",
                   2580:        NO_STR
                   2581:        "Default route information\n"
                   2582:        "Distribute default route\n")
                   2583: {
                   2584:   struct prefix_ipv6 p;
                   2585: 
                   2586:   if (ripng->default_information) {
                   2587:     ripng->default_information = 0;
                   2588: 
                   2589:     str2prefix_ipv6 ("::/0", &p);
                   2590:     ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0);
                   2591:   }
                   2592: 
                   2593:   return CMD_SUCCESS;
                   2594: }
                   2595: 
                   2596: /* RIPng configuration write function. */
                   2597: static int
                   2598: ripng_config_write (struct vty *vty)
                   2599: {
                   2600:   int ripng_network_write (struct vty *, int);
                   2601:   void ripng_redistribute_write (struct vty *, int);
                   2602:   int write = 0;
                   2603:   struct route_node *rp;
                   2604: 
                   2605:   if (ripng)
                   2606:     {
                   2607: 
                   2608:       /* RIPng router. */
                   2609:       vty_out (vty, "router ripng%s", VTY_NEWLINE);
                   2610: 
                   2611:       if (ripng->default_information)
                   2612:        vty_out (vty, " default-information originate%s", VTY_NEWLINE);
                   2613: 
                   2614:       ripng_network_write (vty, 1);
                   2615: 
                   2616:       /* RIPng default metric configuration */
                   2617:       if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT)
                   2618:         vty_out (vty, " default-metric %d%s",
                   2619:                 ripng->default_metric, VTY_NEWLINE);
                   2620: 
                   2621:       ripng_redistribute_write (vty, 1);
                   2622: 
                   2623:       /* RIP offset-list configuration. */
                   2624:       config_write_ripng_offset_list (vty);
                   2625:       
                   2626:       /* RIPng aggregate routes. */
                   2627:       for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
                   2628:        if (rp->info != NULL)
                   2629:          vty_out (vty, " aggregate-address %s/%d%s", 
                   2630:                   inet6_ntoa (rp->p.u.prefix6),
                   2631:                   rp->p.prefixlen, 
                   2632: 
                   2633:                   VTY_NEWLINE);
                   2634: 
                   2635:       /* RIPng static routes. */
                   2636:       for (rp = route_top (ripng->route); rp; rp = route_next (rp))
                   2637:        if (rp->info != NULL)
                   2638:          vty_out (vty, " route %s/%d%s", inet6_ntoa (rp->p.u.prefix6),
                   2639:                   rp->p.prefixlen,
                   2640:                   VTY_NEWLINE);
                   2641: 
                   2642:       /* RIPng timers configuration. */
                   2643:       if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT ||
                   2644:          ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT ||
                   2645:          ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
                   2646:        {
                   2647:          vty_out (vty, " timers basic %ld %ld %ld%s",
                   2648:                   ripng->update_time,
                   2649:                   ripng->timeout_time,
                   2650:                   ripng->garbage_time,
                   2651:                   VTY_NEWLINE);
                   2652:        }
                   2653: #if 0
                   2654:       if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT)
                   2655:        vty_out (vty, " update-timer %d%s", ripng->update_time,
                   2656:                 VTY_NEWLINE);
                   2657:       if (ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT)
                   2658:        vty_out (vty, " timeout-timer %d%s", ripng->timeout_time,
                   2659:                 VTY_NEWLINE);
                   2660:       if (ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
                   2661:        vty_out (vty, " garbage-timer %d%s", ripng->garbage_time,
                   2662:                 VTY_NEWLINE);
                   2663: #endif /* 0 */
                   2664: 
                   2665:       write += config_write_distribute (vty);
                   2666: 
                   2667:       write += config_write_if_rmap (vty);
                   2668: 
                   2669:       write++;
                   2670:     }
                   2671:   return write;
                   2672: }
                   2673: 
                   2674: /* RIPng node structure. */
                   2675: static struct cmd_node cmd_ripng_node =
                   2676: {
                   2677:   RIPNG_NODE,
                   2678:   "%s(config-router)# ",
                   2679:   1,
                   2680: };
                   2681: 
                   2682: static void
                   2683: ripng_distribute_update (struct distribute *dist)
                   2684: {
                   2685:   struct interface *ifp;
                   2686:   struct ripng_interface *ri;
                   2687:   struct access_list *alist;
                   2688:   struct prefix_list *plist;
                   2689: 
                   2690:   if (! dist->ifname)
                   2691:     return;
                   2692: 
                   2693:   ifp = if_lookup_by_name (dist->ifname);
                   2694:   if (ifp == NULL)
                   2695:     return;
                   2696: 
                   2697:   ri = ifp->info;
                   2698: 
                   2699:   if (dist->list[DISTRIBUTE_IN])
                   2700:     {
                   2701:       alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
                   2702:       if (alist)
                   2703:        ri->list[RIPNG_FILTER_IN] = alist;
                   2704:       else
                   2705:        ri->list[RIPNG_FILTER_IN] = NULL;
                   2706:     }
                   2707:   else
                   2708:     ri->list[RIPNG_FILTER_IN] = NULL;
                   2709: 
                   2710:   if (dist->list[DISTRIBUTE_OUT])
                   2711:     {
                   2712:       alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
                   2713:       if (alist)
                   2714:        ri->list[RIPNG_FILTER_OUT] = alist;
                   2715:       else
                   2716:        ri->list[RIPNG_FILTER_OUT] = NULL;
                   2717:     }
                   2718:   else
                   2719:     ri->list[RIPNG_FILTER_OUT] = NULL;
                   2720: 
                   2721:   if (dist->prefix[DISTRIBUTE_IN])
                   2722:     {
                   2723:       plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
                   2724:       if (plist)
                   2725:        ri->prefix[RIPNG_FILTER_IN] = plist;
                   2726:       else
                   2727:        ri->prefix[RIPNG_FILTER_IN] = NULL;
                   2728:     }
                   2729:   else
                   2730:     ri->prefix[RIPNG_FILTER_IN] = NULL;
                   2731: 
                   2732:   if (dist->prefix[DISTRIBUTE_OUT])
                   2733:     {
                   2734:       plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
                   2735:       if (plist)
                   2736:        ri->prefix[RIPNG_FILTER_OUT] = plist;
                   2737:       else
                   2738:        ri->prefix[RIPNG_FILTER_OUT] = NULL;
                   2739:     }
                   2740:   else
                   2741:     ri->prefix[RIPNG_FILTER_OUT] = NULL;
                   2742: }
                   2743: 
                   2744: void
                   2745: ripng_distribute_update_interface (struct interface *ifp)
                   2746: {
                   2747:   struct distribute *dist;
                   2748: 
                   2749:   dist = distribute_lookup (ifp->name);
                   2750:   if (dist)
                   2751:     ripng_distribute_update (dist);
                   2752: }
                   2753: 
                   2754: /* Update all interface's distribute list. */
                   2755: static void
                   2756: ripng_distribute_update_all (struct prefix_list *notused)
                   2757: {
                   2758:   struct interface *ifp;
                   2759:   struct listnode *node;
                   2760: 
                   2761:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                   2762:     ripng_distribute_update_interface (ifp);
                   2763: }
                   2764: 
                   2765: static void
                   2766: ripng_distribute_update_all_wrapper (struct access_list *notused)
                   2767: {
                   2768:   ripng_distribute_update_all(NULL);
                   2769: }
                   2770: 
                   2771: /* delete all the added ripng routes. */
                   2772: void
                   2773: ripng_clean()
                   2774: {
                   2775:   int i;
                   2776:   struct route_node *rp;
                   2777:   struct ripng_info *rinfo;
                   2778: 
                   2779:   if (ripng) {
                   2780:     /* Clear RIPng routes */
                   2781:     for (rp = route_top (ripng->table); rp; rp = route_next (rp)) {
                   2782:       if ((rinfo = rp->info) != NULL) {
                   2783:         if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
                   2784:             (rinfo->sub_type == RIPNG_ROUTE_RTE))
                   2785:           ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p,
                   2786:                                    &rinfo->nexthop, rinfo->metric);
                   2787: 
                   2788:         RIPNG_TIMER_OFF (rinfo->t_timeout);
                   2789:         RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
                   2790: 
                   2791:         rp->info = NULL;
                   2792:         route_unlock_node (rp);
                   2793: 
                   2794:         ripng_info_free(rinfo);
                   2795:       }
                   2796:     }
                   2797: 
                   2798:     /* Cancel the RIPng timers */
                   2799:     RIPNG_TIMER_OFF (ripng->t_update);
                   2800:     RIPNG_TIMER_OFF (ripng->t_triggered_update);
                   2801:     RIPNG_TIMER_OFF (ripng->t_triggered_interval);
                   2802: 
                   2803:     /* Cancel the read thread */
                   2804:     if (ripng->t_read) {
                   2805:       thread_cancel (ripng->t_read);
                   2806:       ripng->t_read = NULL;
                   2807:     }
                   2808: 
                   2809:     /* Close the RIPng socket */
                   2810:     if (ripng->sock >= 0) {
                   2811:       close(ripng->sock);
                   2812:       ripng->sock = -1;
                   2813:     }
                   2814: 
                   2815:     /* Static RIPng route configuration. */
                   2816:     for (rp = route_top (ripng->route); rp; rp = route_next (rp))
                   2817:       if (rp->info) {
                   2818:         rp->info = NULL;
                   2819:         route_unlock_node (rp);
                   2820:     }
                   2821: 
                   2822:     /* RIPng aggregated prefixes */
                   2823:     for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
                   2824:       if (rp->info) {
                   2825:           rp->info = NULL;
                   2826:           route_unlock_node (rp);
                   2827:     }
                   2828: 
                   2829:     for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
                   2830:       if (ripng->route_map[i].name)
                   2831:         free (ripng->route_map[i].name);
                   2832: 
                   2833:     XFREE (MTYPE_ROUTE_TABLE, ripng->table);
                   2834:     XFREE (MTYPE_ROUTE_TABLE, ripng->route);
                   2835:     XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate);
                   2836: 
                   2837:     XFREE (MTYPE_RIPNG, ripng);
                   2838:     ripng = NULL;
                   2839:   } /* if (ripng) */
                   2840: 
                   2841:   ripng_clean_network();
                   2842:   ripng_passive_interface_clean ();
                   2843:   ripng_offset_clean ();
                   2844:   ripng_interface_clean ();
                   2845:   ripng_redistribute_clean ();
                   2846: }
                   2847: 
                   2848: /* Reset all values to the default settings. */
                   2849: void
                   2850: ripng_reset ()
                   2851: {
                   2852:   /* Call ripd related reset functions. */
                   2853:   ripng_debug_reset ();
                   2854:   ripng_route_map_reset ();
                   2855: 
                   2856:   /* Call library reset functions. */
                   2857:   vty_reset ();
                   2858:   access_list_reset ();
                   2859:   prefix_list_reset ();
                   2860: 
                   2861:   distribute_list_reset ();
                   2862: 
                   2863:   ripng_interface_reset ();
                   2864: 
                   2865:   ripng_zclient_reset ();
                   2866: }
                   2867: 
                   2868: static void
                   2869: ripng_if_rmap_update (struct if_rmap *if_rmap)
                   2870: {
                   2871:   struct interface *ifp;
                   2872:   struct ripng_interface *ri;
                   2873:   struct route_map *rmap;
                   2874: 
                   2875:   ifp = if_lookup_by_name (if_rmap->ifname);
                   2876:   if (ifp == NULL)
                   2877:     return;
                   2878: 
                   2879:   ri = ifp->info;
                   2880: 
                   2881:   if (if_rmap->routemap[IF_RMAP_IN])
                   2882:     {
                   2883:       rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
                   2884:       if (rmap)
                   2885:        ri->routemap[IF_RMAP_IN] = rmap;
                   2886:       else
                   2887:        ri->routemap[IF_RMAP_IN] = NULL;
                   2888:     }
                   2889:   else
                   2890:     ri->routemap[RIPNG_FILTER_IN] = NULL;
                   2891: 
                   2892:   if (if_rmap->routemap[IF_RMAP_OUT])
                   2893:     {
                   2894:       rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
                   2895:       if (rmap)
                   2896:        ri->routemap[IF_RMAP_OUT] = rmap;
                   2897:       else
                   2898:        ri->routemap[IF_RMAP_OUT] = NULL;
                   2899:     }
                   2900:   else
                   2901:     ri->routemap[RIPNG_FILTER_OUT] = NULL;
                   2902: }
                   2903: 
                   2904: void
                   2905: ripng_if_rmap_update_interface (struct interface *ifp)
                   2906: {
                   2907:   struct if_rmap *if_rmap;
                   2908: 
                   2909:   if_rmap = if_rmap_lookup (ifp->name);
                   2910:   if (if_rmap)
                   2911:     ripng_if_rmap_update (if_rmap);
                   2912: }
                   2913: 
                   2914: static void
                   2915: ripng_routemap_update_redistribute (void)
                   2916: {
                   2917:   int i;
                   2918: 
                   2919:   if (ripng)
                   2920:     {
                   2921:       for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 
                   2922:        {
                   2923:          if (ripng->route_map[i].name)
                   2924:            ripng->route_map[i].map = 
                   2925:              route_map_lookup_by_name (ripng->route_map[i].name);
                   2926:        }
                   2927:     }
                   2928: }
                   2929: 
                   2930: static void
                   2931: ripng_routemap_update (const char *unused)
                   2932: {
                   2933:   struct interface *ifp;
                   2934:   struct listnode *node;
                   2935: 
                   2936:   for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                   2937:     ripng_if_rmap_update_interface (ifp);
                   2938: 
                   2939:   ripng_routemap_update_redistribute ();
                   2940: }
                   2941: 
                   2942: /* Initialize ripng structure and set commands. */
                   2943: void
                   2944: ripng_init ()
                   2945: {
                   2946:   /* Randomize. */
                   2947:   srand (time (NULL));
                   2948: 
                   2949:   /* Install RIPNG_NODE. */
                   2950:   install_node (&cmd_ripng_node, ripng_config_write);
                   2951: 
                   2952:   /* Install ripng commands. */
                   2953:   install_element (VIEW_NODE, &show_ipv6_ripng_cmd);
                   2954:   install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd);
                   2955: 
                   2956:   install_element (ENABLE_NODE, &show_ipv6_ripng_cmd);
                   2957:   install_element (ENABLE_NODE, &show_ipv6_ripng_status_cmd);
                   2958: 
                   2959:   install_element (CONFIG_NODE, &router_ripng_cmd);
                   2960:   install_element (CONFIG_NODE, &no_router_ripng_cmd);
                   2961: 
                   2962:   install_default (RIPNG_NODE);
                   2963:   install_element (RIPNG_NODE, &ripng_route_cmd);
                   2964:   install_element (RIPNG_NODE, &no_ripng_route_cmd);
                   2965:   install_element (RIPNG_NODE, &ripng_aggregate_address_cmd);
                   2966:   install_element (RIPNG_NODE, &no_ripng_aggregate_address_cmd);
                   2967: 
                   2968:   install_element (RIPNG_NODE, &ripng_default_metric_cmd);
                   2969:   install_element (RIPNG_NODE, &no_ripng_default_metric_cmd);
                   2970:   install_element (RIPNG_NODE, &no_ripng_default_metric_val_cmd);
                   2971: 
                   2972:   install_element (RIPNG_NODE, &ripng_timers_cmd);
                   2973:   install_element (RIPNG_NODE, &no_ripng_timers_cmd);
                   2974:   install_element (RIPNG_NODE, &no_ripng_timers_val_cmd);
                   2975: #if 0
                   2976:   install_element (RIPNG_NODE, &ripng_update_timer_cmd);
                   2977:   install_element (RIPNG_NODE, &no_ripng_update_timer_cmd);
                   2978:   install_element (RIPNG_NODE, &ripng_timeout_timer_cmd);
                   2979:   install_element (RIPNG_NODE, &no_ripng_timeout_timer_cmd);
                   2980:   install_element (RIPNG_NODE, &ripng_garbage_timer_cmd);
                   2981:   install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd);
                   2982: #endif /* 0 */
                   2983: 
                   2984:   install_element (RIPNG_NODE, &ripng_default_information_originate_cmd);
                   2985:   install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd);
                   2986: 
                   2987:   ripng_if_init ();
                   2988:   ripng_debug_init ();
                   2989: 
                   2990:   /* Access list install. */
                   2991:   access_list_init ();
                   2992:   access_list_add_hook (ripng_distribute_update_all_wrapper);
                   2993:   access_list_delete_hook (ripng_distribute_update_all_wrapper);
                   2994: 
                   2995:   /* Prefix list initialize.*/
                   2996:   prefix_list_init ();
                   2997:   prefix_list_add_hook (ripng_distribute_update_all);
                   2998:   prefix_list_delete_hook (ripng_distribute_update_all);
                   2999: 
                   3000:   /* Distribute list install. */
                   3001:   distribute_list_init (RIPNG_NODE);
                   3002:   distribute_list_add_hook (ripng_distribute_update);
                   3003:   distribute_list_delete_hook (ripng_distribute_update);
                   3004: 
                   3005:   /* Route-map for interface. */
                   3006:   ripng_route_map_init ();
                   3007:   ripng_offset_init ();
                   3008: 
                   3009:   route_map_add_hook (ripng_routemap_update);
                   3010:   route_map_delete_hook (ripng_routemap_update);
                   3011: 
                   3012:   if_rmap_init (RIPNG_NODE);
                   3013:   if_rmap_hook_add (ripng_if_rmap_update);
                   3014:   if_rmap_hook_delete (ripng_if_rmap_update);
                   3015: }

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