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

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