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

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

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