File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ripngd / ripngd.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:12 2016 UTC (8 years ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

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