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