File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ripngd / ripngd.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:29 2012 UTC (11 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, HEAD
quagga

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

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