2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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
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.
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
34 #include "distribute.h"
40 #include "ripngd/ripngd.h"
41 #include "ripngd/ripng_route.h"
42 #include "ripngd/ripng_debug.h"
43 #include "ripngd/ripng_nexthop.h"
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;
56 extern struct zebra_privs_t ripngd_privs;
60 ripng_output_process (struct interface *, struct sockaddr_in6 *, int);
63 ripng_triggered_update (struct thread *);
65 /* RIPng next hop specification. */
68 enum ripng_nexthop_type
73 struct in6_addr address;
77 ripng_route_rte (struct ripng_info *rinfo)
79 return (rinfo->type == ZEBRA_ROUTE_RIPNG && rinfo->sub_type == RIPNG_ROUTE_RTE);
82 /* Allocate new ripng information. */
86 struct ripng_info *new;
88 new = XCALLOC (MTYPE_RIPNG_ROUTE, sizeof (struct ripng_info));
92 /* Free ripng information. */
94 ripng_info_free (struct ripng_info *rinfo)
96 XFREE (MTYPE_RIPNG_ROUTE, rinfo);
99 /* Create ripng socket. */
101 ripng_make_socket (void)
105 struct sockaddr_in6 ripaddr;
107 sock = socket (AF_INET6, SOCK_DGRAM, 0);
110 zlog (NULL, LOG_ERR, "Can't make ripng socket");
114 ret = setsockopt_so_recvbuf (sock, 8096);
117 ret = setsockopt_ipv6_pktinfo (sock, 1);
120 #ifdef IPTOS_PREC_INTERNETCONTROL
121 ret = setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL);
125 ret = setsockopt_ipv6_multicast_hops (sock, 255);
128 ret = setsockopt_ipv6_multicast_loop (sock, 0);
131 ret = setsockopt_ipv6_hoplimit (sock, 1);
135 memset (&ripaddr, 0, sizeof (ripaddr));
136 ripaddr.sin6_family = AF_INET6;
138 ripaddr.sin6_len = sizeof (struct sockaddr_in6);
139 #endif /* SIN6_LEN */
140 ripaddr.sin6_port = htons (RIPNG_PORT_DEFAULT);
142 if (ripngd_privs.change (ZPRIVS_RAISE))
143 zlog_err ("ripng_make_socket: could not raise privs");
145 ret = bind (sock, (struct sockaddr *) &ripaddr, sizeof (ripaddr));
148 zlog (NULL, LOG_ERR, "Can't bind ripng socket: %s.", safe_strerror (errno));
149 if (ripngd_privs.change (ZPRIVS_LOWER))
150 zlog_err ("ripng_make_socket: could not lower privs");
153 if (ripngd_privs.change (ZPRIVS_LOWER))
154 zlog_err ("ripng_make_socket: could not lower privs");
158 /* Send RIPng packet. */
160 ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to,
161 struct interface *ifp)
166 struct cmsghdr *cmsgptr;
168 struct in6_pktinfo *pkt;
169 struct sockaddr_in6 addr;
171 if (IS_RIPNG_DEBUG_SEND) {
173 zlog_debug ("send to %s", inet6_ntoa (to->sin6_addr));
174 zlog_debug (" send interface %s", ifp->name);
175 zlog_debug (" send packet size %d", bufsize);
178 memset (&addr, 0, sizeof (struct sockaddr_in6));
179 addr.sin6_family = AF_INET6;
181 addr.sin6_len = sizeof (struct sockaddr_in6);
182 #endif /* SIN6_LEN */
183 addr.sin6_flowinfo = htonl (RIPNG_PRIORITY_DEFAULT);
185 /* When destination is specified. */
188 addr.sin6_addr = to->sin6_addr;
189 addr.sin6_port = to->sin6_port;
193 inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr);
194 addr.sin6_port = htons (RIPNG_PORT_DEFAULT);
197 msg.msg_name = (void *) &addr;
198 msg.msg_namelen = sizeof (struct sockaddr_in6);
201 msg.msg_control = (void *) adata;
202 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
205 iov.iov_len = bufsize;
207 cmsgptr = (struct cmsghdr *)adata;
208 cmsgptr->cmsg_len = CMSG_LEN(sizeof (struct in6_pktinfo));
209 cmsgptr->cmsg_level = IPPROTO_IPV6;
210 cmsgptr->cmsg_type = IPV6_PKTINFO;
212 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
213 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
214 pkt->ipi6_ifindex = ifp->ifindex;
216 ret = sendmsg (ripng->sock, &msg, 0);
220 zlog_err ("RIPng send fail on %s to %s: %s", ifp->name,
221 inet6_ntoa (to->sin6_addr), safe_strerror (errno));
223 zlog_err ("RIPng send fail on %s: %s", ifp->name, safe_strerror (errno));
229 /* Receive UDP RIPng packet from socket. */
231 ripng_recv_packet (int sock, u_char *buf, int bufsize,
232 struct sockaddr_in6 *from, ifindex_t *ifindex,
238 struct cmsghdr *cmsgptr;
239 struct in6_addr dst = { .s6_addr = { 0 } };
241 /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this
242 point I can't determine size of cmsghdr */
245 /* Fill in message and iovec. */
246 msg.msg_name = (void *) from;
247 msg.msg_namelen = sizeof (struct sockaddr_in6);
250 msg.msg_control = (void *) adata;
251 msg.msg_controllen = sizeof adata;
253 iov.iov_len = bufsize;
255 /* If recvmsg fail return minus value. */
256 ret = recvmsg (sock, &msg, 0);
260 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
261 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
263 /* I want interface index which this packet comes from. */
264 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
265 cmsgptr->cmsg_type == IPV6_PKTINFO)
267 struct in6_pktinfo *ptr;
269 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
270 *ifindex = ptr->ipi6_ifindex;
271 dst = ptr->ipi6_addr;
274 zlog_warn ("Interface index returned by IPV6_PKTINFO is zero");
277 /* Incoming packet's multicast hop limit. */
278 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
279 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
281 int *phoplimit = (int *) CMSG_DATA (cmsgptr);
282 *hoplimit = *phoplimit;
286 /* Hoplimit check shold be done when destination address is
287 multicast address. */
288 if (! IN6_IS_ADDR_MULTICAST (&dst))
294 /* Dump rip packet */
296 ripng_packet_dump (struct ripng_packet *packet, int size, const char *sndrcv)
300 const char *command_str;
302 /* Set command string. */
303 if (packet->command == RIPNG_REQUEST)
304 command_str = "request";
305 else if (packet->command == RIPNG_RESPONSE)
306 command_str = "response";
308 command_str = "unknown";
310 /* Dump packet header. */
311 zlog_debug ("%s %s version %d packet size %d",
312 sndrcv, command_str, packet->version, size);
314 /* Dump each routing table entry. */
317 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
319 if (rte->metric == RIPNG_METRIC_NEXTHOP)
320 zlog_debug (" nexthop %s/%d", inet6_ntoa (rte->addr), rte->prefixlen);
322 zlog_debug (" %s/%d metric %d tag %d",
323 inet6_ntoa (rte->addr), rte->prefixlen,
324 rte->metric, ntohs (rte->tag));
328 /* RIPng next hop address RTE (Route Table Entry). */
330 ripng_nexthop_rte (struct rte *rte,
331 struct sockaddr_in6 *from,
332 struct ripng_nexthop *nexthop)
334 char buf[INET6_BUFSIZ];
336 /* Logging before checking RTE. */
337 if (IS_RIPNG_DEBUG_RECV)
338 zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d",
339 inet6_ntoa (rte->addr), ntohs (rte->tag), rte->prefixlen);
341 /* RFC2080 2.1.1 Next Hop:
342 The route tag and prefix length in the next hop RTE must be
343 set to zero on sending and ignored on receiption. */
344 if (ntohs (rte->tag) != 0)
345 zlog_warn ("RIPng nexthop RTE with non zero tag value %d from %s",
346 ntohs (rte->tag), inet6_ntoa (from->sin6_addr));
348 if (rte->prefixlen != 0)
349 zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
350 rte->prefixlen, inet6_ntoa (from->sin6_addr));
352 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
353 next hop RTE indicates that the next hop address should be the
354 originator of the RIPng advertisement. An address specified as a
355 next hop must be a link-local address. */
356 if (IN6_IS_ADDR_UNSPECIFIED (&rte->addr))
358 nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
359 memset (&nexthop->address, 0, sizeof (struct in6_addr));
363 if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
365 nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
366 IPV6_ADDR_COPY (&nexthop->address, &rte->addr);
370 /* The purpose of the next hop RTE is to eliminate packets being
371 routed through extra hops in the system. It is particularly useful
372 when RIPng is not being run on all of the routers on a network.
373 Note that next hop RTE is "advisory". That is, if the provided
374 information is ignored, a possibly sub-optimal, but absolutely
375 valid, route may be taken. If the received next hop address is not
376 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
377 zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s",
378 inet6_ntoa (rte->addr),
379 inet_ntop (AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ));
381 nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
382 memset (&nexthop->address, 0, sizeof (struct in6_addr));
387 /* If ifp has same link-local address then return 1. */
389 ripng_lladdr_check (struct interface *ifp, struct in6_addr *addr)
391 struct listnode *node;
392 struct connected *connected;
395 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
397 p = connected->address;
399 if (p->family == AF_INET6 &&
400 IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6) &&
401 IN6_ARE_ADDR_EQUAL (&p->u.prefix6, addr))
407 /* RIPng route garbage collect timer. */
409 ripng_garbage_collect (struct thread *t)
411 struct ripng_info *rinfo;
412 struct route_node *rp;
414 rinfo = THREAD_ARG (t);
415 rinfo->t_garbage_collect = NULL;
417 /* Off timeout timer. */
418 RIPNG_TIMER_OFF (rinfo->t_timeout);
420 /* Get route_node pointer. */
423 /* Unlock route_node. */
424 listnode_delete (rp->info, rinfo);
425 if (list_isempty ((struct list *)rp->info))
427 list_free (rp->info);
429 route_unlock_node (rp);
432 /* Free RIPng routing information. */
433 ripng_info_free (rinfo);
438 static void ripng_timeout_update (struct ripng_info *rinfo);
440 /* Add new route to the ECMP list.
441 * RETURN: the new entry added in the list, or NULL if it is not the first
442 * entry and ECMP is not allowed.
445 ripng_ecmp_add (struct ripng_info *rinfo_new)
447 struct route_node *rp = rinfo_new->rp;
448 struct ripng_info *rinfo = NULL;
449 struct list *list = NULL;
451 if (rp->info == NULL)
452 rp->info = list_new ();
453 list = (struct list *)rp->info;
455 /* If ECMP is not allowed and some entry already exists in the list,
457 if (listcount (list) && !ripng->ecmp)
460 rinfo = ripng_info_new ();
461 memcpy (rinfo, rinfo_new, sizeof (struct ripng_info));
462 listnode_add (list, rinfo);
464 if (ripng_route_rte (rinfo))
466 ripng_timeout_update (rinfo);
467 ripng_zebra_ipv6_add (rp);
470 ripng_aggregate_increment (rp, rinfo);
472 /* Set the route change flag on the first entry. */
473 rinfo = listgetdata (listhead (list));
474 SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED);
476 /* Signal the output process to trigger an update. */
477 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
482 /* Replace the ECMP list with the new route.
483 * RETURN: the new entry added in the list
486 ripng_ecmp_replace (struct ripng_info *rinfo_new)
488 struct route_node *rp = rinfo_new->rp;
489 struct list *list = (struct list *)rp->info;
490 struct ripng_info *rinfo = NULL, *tmp_rinfo = NULL;
491 struct listnode *node = NULL, *nextnode = NULL;
493 if (list == NULL || listcount (list) == 0)
494 return ripng_ecmp_add (rinfo_new);
496 /* Get the first entry */
497 rinfo = listgetdata (listhead (list));
499 /* Learnt route replaced by a local one. Delete it from zebra. */
500 if (ripng_route_rte (rinfo) && !ripng_route_rte (rinfo_new))
501 if (CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB))
502 ripng_zebra_ipv6_delete (rp);
504 if (rinfo->metric != RIPNG_METRIC_INFINITY)
505 ripng_aggregate_decrement_list (rp, list);
507 /* Re-use the first entry, and delete the others. */
508 for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo))
509 if (tmp_rinfo != rinfo)
511 RIPNG_TIMER_OFF (tmp_rinfo->t_timeout);
512 RIPNG_TIMER_OFF (tmp_rinfo->t_garbage_collect);
513 list_delete_node (list, node);
514 ripng_info_free (tmp_rinfo);
517 RIPNG_TIMER_OFF (rinfo->t_timeout);
518 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
519 memcpy (rinfo, rinfo_new, sizeof (struct ripng_info));
521 if (ripng_route_rte (rinfo))
523 ripng_timeout_update (rinfo);
524 /* The ADD message implies an update. */
525 ripng_zebra_ipv6_add (rp);
528 ripng_aggregate_increment (rp, rinfo);
530 /* Set the route change flag. */
531 SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED);
533 /* Signal the output process to trigger an update. */
534 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
539 /* Delete one route from the ECMP list.
541 * null - the entry is freed, and other entries exist in the list
542 * the entry - the entry is the last one in the list; its metric is set
543 * to INFINITY, and the garbage collector is started for it
546 ripng_ecmp_delete (struct ripng_info *rinfo)
548 struct route_node *rp = rinfo->rp;
549 struct list *list = (struct list *)rp->info;
551 RIPNG_TIMER_OFF (rinfo->t_timeout);
553 if (rinfo->metric != RIPNG_METRIC_INFINITY)
554 ripng_aggregate_decrement (rp, rinfo);
556 if (listcount (list) > 1)
558 /* Some other ECMP entries still exist. Just delete this entry. */
559 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
560 listnode_delete (list, rinfo);
561 if (ripng_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB))
562 /* The ADD message implies the update. */
563 ripng_zebra_ipv6_add (rp);
564 ripng_info_free (rinfo);
569 assert (rinfo == listgetdata (listhead (list)));
571 /* This is the only entry left in the list. We must keep it in
572 * the list for garbage collection time, with INFINITY metric. */
574 rinfo->metric = RIPNG_METRIC_INFINITY;
575 RIPNG_TIMER_ON (rinfo->t_garbage_collect,
576 ripng_garbage_collect, ripng->garbage_time);
578 if (ripng_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB))
579 ripng_zebra_ipv6_delete (rp);
582 /* Set the route change flag on the first entry. */
583 rinfo = listgetdata (listhead (list));
584 SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED);
586 /* Signal the output process to trigger an update. */
587 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
592 /* Timeout RIPng routes. */
594 ripng_timeout (struct thread *t)
596 ripng_ecmp_delete ((struct ripng_info *)THREAD_ARG (t));
601 ripng_timeout_update (struct ripng_info *rinfo)
603 if (rinfo->metric != RIPNG_METRIC_INFINITY)
605 RIPNG_TIMER_OFF (rinfo->t_timeout);
606 RIPNG_TIMER_ON (rinfo->t_timeout, ripng_timeout, ripng->timeout_time);
611 ripng_filter (int ripng_distribute, struct prefix_ipv6 *p,
612 struct ripng_interface *ri)
614 struct distribute *dist;
615 struct access_list *alist;
616 struct prefix_list *plist;
617 int distribute = ripng_distribute == RIPNG_FILTER_OUT ?
618 DISTRIBUTE_V6_OUT : DISTRIBUTE_V6_IN;
619 const char *inout = ripng_distribute == RIPNG_FILTER_OUT ? "out" : "in";
621 /* Input distribute-list filtering. */
622 if (ri->list[ripng_distribute])
624 if (access_list_apply (ri->list[ripng_distribute],
625 (struct prefix *) p) == FILTER_DENY)
627 if (IS_RIPNG_DEBUG_PACKET)
628 zlog_debug ("%s/%d filtered by distribute %s",
629 inet6_ntoa (p->prefix), p->prefixlen, inout);
633 if (ri->prefix[ripng_distribute])
635 if (prefix_list_apply (ri->prefix[ripng_distribute],
636 (struct prefix *) p) == PREFIX_DENY)
638 if (IS_RIPNG_DEBUG_PACKET)
639 zlog_debug ("%s/%d filtered by prefix-list %s",
640 inet6_ntoa (p->prefix), p->prefixlen, inout);
645 /* All interface filter check. */
646 dist = distribute_lookup (NULL);
649 if (dist->list[distribute])
651 alist = access_list_lookup (AFI_IP6, dist->list[distribute]);
655 if (access_list_apply (alist,
656 (struct prefix *) p) == FILTER_DENY)
658 if (IS_RIPNG_DEBUG_PACKET)
659 zlog_debug ("%s/%d filtered by distribute %s",
660 inet6_ntoa (p->prefix), p->prefixlen, inout);
665 if (dist->prefix[distribute])
667 plist = prefix_list_lookup (AFI_IP6, dist->prefix[distribute]);
671 if (prefix_list_apply (plist,
672 (struct prefix *) p) == PREFIX_DENY)
674 if (IS_RIPNG_DEBUG_PACKET)
675 zlog_debug ("%s/%d filtered by prefix-list %s",
676 inet6_ntoa (p->prefix), p->prefixlen, inout);
685 /* Process RIPng route according to RFC2080. */
687 ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
688 struct ripng_nexthop *ripng_nexthop,
689 struct interface *ifp)
692 struct prefix_ipv6 p;
693 struct route_node *rp;
694 struct ripng_info *rinfo = NULL, newinfo;
695 struct ripng_interface *ri;
696 struct in6_addr *nexthop;
698 struct list *list = NULL;
699 struct listnode *node = NULL;
701 /* Make prefix structure. */
702 memset (&p, 0, sizeof (struct prefix_ipv6));
704 /* p.prefix = rte->addr; */
705 IPV6_ADDR_COPY (&p.prefix, &rte->addr);
706 p.prefixlen = rte->prefixlen;
708 /* Make sure mask is applied. */
709 /* XXX We have to check the prefix is valid or not before call
711 apply_mask_ipv6 (&p);
713 /* Apply input filters. */
716 ret = ripng_filter (RIPNG_FILTER_IN, &p, ri);
720 memset (&newinfo, 0, sizeof (newinfo));
721 newinfo.type = ZEBRA_ROUTE_RIPNG;
722 newinfo.sub_type = RIPNG_ROUTE_RTE;
723 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
724 newinfo.nexthop = ripng_nexthop->address;
726 newinfo.nexthop = from->sin6_addr;
727 newinfo.from = from->sin6_addr;
728 newinfo.ifindex = ifp->ifindex;
729 newinfo.metric = rte->metric;
730 newinfo.metric_out = rte->metric; /* XXX */
731 newinfo.tag = ntohs (rte->tag); /* XXX */
734 if (ri->routemap[RIPNG_FILTER_IN])
738 ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN],
739 (struct prefix *)&p, RMAP_RIPNG, &newinfo);
741 if (ret == RMAP_DENYMATCH)
743 if (IS_RIPNG_DEBUG_PACKET)
744 zlog_debug ("RIPng %s/%d is filtered by route-map in",
745 inet6_ntoa (p.prefix), p.prefixlen);
749 /* Get back the object */
750 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) {
751 if (! IPV6_ADDR_SAME(&newinfo.nexthop, &ripng_nexthop->address) ) {
752 /* the nexthop get changed by the routemap */
753 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop))
754 ripng_nexthop->address = newinfo.nexthop;
756 ripng_nexthop->address = in6addr_any;
759 if (! IPV6_ADDR_SAME(&newinfo.nexthop, &from->sin6_addr) ) {
760 /* the nexthop get changed by the routemap */
761 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) {
762 ripng_nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
763 ripng_nexthop->address = newinfo.nexthop;
767 rte->tag = htons(newinfo.tag_out); /* XXX */
768 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
771 /* Once the entry has been validated, update the metric by
772 * adding the cost of the network on wich the message
773 * arrived. If the result is greater than infinity, use infinity
774 * (RFC2453 Sec. 3.9.2)
777 /* Zebra ripngd can handle offset-list in. */
778 ret = ripng_offset_list_apply_in (&p, ifp, &rte->metric);
780 /* If offset-list does not modify the metric use interface's
783 rte->metric += ifp->metric ? ifp->metric : 1;
785 if (rte->metric > RIPNG_METRIC_INFINITY)
786 rte->metric = RIPNG_METRIC_INFINITY;
788 /* Set nexthop pointer. */
789 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
790 nexthop = &ripng_nexthop->address;
792 nexthop = &from->sin6_addr;
794 /* Lookup RIPng routing table. */
795 rp = route_node_get (ripng->table, (struct prefix *) &p);
798 newinfo.nexthop = *nexthop;
799 newinfo.metric = rte->metric;
800 newinfo.tag = ntohs (rte->tag);
802 /* Check to see whether there is already RIPng route on the table. */
803 if ((list = rp->info) != NULL)
804 for (ALL_LIST_ELEMENTS_RO (list, node, rinfo))
806 /* Need to compare with redistributed entry or local entry */
807 if (!ripng_route_rte (rinfo))
810 if (IPV6_ADDR_SAME (&rinfo->from, &from->sin6_addr) &&
811 IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
814 if (!listnextnode (node))
816 /* Not found in the list */
818 if (rte->metric > rinfo->metric)
820 /* New route has a greater metric. Discard it. */
821 route_unlock_node (rp);
825 if (rte->metric < rinfo->metric)
826 /* New route has a smaller metric. Replace the ECMP list
827 * with the new one in below. */
830 /* Metrics are same. Keep "rinfo" null and the new route
831 * is added in the ECMP list in below. */
837 /* Redistributed route check. */
838 if (rinfo->type != ZEBRA_ROUTE_RIPNG
839 && rinfo->metric != RIPNG_METRIC_INFINITY)
841 route_unlock_node (rp);
845 /* Local static route. */
846 if (rinfo->type == ZEBRA_ROUTE_RIPNG
847 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
848 (rinfo->sub_type == RIPNG_ROUTE_DEFAULT))
849 && rinfo->metric != RIPNG_METRIC_INFINITY)
851 route_unlock_node (rp);
858 /* Now, check to see whether there is already an explicit route
859 for the destination prefix. If there is no such route, add
860 this route to the routing table, unless the metric is
861 infinity (there is no point in adding a route which
863 if (rte->metric != RIPNG_METRIC_INFINITY)
864 ripng_ecmp_add (&newinfo);
868 /* If there is an existing route, compare the next hop address
869 to the address of the router from which the datagram came.
870 If this datagram is from the same router as the existing
871 route, reinitialize the timeout. */
872 same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr)
873 && (rinfo->ifindex == ifp->ifindex));
875 /* Next, compare the metrics. If the datagram is from the same
876 router as the existing route, and the new metric is different
877 than the old one; or, if the new metric is lower than the old
878 one; do the following actions: */
879 if ((same && rinfo->metric != rte->metric) ||
880 rte->metric < rinfo->metric)
882 if (listcount (list) == 1)
884 if (newinfo.metric != RIPNG_METRIC_INFINITY)
885 ripng_ecmp_replace (&newinfo);
887 ripng_ecmp_delete (rinfo);
891 if (newinfo.metric < rinfo->metric)
892 ripng_ecmp_replace (&newinfo);
893 else /* newinfo.metric > rinfo->metric */
894 ripng_ecmp_delete (rinfo);
897 else /* same & no change */
898 ripng_timeout_update (rinfo);
900 /* Unlock tempolary lock of the route. */
901 route_unlock_node (rp);
905 /* Add redistributed route to RIPng table. */
907 ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p,
908 ifindex_t ifindex, struct in6_addr *nexthop,
911 struct route_node *rp;
912 struct ripng_info *rinfo = NULL, newinfo;
913 struct list *list = NULL;
915 /* Redistribute route */
916 if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
918 if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
921 rp = route_node_get (ripng->table, (struct prefix *) p);
923 memset (&newinfo, 0, sizeof (struct ripng_info));
925 newinfo.sub_type = sub_type;
926 newinfo.ifindex = ifindex;
928 if (tag <= UINT16_MAX) /* RIPng only supports 16 bit tags */
931 if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop))
932 newinfo.nexthop = *nexthop;
934 if ((list = rp->info) != NULL && listcount (list) != 0)
936 rinfo = listgetdata (listhead (list));
938 if (rinfo->type == ZEBRA_ROUTE_CONNECT
939 && rinfo->sub_type == RIPNG_ROUTE_INTERFACE
940 && rinfo->metric != RIPNG_METRIC_INFINITY) {
941 route_unlock_node (rp);
945 /* Manually configured RIPng route check.
946 * They have the precedence on all the other entries.
948 if (rinfo->type == ZEBRA_ROUTE_RIPNG
949 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
950 (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) ) {
951 if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) &&
952 (sub_type != RIPNG_ROUTE_DEFAULT))) {
953 route_unlock_node (rp);
958 rinfo = ripng_ecmp_replace (&newinfo);
959 route_unlock_node (rp);
962 rinfo = ripng_ecmp_add (&newinfo);
964 if (IS_RIPNG_DEBUG_EVENT) {
966 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
967 inet6_ntoa(p->prefix), p->prefixlen,
968 ifindex2ifname(ifindex));
970 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
971 inet6_ntoa(p->prefix), p->prefixlen, inet6_ntoa(*nexthop),
972 ifindex2ifname(ifindex));
975 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
978 /* Delete redistributed route to RIPng table. */
980 ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p,
983 struct route_node *rp;
984 struct ripng_info *rinfo;
986 if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
988 if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
991 rp = route_node_lookup (ripng->table, (struct prefix *) p);
995 struct list *list = rp->info;
997 if (list != NULL && listcount (list) != 0)
999 rinfo = listgetdata (listhead (list));
1001 && rinfo->type == type
1002 && rinfo->sub_type == sub_type
1003 && rinfo->ifindex == ifindex)
1005 /* Perform poisoned reverse. */
1006 rinfo->metric = RIPNG_METRIC_INFINITY;
1007 RIPNG_TIMER_ON (rinfo->t_garbage_collect,
1008 ripng_garbage_collect, ripng->garbage_time);
1009 RIPNG_TIMER_OFF (rinfo->t_timeout);
1011 /* Aggregate count decrement. */
1012 ripng_aggregate_decrement (rp, rinfo);
1014 rinfo->flags |= RIPNG_RTF_CHANGED;
1016 if (IS_RIPNG_DEBUG_EVENT)
1017 zlog_debug ("Poisone %s/%d on the interface %s with an "
1018 "infinity metric [delete]",
1019 inet6_ntoa (p->prefix), p->prefixlen,
1020 ifindex2ifname (ifindex));
1022 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
1025 route_unlock_node (rp);
1029 /* Withdraw redistributed route. */
1031 ripng_redistribute_withdraw (int type)
1033 struct route_node *rp;
1034 struct ripng_info *rinfo = NULL;
1035 struct list *list = NULL;
1040 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1041 if ((list = rp->info) != NULL)
1043 rinfo = listgetdata (listhead (list));
1044 if ((rinfo->type == type)
1045 && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE))
1047 /* Perform poisoned reverse. */
1048 rinfo->metric = RIPNG_METRIC_INFINITY;
1049 RIPNG_TIMER_ON (rinfo->t_garbage_collect,
1050 ripng_garbage_collect, ripng->garbage_time);
1051 RIPNG_TIMER_OFF (rinfo->t_timeout);
1053 /* Aggregate count decrement. */
1054 ripng_aggregate_decrement (rp, rinfo);
1056 rinfo->flags |= RIPNG_RTF_CHANGED;
1058 if (IS_RIPNG_DEBUG_EVENT) {
1059 struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p;
1061 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
1062 inet6_ntoa(p->prefix), p->prefixlen,
1063 ifindex2ifname(rinfo->ifindex));
1066 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
1071 /* RIP routing information. */
1073 ripng_response_process (struct ripng_packet *packet, int size,
1074 struct sockaddr_in6 *from, struct interface *ifp,
1079 struct ripng_nexthop nexthop;
1081 /* RFC2080 2.4.2 Response Messages:
1082 The Response must be ignored if it is not from the RIPng port. */
1083 if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT)
1085 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
1086 ntohs (from->sin6_port), inet6_ntoa (from->sin6_addr));
1087 ripng_peer_bad_packet (from);
1091 /* The datagram's IPv6 source address should be checked to see
1092 whether the datagram is from a valid neighbor; the source of the
1093 datagram must be a link-local address. */
1094 if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr))
1096 zlog_warn ("RIPng packet comes from non link local address %s",
1097 inet6_ntoa (from->sin6_addr));
1098 ripng_peer_bad_packet (from);
1102 /* It is also worth checking to see whether the response is from one
1103 of the router's own addresses. Interfaces on broadcast networks
1104 may receive copies of their own multicasts immediately. If a
1105 router processes its own output as new input, confusion is likely,
1106 and such datagrams must be ignored. */
1107 if (ripng_lladdr_check (ifp, &from->sin6_addr))
1109 zlog_warn ("RIPng packet comes from my own link local address %s",
1110 inet6_ntoa (from->sin6_addr));
1111 ripng_peer_bad_packet (from);
1115 /* As an additional check, periodic advertisements must have their
1116 hop counts set to 255, and inbound, multicast packets sent from the
1117 RIPng port (i.e. periodic advertisement or triggered update
1118 packets) must be examined to ensure that the hop count is 255. */
1119 if (hoplimit >= 0 && hoplimit != 255)
1121 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
1122 hoplimit, inet6_ntoa (from->sin6_addr));
1123 ripng_peer_bad_packet (from);
1127 /* Update RIPng peer. */
1128 ripng_peer_update (from, packet->version);
1130 /* Reset nexthop. */
1131 memset (&nexthop, 0, sizeof (struct ripng_nexthop));
1132 nexthop.flag = RIPNG_NEXTHOP_UNSPEC;
1134 /* Set RTE pointer. */
1137 for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++)
1139 /* First of all, we have to check this RTE is next hop RTE or
1140 not. Next hop RTE is completely different with normal RTE so
1141 we need special treatment. */
1142 if (rte->metric == RIPNG_METRIC_NEXTHOP)
1144 ripng_nexthop_rte (rte, from, &nexthop);
1148 /* RTE information validation. */
1150 /* - is the destination prefix valid (e.g., not a multicast
1151 prefix and not a link-local address) A link-local address
1152 should never be present in an RTE. */
1153 if (IN6_IS_ADDR_MULTICAST (&rte->addr))
1155 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
1156 inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
1157 ripng_peer_bad_route (from);
1160 if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
1162 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
1163 inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
1164 ripng_peer_bad_route (from);
1167 if (IN6_IS_ADDR_LOOPBACK (&rte->addr))
1169 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
1170 inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
1171 ripng_peer_bad_route (from);
1175 /* - is the prefix length valid (i.e., between 0 and 128,
1177 if (rte->prefixlen > 128)
1179 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
1180 inet6_ntoa (rte->addr), rte->prefixlen,
1181 inet6_ntoa (from->sin6_addr), ifp->name);
1182 ripng_peer_bad_route (from);
1186 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1187 if (! (rte->metric >= 1 && rte->metric <= 16))
1189 zlog_warn ("Invalid metric %d from %s%%%s", rte->metric,
1190 inet6_ntoa (from->sin6_addr), ifp->name);
1191 ripng_peer_bad_route (from);
1195 /* Vincent: XXX Should we compute the direclty reachable nexthop
1196 * for our RIPng network ?
1199 /* Routing table updates. */
1200 ripng_route_process (rte, from, &nexthop, ifp);
1204 /* Response to request message. */
1206 ripng_request_process (struct ripng_packet *packet,int size,
1207 struct sockaddr_in6 *from, struct interface *ifp)
1211 struct prefix_ipv6 p;
1212 struct route_node *rp;
1213 struct ripng_info *rinfo;
1214 struct ripng_interface *ri;
1216 /* Does not reponse to the requests on the loopback interfaces */
1217 if (if_is_loopback (ifp))
1220 /* Check RIPng process is enabled on this interface. */
1225 /* When passive interface is specified, suppress responses */
1229 /* RIPng peer update. */
1230 ripng_peer_update (from, packet->version);
1232 lim = ((caddr_t) packet) + size;
1235 /* The Request is processed entry by entry. If there are no
1236 entries, no response is given. */
1237 if (lim == (caddr_t) rte)
1240 /* There is one special case. If there is exactly one entry in the
1241 request, and it has a destination prefix of zero, a prefix length
1242 of zero, and a metric of infinity (i.e., 16), then this is a
1243 request to send the entire routing table. In that case, a call
1244 is made to the output process to send the routing table to the
1245 requesting address/port. */
1246 if (lim == ((caddr_t) (rte + 1)) &&
1247 IN6_IS_ADDR_UNSPECIFIED (&rte->addr) &&
1248 rte->prefixlen == 0 &&
1249 rte->metric == RIPNG_METRIC_INFINITY)
1251 /* All route with split horizon */
1252 ripng_output_process (ifp, from, ripng_all_route);
1256 /* Except for this special case, processing is quite simple.
1257 Examine the list of RTEs in the Request one by one. For each
1258 entry, look up the destination in the router's routing
1259 database and, if there is a route, put that route's metric in
1260 the metric field of the RTE. If there is no explicit route
1261 to the specified destination, put infinity in the metric
1262 field. Once all the entries have been filled in, change the
1263 command from Request to Response and send the datagram back
1264 to the requestor. */
1265 memset (&p, 0, sizeof (struct prefix_ipv6));
1266 p.family = AF_INET6;
1268 for (; ((caddr_t) rte) < lim; rte++)
1270 p.prefix = rte->addr;
1271 p.prefixlen = rte->prefixlen;
1272 apply_mask_ipv6 (&p);
1274 rp = route_node_lookup (ripng->table, (struct prefix *) &p);
1278 rinfo = listgetdata (listhead ((struct list *)rp->info));
1279 rte->metric = rinfo->metric;
1280 route_unlock_node (rp);
1283 rte->metric = RIPNG_METRIC_INFINITY;
1285 packet->command = RIPNG_RESPONSE;
1287 ripng_send_packet ((caddr_t) packet, size, from, ifp);
1291 /* First entry point of reading RIPng packet. */
1293 ripng_read (struct thread *thread)
1297 struct sockaddr_in6 from;
1298 struct ripng_packet *packet;
1299 ifindex_t ifindex = 0;
1300 struct interface *ifp;
1303 /* Check ripng is active and alive. */
1304 assert (ripng != NULL);
1305 assert (ripng->sock >= 0);
1307 /* Fetch thread data and set read pointer to empty for event
1308 managing. `sock' sould be same as ripng->sock. */
1309 sock = THREAD_FD (thread);
1310 ripng->t_read = NULL;
1312 /* Add myself to the next event. */
1313 ripng_event (RIPNG_READ, sock);
1315 /* Read RIPng packet. */
1316 len = ripng_recv_packet (sock, STREAM_DATA (ripng->ibuf),
1317 STREAM_SIZE (ripng->ibuf), &from, &ifindex,
1321 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno));
1325 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1326 (4)) must be multiple size of one RTE size (20). */
1327 if (((len - 4) % 20) != 0)
1329 zlog_warn ("RIPng invalid packet size %d from %s", len,
1330 inet6_ntoa (from.sin6_addr));
1331 ripng_peer_bad_packet (&from);
1335 packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf);
1336 ifp = if_lookup_by_index (ifindex);
1338 /* RIPng packet received. */
1339 if (IS_RIPNG_DEBUG_EVENT)
1340 zlog_debug ("RIPng packet received from %s port %d on %s",
1341 inet6_ntoa (from.sin6_addr), ntohs (from.sin6_port),
1342 ifp ? ifp->name : "unknown");
1344 /* Logging before packet checking. */
1345 if (IS_RIPNG_DEBUG_RECV)
1346 ripng_packet_dump (packet, len, "RECV");
1348 /* Packet comes from unknown interface. */
1351 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex);
1355 /* Packet version mismatch checking. */
1356 if (packet->version != ripng->version)
1358 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1359 packet->version, ripng->version);
1360 ripng_peer_bad_packet (&from);
1364 /* Process RIPng packet. */
1365 switch (packet->command)
1368 ripng_request_process (packet, len, &from, ifp);
1370 case RIPNG_RESPONSE:
1371 ripng_response_process (packet, len, &from, ifp, hoplimit);
1374 zlog_warn ("Invalid RIPng command %d", packet->command);
1375 ripng_peer_bad_packet (&from);
1381 /* Walk down the RIPng routing table then clear changed flag. */
1383 ripng_clear_changed_flag (void)
1385 struct route_node *rp;
1386 struct ripng_info *rinfo = NULL;
1387 struct list *list = NULL;
1388 struct listnode *listnode = NULL;
1390 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1391 if ((list = rp->info) != NULL)
1392 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
1394 UNSET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED);
1395 /* This flag can be set only on the first entry. */
1400 /* Regular update of RIPng route. Send all routing formation to RIPng
1401 enabled interface. */
1403 ripng_update (struct thread *t)
1405 struct listnode *node;
1406 struct interface *ifp;
1407 struct ripng_interface *ri;
1409 /* Clear update timer thread. */
1410 ripng->t_update = NULL;
1412 /* Logging update event. */
1413 if (IS_RIPNG_DEBUG_EVENT)
1414 zlog_debug ("RIPng update timer expired!");
1416 /* Supply routes to each interface. */
1417 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
1421 if (if_is_loopback (ifp) || ! if_is_up (ifp))
1427 /* When passive interface is specified, suppress announce to the
1433 if (ri->ri_send == RIPNG_SEND_OFF)
1435 if (IS_RIPNG_DEBUG_EVENT)
1436 zlog (NULL, LOG_DEBUG,
1437 "[Event] RIPng send to if %d is suppressed by config",
1441 #endif /* RIPNG_ADVANCED */
1443 ripng_output_process (ifp, NULL, ripng_all_route);
1446 /* Triggered updates may be suppressed if a regular update is due by
1447 the time the triggered update would be sent. */
1448 if (ripng->t_triggered_interval)
1450 thread_cancel (ripng->t_triggered_interval);
1451 ripng->t_triggered_interval = NULL;
1455 /* Reset flush event. */
1456 ripng_event (RIPNG_UPDATE_EVENT, 0);
1461 /* Triggered update interval timer. */
1463 ripng_triggered_interval (struct thread *t)
1465 ripng->t_triggered_interval = NULL;
1470 ripng_triggered_update (t);
1475 /* Execute triggered update. */
1477 ripng_triggered_update (struct thread *t)
1479 struct listnode *node;
1480 struct interface *ifp;
1481 struct ripng_interface *ri;
1484 ripng->t_triggered_update = NULL;
1486 /* Cancel interval timer. */
1487 if (ripng->t_triggered_interval)
1489 thread_cancel (ripng->t_triggered_interval);
1490 ripng->t_triggered_interval = NULL;
1494 /* Logging triggered update. */
1495 if (IS_RIPNG_DEBUG_EVENT)
1496 zlog_debug ("RIPng triggered update!");
1498 /* Split Horizon processing is done when generating triggered
1499 updates as well as normal updates (see section 2.6). */
1500 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
1504 if (if_is_loopback (ifp) || ! if_is_up (ifp))
1510 /* When passive interface is specified, suppress announce to the
1515 ripng_output_process (ifp, NULL, ripng_changed_route);
1518 /* Once all of the triggered updates have been generated, the route
1519 change flags should be cleared. */
1520 ripng_clear_changed_flag ();
1522 /* After a triggered update is sent, a timer should be set for a
1523 random interval between 1 and 5 seconds. If other changes that
1524 would trigger updates occur before the timer expires, a single
1525 update is triggered when the timer expires. */
1526 interval = (random () % 5) + 1;
1528 ripng->t_triggered_interval =
1529 thread_add_timer (master, ripng_triggered_interval, NULL, interval);
1534 /* Write routing table entry to the stream and return next index of
1535 the routing table entry in the stream. */
1537 ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,
1538 struct in6_addr *nexthop, u_int16_t tag, u_char metric)
1540 /* RIPng packet header. */
1543 stream_putc (s, RIPNG_RESPONSE);
1544 stream_putc (s, RIPNG_V1);
1548 /* Write routing table entry. */
1550 stream_write (s, (u_char *) &p->prefix, sizeof (struct in6_addr));
1552 stream_write (s, (u_char *) nexthop, sizeof (struct in6_addr));
1553 stream_putw (s, tag);
1555 stream_putc (s, p->prefixlen);
1558 stream_putc (s, metric);
1563 /* Send RESPONSE message to specified destination. */
1565 ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to,
1569 struct route_node *rp;
1570 struct ripng_info *rinfo;
1571 struct ripng_interface *ri;
1572 struct ripng_aggregate *aggregate;
1573 struct prefix_ipv6 *p;
1574 struct list * ripng_rte_list;
1575 struct list *list = NULL;
1576 struct listnode *listnode = NULL;
1578 if (IS_RIPNG_DEBUG_EVENT) {
1580 zlog_debug ("RIPng update routes to neighbor %s",
1581 inet6_ntoa(to->sin6_addr));
1583 zlog_debug ("RIPng update routes on interface %s", ifp->name);
1586 /* Get RIPng interface. */
1589 ripng_rte_list = ripng_rte_new();
1591 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1593 if ((list = rp->info) != NULL &&
1594 (rinfo = listgetdata (listhead (list))) != NULL &&
1595 rinfo->suppress == 0)
1597 /* If no route-map are applied, the RTE will be these following
1600 p = (struct prefix_ipv6 *) &rp->p;
1601 rinfo->metric_out = rinfo->metric;
1602 rinfo->tag_out = rinfo->tag;
1603 memset(&rinfo->nexthop_out, 0, sizeof(rinfo->nexthop_out));
1604 /* In order to avoid some local loops,
1605 * if the RIPng route has a nexthop via this interface, keep the nexthop,
1606 * otherwise set it to 0. The nexthop should not be propagated
1607 * beyond the local broadcast/multicast area in order
1608 * to avoid an IGP multi-level recursive look-up.
1610 if (rinfo->ifindex == ifp->ifindex)
1611 rinfo->nexthop_out = rinfo->nexthop;
1613 /* Apply output filters. */
1614 ret = ripng_filter (RIPNG_FILTER_OUT, p, ri);
1618 /* Changed route only output. */
1619 if (route_type == ripng_changed_route &&
1620 (! (rinfo->flags & RIPNG_RTF_CHANGED)))
1623 /* Split horizon. */
1624 if (ri->split_horizon == RIPNG_SPLIT_HORIZON)
1626 /* We perform split horizon for RIPng routes. */
1628 struct ripng_info *tmp_rinfo = NULL;
1630 for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
1631 if (tmp_rinfo->type == ZEBRA_ROUTE_RIPNG &&
1632 tmp_rinfo->ifindex == ifp->ifindex)
1641 /* Preparation for route-map. */
1642 rinfo->metric_set = 0;
1645 * and tag_out are already initialized.
1648 /* Interface route-map */
1649 if (ri->routemap[RIPNG_FILTER_OUT])
1653 ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
1654 (struct prefix *) p, RMAP_RIPNG,
1657 if (ret == RMAP_DENYMATCH)
1659 if (IS_RIPNG_DEBUG_PACKET)
1660 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1661 inet6_ntoa (p->prefix), p->prefixlen);
1667 /* Redistribute route-map. */
1668 if (ripng->route_map[rinfo->type].name)
1672 ret = route_map_apply (ripng->route_map[rinfo->type].map,
1673 (struct prefix *) p, RMAP_RIPNG,
1676 if (ret == RMAP_DENYMATCH)
1678 if (IS_RIPNG_DEBUG_PACKET)
1679 zlog_debug ("RIPng %s/%d is filtered by route-map",
1680 inet6_ntoa (p->prefix), p->prefixlen);
1685 /* When the route-map does not set metric. */
1686 if (! rinfo->metric_set)
1688 /* If the redistribute metric is set. */
1689 if (ripng->route_map[rinfo->type].metric_config
1690 && rinfo->metric != RIPNG_METRIC_INFINITY)
1692 rinfo->metric_out = ripng->route_map[rinfo->type].metric;
1696 /* If the route is not connected or localy generated
1697 one, use default-metric value */
1698 if (rinfo->type != ZEBRA_ROUTE_RIPNG
1699 && rinfo->type != ZEBRA_ROUTE_CONNECT
1700 && rinfo->metric != RIPNG_METRIC_INFINITY)
1701 rinfo->metric_out = ripng->default_metric;
1705 /* Apply offset-list */
1706 if (rinfo->metric_out != RIPNG_METRIC_INFINITY)
1707 ripng_offset_list_apply_out (p, ifp, &rinfo->metric_out);
1709 if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
1710 rinfo->metric_out = RIPNG_METRIC_INFINITY;
1712 /* Perform split-horizon with poisoned reverse
1715 if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) {
1716 struct ripng_info *tmp_rinfo = NULL;
1718 for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
1719 if ((tmp_rinfo->type == ZEBRA_ROUTE_RIPNG) &&
1720 tmp_rinfo->ifindex == ifp->ifindex)
1721 rinfo->metric_out = RIPNG_METRIC_INFINITY;
1724 /* Add RTE to the list */
1725 ripng_rte_add(ripng_rte_list, p, rinfo, NULL);
1728 /* Process the aggregated RTE entry */
1729 if ((aggregate = rp->aggregate) != NULL &&
1730 aggregate->count > 0 &&
1731 aggregate->suppress == 0)
1733 /* If no route-map are applied, the RTE will be these following
1736 p = (struct prefix_ipv6 *) &rp->p;
1737 aggregate->metric_set = 0;
1738 aggregate->metric_out = aggregate->metric;
1739 aggregate->tag_out = aggregate->tag;
1740 memset(&aggregate->nexthop_out, 0, sizeof(aggregate->nexthop_out));
1742 /* Apply output filters.*/
1743 ret = ripng_filter (RIPNG_FILTER_OUT, p, ri);
1747 /* Interface route-map */
1748 if (ri->routemap[RIPNG_FILTER_OUT])
1751 struct ripng_info newinfo;
1753 /* let's cast the aggregate structure to ripng_info */
1754 memset (&newinfo, 0, sizeof (struct ripng_info));
1755 /* the nexthop is :: */
1756 newinfo.metric = aggregate->metric;
1757 newinfo.metric_out = aggregate->metric_out;
1758 newinfo.tag = aggregate->tag;
1759 newinfo.tag_out = aggregate->tag_out;
1761 ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
1762 (struct prefix *) p, RMAP_RIPNG,
1765 if (ret == RMAP_DENYMATCH)
1767 if (IS_RIPNG_DEBUG_PACKET)
1768 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1769 inet6_ntoa (p->prefix), p->prefixlen);
1773 aggregate->metric_out = newinfo.metric_out;
1774 aggregate->tag_out = newinfo.tag_out;
1775 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out))
1776 aggregate->nexthop_out = newinfo.nexthop_out;
1779 /* There is no redistribute routemap for the aggregated RTE */
1781 /* Changed route only output. */
1782 /* XXX, vincent, in order to increase time convergence,
1783 * it should be announced if a child has changed.
1785 if (route_type == ripng_changed_route)
1788 /* Apply offset-list */
1789 if (aggregate->metric_out != RIPNG_METRIC_INFINITY)
1790 ripng_offset_list_apply_out (p, ifp, &aggregate->metric_out);
1792 if (aggregate->metric_out > RIPNG_METRIC_INFINITY)
1793 aggregate->metric_out = RIPNG_METRIC_INFINITY;
1795 /* Add RTE to the list */
1796 ripng_rte_add(ripng_rte_list, p, NULL, aggregate);
1801 /* Flush the list */
1802 ripng_rte_send(ripng_rte_list, ifp, to);
1803 ripng_rte_free(ripng_rte_list);
1806 /* Create new RIPng instance and set it to global variable. */
1810 /* ripng should be NULL. */
1811 assert (ripng == NULL);
1813 /* Allocaste RIPng instance. */
1814 ripng = XCALLOC (MTYPE_RIPNG, sizeof (struct ripng));
1816 /* Default version and timer values. */
1817 ripng->version = RIPNG_V1;
1818 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
1819 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
1820 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
1821 ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
1824 ripng->ibuf = stream_new (RIPNG_MAX_PACKET_SIZE * 5);
1825 ripng->obuf = stream_new (RIPNG_MAX_PACKET_SIZE);
1827 /* Initialize RIPng routig table. */
1828 ripng->table = route_table_init ();
1829 ripng->route = route_table_init ();
1830 ripng->aggregate = route_table_init ();
1833 ripng->sock = ripng_make_socket ();
1834 if (ripng->sock < 0)
1838 ripng_event (RIPNG_READ, ripng->sock);
1839 ripng_event (RIPNG_UPDATE_EVENT, 1);
1844 /* Send RIPng request to the interface. */
1846 ripng_request (struct interface *ifp)
1849 struct ripng_packet ripng_packet;
1851 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
1852 if (if_is_loopback(ifp))
1855 /* If interface is down, don't send RIP packet. */
1856 if (! if_is_up (ifp))
1859 if (IS_RIPNG_DEBUG_EVENT)
1860 zlog_debug ("RIPng send request to %s", ifp->name);
1862 memset (&ripng_packet, 0, sizeof (ripng_packet));
1863 ripng_packet.command = RIPNG_REQUEST;
1864 ripng_packet.version = RIPNG_V1;
1865 rte = ripng_packet.rte;
1866 rte->metric = RIPNG_METRIC_INFINITY;
1868 return ripng_send_packet ((caddr_t) &ripng_packet, sizeof (ripng_packet),
1874 ripng_update_jitter (int time)
1876 return ((random () % (time + 1)) - (time / 2));
1880 ripng_event (enum ripng_event event, int sock)
1888 ripng->t_read = thread_add_read (master, ripng_read, NULL, sock);
1890 case RIPNG_UPDATE_EVENT:
1891 if (ripng->t_update)
1893 thread_cancel (ripng->t_update);
1894 ripng->t_update = NULL;
1896 /* Update timer jitter. */
1897 jitter = ripng_update_jitter (ripng->update_time);
1900 thread_add_timer (master, ripng_update, NULL,
1901 sock ? 2 : ripng->update_time + jitter);
1903 case RIPNG_TRIGGERED_UPDATE:
1904 if (ripng->t_triggered_interval)
1906 else if (! ripng->t_triggered_update)
1907 ripng->t_triggered_update =
1908 thread_add_event (master, ripng_triggered_update, NULL, 0);
1916 /* Print out routes update time. */
1918 ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo)
1923 char timebuf [TIME_BUF];
1924 struct thread *thread;
1926 if ((thread = rinfo->t_timeout) != NULL)
1928 clock = thread_timer_remain_second (thread);
1929 tm = gmtime (&clock);
1930 strftime (timebuf, TIME_BUF, "%M:%S", tm);
1931 vty_out (vty, "%5s", timebuf);
1933 else if ((thread = rinfo->t_garbage_collect) != NULL)
1935 clock = thread_timer_remain_second (thread);
1936 tm = gmtime (&clock);
1937 strftime (timebuf, TIME_BUF, "%M:%S", tm);
1938 vty_out (vty, "%5s", timebuf);
1943 ripng_route_subtype_print (struct ripng_info *rinfo)
1948 if (rinfo->suppress)
1951 switch (rinfo->sub_type)
1953 case RIPNG_ROUTE_RTE:
1956 case RIPNG_ROUTE_STATIC:
1959 case RIPNG_ROUTE_DEFAULT:
1962 case RIPNG_ROUTE_REDISTRIBUTE:
1965 case RIPNG_ROUTE_INTERFACE:
1976 DEFUN (show_ipv6_ripng,
1977 show_ipv6_ripng_cmd,
1981 "Show RIPng routes\n")
1983 struct route_node *rp;
1984 struct ripng_info *rinfo;
1985 struct ripng_aggregate *aggregate;
1986 struct prefix_ipv6 *p;
1987 struct list *list = NULL;
1988 struct listnode *listnode = NULL;
1994 /* Header of display. */
1995 vty_out (vty, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
1997 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
1998 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
1999 " Network Next Hop Via Metric Tag Time%s",
2000 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
2001 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
2003 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
2005 if ((aggregate = rp->aggregate) != NULL)
2007 p = (struct prefix_ipv6 *) &rp->p;
2010 len = vty_out (vty, "R(a) %d/%d %s/%d ",
2011 aggregate->count, aggregate->suppress,
2012 inet6_ntoa (p->prefix), p->prefixlen);
2014 len = vty_out (vty, "R(a) %s/%d ",
2015 inet6_ntoa (p->prefix), p->prefixlen);
2017 vty_out (vty, "%s", VTY_NEWLINE);
2018 vty_out (vty, "%*s", 18, " ");
2020 vty_out (vty, "%*s", 28, " ");
2021 vty_out (vty, "self %2d %3d%s", aggregate->metric,
2026 if ((list = rp->info) != NULL)
2027 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
2029 p = (struct prefix_ipv6 *) &rp->p;
2032 len = vty_out (vty, "%c(%s) 0/%d %s/%d ",
2033 zebra_route_char(rinfo->type),
2034 ripng_route_subtype_print(rinfo),
2036 inet6_ntoa (p->prefix), p->prefixlen);
2038 len = vty_out (vty, "%c(%s) %s/%d ",
2039 zebra_route_char(rinfo->type),
2040 ripng_route_subtype_print(rinfo),
2041 inet6_ntoa (p->prefix), p->prefixlen);
2043 vty_out (vty, "%s", VTY_NEWLINE);
2044 vty_out (vty, "%*s", 18, " ");
2045 len = vty_out (vty, "%s", inet6_ntoa (rinfo->nexthop));
2049 len = vty_out (vty, "%*s", len, " ");
2052 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2053 (rinfo->sub_type == RIPNG_ROUTE_RTE))
2055 len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex));
2056 } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
2058 len = vty_out (vty, "kill");
2060 len = vty_out (vty, "self");
2064 vty_out (vty, "%*s", len, " ");
2066 vty_out (vty, " %2d %3d ",
2067 rinfo->metric, rinfo->tag);
2070 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2071 (rinfo->sub_type == RIPNG_ROUTE_RTE))
2073 /* RTE from remote RIP routers */
2074 ripng_vty_out_uptime (vty, rinfo);
2075 } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
2077 /* poisonous reversed routes (gc) */
2078 ripng_vty_out_uptime (vty, rinfo);
2081 vty_out (vty, "%s", VTY_NEWLINE);
2088 DEFUN (show_ipv6_ripng_status,
2089 show_ipv6_ripng_status_cmd,
2090 "show ipv6 ripng status",
2093 "Show RIPng routes\n"
2094 "IPv6 routing protocol process parameters and statistics\n")
2096 struct listnode *node;
2097 struct interface *ifp;
2102 vty_out (vty, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE);
2103 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
2104 ripng->update_time);
2105 vty_out (vty, " next due in %lu seconds%s",
2106 thread_timer_remain_second (ripng->t_update),
2108 vty_out (vty, " Timeout after %ld seconds,", ripng->timeout_time);
2109 vty_out (vty, " garbage collect after %ld seconds%s", ripng->garbage_time,
2112 /* Filtering status show. */
2113 config_show_distribute (vty);
2115 /* Default metric information. */
2116 vty_out (vty, " Default redistribution metric is %d%s",
2117 ripng->default_metric, VTY_NEWLINE);
2119 /* Redistribute information. */
2120 vty_out (vty, " Redistributing:");
2121 ripng_redistribute_write (vty, 0);
2122 vty_out (vty, "%s", VTY_NEWLINE);
2124 vty_out (vty, " Default version control: send version %d,", ripng->version);
2125 vty_out (vty, " receive version %d %s", ripng->version,
2128 vty_out (vty, " Interface Send Recv%s", VTY_NEWLINE);
2130 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2132 struct ripng_interface *ri;
2136 if (ri->enable_network || ri->enable_interface)
2139 vty_out (vty, " %-17s%-3d %-3d%s", ifp->name,
2146 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
2147 ripng_network_write (vty, 0);
2149 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
2150 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
2151 ripng_peer_display (vty);
2156 DEFUN (router_ripng,
2159 "Enable a routing process\n"
2160 "Make RIPng instance command\n")
2164 vty->node = RIPNG_NODE;
2168 ret = ripng_create ();
2170 /* Notice to user we couldn't create RIPng. */
2173 zlog_warn ("can't create RIPng");
2181 DEFUN (no_router_ripng,
2182 no_router_ripng_cmd,
2185 "Enable a routing process\n"
2186 "Make RIPng instance command\n")
2196 "Static route setup\n"
2197 "Set static RIPng route announcement\n")
2200 struct prefix_ipv6 p;
2201 struct route_node *rp;
2203 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2206 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2209 apply_mask_ipv6 (&p);
2211 rp = route_node_get (ripng->route, (struct prefix *) &p);
2214 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2215 route_unlock_node (rp);
2218 rp->info = (void *)1;
2220 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL, 0);
2225 DEFUN (no_ripng_route,
2227 "no route IPV6ADDR",
2229 "Static route setup\n"
2230 "Delete static RIPng route announcement\n")
2233 struct prefix_ipv6 p;
2234 struct route_node *rp;
2236 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2239 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2242 apply_mask_ipv6 (&p);
2244 rp = route_node_lookup (ripng->route, (struct prefix *) &p);
2247 vty_out (vty, "Can't find static route.%s", VTY_NEWLINE);
2251 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
2252 route_unlock_node (rp);
2255 route_unlock_node (rp);
2260 DEFUN (ripng_aggregate_address,
2261 ripng_aggregate_address_cmd,
2262 "aggregate-address X:X::X:X/M",
2263 "Set aggregate RIPng route announcement\n"
2264 "Aggregate network\n")
2268 struct route_node *node;
2270 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2273 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2277 /* Check aggregate alredy exist or not. */
2278 node = route_node_get (ripng->aggregate, &p);
2281 vty_out (vty, "There is already same aggregate route.%s", VTY_NEWLINE);
2282 route_unlock_node (node);
2285 node->info = (void *)1;
2287 ripng_aggregate_add (&p);
2292 DEFUN (no_ripng_aggregate_address,
2293 no_ripng_aggregate_address_cmd,
2294 "no aggregate-address X:X::X:X/M",
2296 "Delete aggregate RIPng route announcement\n"
2297 "Aggregate network")
2301 struct route_node *rn;
2303 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &p);
2306 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2310 rn = route_node_lookup (ripng->aggregate, &p);
2313 vty_out (vty, "Can't find aggregate route.%s", VTY_NEWLINE);
2316 route_unlock_node (rn);
2318 route_unlock_node (rn);
2320 ripng_aggregate_delete (&p);
2325 DEFUN (ripng_default_metric,
2326 ripng_default_metric_cmd,
2327 "default-metric <1-16>",
2328 "Set a metric of redistribute routes\n"
2333 ripng->default_metric = atoi (argv[0]);
2338 DEFUN (no_ripng_default_metric,
2339 no_ripng_default_metric_cmd,
2340 "no default-metric",
2342 "Set a metric of redistribute routes\n"
2347 ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
2352 ALIAS (no_ripng_default_metric,
2353 no_ripng_default_metric_val_cmd,
2354 "no default-metric <1-16>",
2356 "Set a metric of redistribute routes\n"
2360 /* RIPng update timer setup. */
2361 DEFUN (ripng_update_timer,
2362 ripng_update_timer_cmd,
2363 "update-timer SECOND",
2364 "Set RIPng update timer in seconds\n"
2367 unsigned long update;
2368 char *endptr = NULL;
2370 update = strtoul (argv[0], &endptr, 10);
2371 if (update == ULONG_MAX || *endptr != '\0')
2373 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2377 ripng->update_time = update;
2379 ripng_event (RIPNG_UPDATE_EVENT, 0);
2383 DEFUN (no_ripng_update_timer,
2384 no_ripng_update_timer_cmd,
2385 "no update-timer SECOND",
2387 "Unset RIPng update timer in seconds\n"
2390 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
2391 ripng_event (RIPNG_UPDATE_EVENT, 0);
2395 /* RIPng timeout timer setup. */
2396 DEFUN (ripng_timeout_timer,
2397 ripng_timeout_timer_cmd,
2398 "timeout-timer SECOND",
2399 "Set RIPng timeout timer in seconds\n"
2402 unsigned long timeout;
2403 char *endptr = NULL;
2405 timeout = strtoul (argv[0], &endptr, 10);
2406 if (timeout == ULONG_MAX || *endptr != '\0')
2408 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2412 ripng->timeout_time = timeout;
2417 DEFUN (no_ripng_timeout_timer,
2418 no_ripng_timeout_timer_cmd,
2419 "no timeout-timer SECOND",
2421 "Unset RIPng timeout timer in seconds\n"
2424 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
2428 /* RIPng garbage timer setup. */
2429 DEFUN (ripng_garbage_timer,
2430 ripng_garbage_timer_cmd,
2431 "garbage-timer SECOND",
2432 "Set RIPng garbage timer in seconds\n"
2435 unsigned long garbage;
2436 char *endptr = NULL;
2438 garbage = strtoul (argv[0], &endptr, 10);
2439 if (garbage == ULONG_MAX || *endptr != '\0')
2441 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2445 ripng->garbage_time = garbage;
2450 DEFUN (no_ripng_garbage_timer,
2451 no_ripng_garbage_timer_cmd,
2452 "no garbage-timer SECOND",
2454 "Unset RIPng garbage timer in seconds\n"
2457 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
2462 DEFUN (ripng_timers,
2464 "timers basic <0-65535> <0-65535> <0-65535>",
2465 "RIPng timers setup\n"
2467 "Routing table update timer value in second. Default is 30.\n"
2468 "Routing information timeout timer. Default is 180.\n"
2469 "Garbage collection timer. Default is 120.\n")
2471 unsigned long update;
2472 unsigned long timeout;
2473 unsigned long garbage;
2475 VTY_GET_INTEGER_RANGE("update timer", update, argv[0], 0, 65535);
2476 VTY_GET_INTEGER_RANGE("timeout timer", timeout, argv[1], 0, 65535);
2477 VTY_GET_INTEGER_RANGE("garbage timer", garbage, argv[2], 0, 65535);
2479 /* Set each timer value. */
2480 ripng->update_time = update;
2481 ripng->timeout_time = timeout;
2482 ripng->garbage_time = garbage;
2484 /* Reset update timer thread. */
2485 ripng_event (RIPNG_UPDATE_EVENT, 0);
2490 DEFUN (no_ripng_timers,
2491 no_ripng_timers_cmd,
2494 "RIPng timers setup\n"
2497 /* Set each timer value to the default. */
2498 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
2499 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
2500 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
2502 /* Reset update timer thread. */
2503 ripng_event (RIPNG_UPDATE_EVENT, 0);
2508 ALIAS (no_ripng_timers,
2509 no_ripng_timers_val_cmd,
2510 "no timers basic <0-65535> <0-65535> <0-65535>",
2512 "RIPng timers setup\n"
2514 "Routing table update timer value in second. Default is 30.\n"
2515 "Routing information timeout timer. Default is 180.\n"
2516 "Garbage collection timer. Default is 120.\n")
2518 DEFUN (show_ipv6_protocols, show_ipv6_protocols_cmd,
2519 "show ipv6 protocols",
2522 "Routing protocol information")
2527 vty_out (vty, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE);
2529 vty_out (vty, "Sending updates every %ld seconds, next due in %d seconds%s",
2530 ripng->update_time, 0,
2533 vty_out (vty, "Timerout after %ld seconds, garbage correct %ld%s",
2534 ripng->timeout_time,
2535 ripng->garbage_time,
2538 vty_out (vty, "Outgoing update filter list for all interfaces is not set");
2539 vty_out (vty, "Incoming update filter list for all interfaces is not set");
2544 /* Please be carefull to use this command. */
2545 DEFUN (ripng_default_information_originate,
2546 ripng_default_information_originate_cmd,
2547 "default-information originate",
2548 "Default route information\n"
2549 "Distribute default route\n")
2551 struct prefix_ipv6 p;
2553 if (! ripng ->default_information) {
2554 ripng->default_information = 1;
2556 str2prefix_ipv6 ("::/0", &p);
2557 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
2563 DEFUN (no_ripng_default_information_originate,
2564 no_ripng_default_information_originate_cmd,
2565 "no default-information originate",
2567 "Default route information\n"
2568 "Distribute default route\n")
2570 struct prefix_ipv6 p;
2572 if (ripng->default_information) {
2573 ripng->default_information = 0;
2575 str2prefix_ipv6 ("::/0", &p);
2576 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0);
2582 /* Update ECMP routes to zebra when ECMP is disabled. */
2584 ripng_ecmp_disable (void)
2586 struct route_node *rp;
2587 struct ripng_info *rinfo, *tmp_rinfo;
2589 struct listnode *node, *nextnode;
2594 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
2595 if ((list = rp->info) != NULL && listcount (list) > 1)
2597 rinfo = listgetdata (listhead (list));
2598 if (!ripng_route_rte (rinfo))
2601 /* Drop all other entries, except the first one. */
2602 for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo))
2603 if (tmp_rinfo != rinfo)
2605 RIPNG_TIMER_OFF (tmp_rinfo->t_timeout);
2606 RIPNG_TIMER_OFF (tmp_rinfo->t_garbage_collect);
2607 list_delete_node (list, node);
2608 ripng_info_free (tmp_rinfo);
2612 ripng_zebra_ipv6_add (rp);
2614 /* Set the route change flag. */
2615 SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED);
2617 /* Signal the output process to trigger an update. */
2618 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
2622 DEFUN (ripng_allow_ecmp,
2623 ripng_allow_ecmp_cmd,
2625 "Allow Equal Cost MultiPath\n")
2629 vty_out (vty, "ECMP is already enabled.%s", VTY_NEWLINE);
2634 zlog_info ("ECMP is enabled.");
2638 DEFUN (no_ripng_allow_ecmp,
2639 no_ripng_allow_ecmp_cmd,
2642 "Allow Equal Cost MultiPath\n")
2646 vty_out (vty, "ECMP is already disabled.%s", VTY_NEWLINE);
2651 zlog_info ("ECMP is disabled.");
2652 ripng_ecmp_disable ();
2656 /* RIPng configuration write function. */
2658 ripng_config_write (struct vty *vty)
2660 int ripng_network_write (struct vty *, int);
2661 void ripng_redistribute_write (struct vty *, int);
2663 struct route_node *rp;
2669 vty_out (vty, "router ripng%s", VTY_NEWLINE);
2671 if (ripng->default_information)
2672 vty_out (vty, " default-information originate%s", VTY_NEWLINE);
2674 ripng_network_write (vty, 1);
2676 /* RIPng default metric configuration */
2677 if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT)
2678 vty_out (vty, " default-metric %d%s",
2679 ripng->default_metric, VTY_NEWLINE);
2681 ripng_redistribute_write (vty, 1);
2683 /* RIP offset-list configuration. */
2684 config_write_ripng_offset_list (vty);
2686 /* RIPng aggregate routes. */
2687 for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
2688 if (rp->info != NULL)
2689 vty_out (vty, " aggregate-address %s/%d%s",
2690 inet6_ntoa (rp->p.u.prefix6),
2695 /* ECMP configuration. */
2697 vty_out (vty, " allow-ecmp%s", VTY_NEWLINE);
2699 /* RIPng static routes. */
2700 for (rp = route_top (ripng->route); rp; rp = route_next (rp))
2701 if (rp->info != NULL)
2702 vty_out (vty, " route %s/%d%s", inet6_ntoa (rp->p.u.prefix6),
2706 /* RIPng timers configuration. */
2707 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT ||
2708 ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT ||
2709 ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
2711 vty_out (vty, " timers basic %ld %ld %ld%s",
2713 ripng->timeout_time,
2714 ripng->garbage_time,
2718 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT)
2719 vty_out (vty, " update-timer %d%s", ripng->update_time,
2721 if (ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT)
2722 vty_out (vty, " timeout-timer %d%s", ripng->timeout_time,
2724 if (ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
2725 vty_out (vty, " garbage-timer %d%s", ripng->garbage_time,
2729 write += config_write_distribute (vty);
2731 write += config_write_if_rmap (vty);
2738 /* RIPng node structure. */
2739 static struct cmd_node cmd_ripng_node =
2742 "%s(config-router)# ",
2747 ripng_distribute_update (struct distribute *dist)
2749 struct interface *ifp;
2750 struct ripng_interface *ri;
2751 struct access_list *alist;
2752 struct prefix_list *plist;
2757 ifp = if_lookup_by_name (dist->ifname);
2763 if (dist->list[DISTRIBUTE_V6_IN])
2765 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_V6_IN]);
2767 ri->list[RIPNG_FILTER_IN] = alist;
2769 ri->list[RIPNG_FILTER_IN] = NULL;
2772 ri->list[RIPNG_FILTER_IN] = NULL;
2774 if (dist->list[DISTRIBUTE_V6_OUT])
2776 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_V6_OUT]);
2778 ri->list[RIPNG_FILTER_OUT] = alist;
2780 ri->list[RIPNG_FILTER_OUT] = NULL;
2783 ri->list[RIPNG_FILTER_OUT] = NULL;
2785 if (dist->prefix[DISTRIBUTE_V6_IN])
2787 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_V6_IN]);
2789 ri->prefix[RIPNG_FILTER_IN] = plist;
2791 ri->prefix[RIPNG_FILTER_IN] = NULL;
2794 ri->prefix[RIPNG_FILTER_IN] = NULL;
2796 if (dist->prefix[DISTRIBUTE_V6_OUT])
2798 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_V6_OUT]);
2800 ri->prefix[RIPNG_FILTER_OUT] = plist;
2802 ri->prefix[RIPNG_FILTER_OUT] = NULL;
2805 ri->prefix[RIPNG_FILTER_OUT] = NULL;
2809 ripng_distribute_update_interface (struct interface *ifp)
2811 struct distribute *dist;
2813 dist = distribute_lookup (ifp->name);
2815 ripng_distribute_update (dist);
2818 /* Update all interface's distribute list. */
2820 ripng_distribute_update_all (struct prefix_list *notused)
2822 struct interface *ifp;
2823 struct listnode *node;
2825 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2826 ripng_distribute_update_interface (ifp);
2830 ripng_distribute_update_all_wrapper (const char *notused)
2832 ripng_distribute_update_all(NULL);
2835 /* delete all the added ripng routes. */
2840 struct route_node *rp;
2841 struct ripng_info *rinfo;
2842 struct ripng_aggregate *aggregate;
2843 struct list *list = NULL;
2844 struct listnode *listnode = NULL;
2847 /* Clear RIPng routes */
2848 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
2850 if ((list = rp->info) != NULL)
2852 rinfo = listgetdata (listhead (list));
2853 if (ripng_route_rte (rinfo))
2854 ripng_zebra_ipv6_delete (rp);
2856 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
2858 RIPNG_TIMER_OFF (rinfo->t_timeout);
2859 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
2860 ripng_info_free (rinfo);
2864 route_unlock_node (rp);
2867 if ((aggregate = rp->aggregate) != NULL)
2869 ripng_aggregate_free (aggregate);
2870 rp->aggregate = NULL;
2871 route_unlock_node (rp);
2875 /* Cancel the RIPng timers */
2876 RIPNG_TIMER_OFF (ripng->t_update);
2877 RIPNG_TIMER_OFF (ripng->t_triggered_update);
2878 RIPNG_TIMER_OFF (ripng->t_triggered_interval);
2880 /* Cancel the read thread */
2881 if (ripng->t_read) {
2882 thread_cancel (ripng->t_read);
2883 ripng->t_read = NULL;
2886 /* Close the RIPng socket */
2887 if (ripng->sock >= 0) {
2892 /* Static RIPng route configuration. */
2893 for (rp = route_top (ripng->route); rp; rp = route_next (rp))
2896 route_unlock_node (rp);
2899 /* RIPng aggregated prefixes */
2900 for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
2903 route_unlock_node (rp);
2906 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2907 if (ripng->route_map[i].name)
2908 free (ripng->route_map[i].name);
2910 XFREE (MTYPE_ROUTE_TABLE, ripng->table);
2911 XFREE (MTYPE_ROUTE_TABLE, ripng->route);
2912 XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate);
2914 XFREE (MTYPE_RIPNG, ripng);
2918 ripng_clean_network();
2919 ripng_passive_interface_clean ();
2920 ripng_offset_clean ();
2921 ripng_interface_clean ();
2922 ripng_redistribute_clean ();
2925 /* Reset all values to the default settings. */
2929 /* Call ripd related reset functions. */
2930 ripng_debug_reset ();
2931 ripng_route_map_reset ();
2933 /* Call library reset functions. */
2935 access_list_reset ();
2936 prefix_list_reset ();
2938 distribute_list_reset ();
2940 ripng_interface_reset ();
2942 ripng_zclient_reset ();
2946 ripng_if_rmap_update (struct if_rmap *if_rmap)
2948 struct interface *ifp;
2949 struct ripng_interface *ri;
2950 struct route_map *rmap;
2952 ifp = if_lookup_by_name (if_rmap->ifname);
2958 if (if_rmap->routemap[IF_RMAP_IN])
2960 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
2962 ri->routemap[IF_RMAP_IN] = rmap;
2964 ri->routemap[IF_RMAP_IN] = NULL;
2967 ri->routemap[RIPNG_FILTER_IN] = NULL;
2969 if (if_rmap->routemap[IF_RMAP_OUT])
2971 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
2973 ri->routemap[IF_RMAP_OUT] = rmap;
2975 ri->routemap[IF_RMAP_OUT] = NULL;
2978 ri->routemap[RIPNG_FILTER_OUT] = NULL;
2982 ripng_if_rmap_update_interface (struct interface *ifp)
2984 struct if_rmap *if_rmap;
2986 if_rmap = if_rmap_lookup (ifp->name);
2988 ripng_if_rmap_update (if_rmap);
2992 ripng_routemap_update_redistribute (void)
2998 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3000 if (ripng->route_map[i].name)
3001 ripng->route_map[i].map =
3002 route_map_lookup_by_name (ripng->route_map[i].name);
3008 ripng_routemap_update (const char *unused)
3010 struct interface *ifp;
3011 struct listnode *node;
3013 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
3014 ripng_if_rmap_update_interface (ifp);
3016 ripng_routemap_update_redistribute ();
3019 /* Initialize ripng structure and set commands. */
3024 srandom (time (NULL));
3026 /* Install RIPNG_NODE. */
3027 install_node (&cmd_ripng_node, ripng_config_write);
3029 /* Install ripng commands. */
3030 install_element (VIEW_NODE, &show_ipv6_ripng_cmd);
3031 install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd);
3033 install_element (CONFIG_NODE, &router_ripng_cmd);
3034 install_element (CONFIG_NODE, &no_router_ripng_cmd);
3036 install_default (RIPNG_NODE);
3037 install_element (RIPNG_NODE, &ripng_route_cmd);
3038 install_element (RIPNG_NODE, &no_ripng_route_cmd);
3039 install_element (RIPNG_NODE, &ripng_aggregate_address_cmd);
3040 install_element (RIPNG_NODE, &no_ripng_aggregate_address_cmd);
3042 install_element (RIPNG_NODE, &ripng_default_metric_cmd);
3043 install_element (RIPNG_NODE, &no_ripng_default_metric_cmd);
3044 install_element (RIPNG_NODE, &no_ripng_default_metric_val_cmd);
3046 install_element (RIPNG_NODE, &ripng_timers_cmd);
3047 install_element (RIPNG_NODE, &no_ripng_timers_cmd);
3048 install_element (RIPNG_NODE, &no_ripng_timers_val_cmd);
3050 install_element (RIPNG_NODE, &ripng_update_timer_cmd);
3051 install_element (RIPNG_NODE, &no_ripng_update_timer_cmd);
3052 install_element (RIPNG_NODE, &ripng_timeout_timer_cmd);
3053 install_element (RIPNG_NODE, &no_ripng_timeout_timer_cmd);
3054 install_element (RIPNG_NODE, &ripng_garbage_timer_cmd);
3055 install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd);
3058 install_element (RIPNG_NODE, &ripng_default_information_originate_cmd);
3059 install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd);
3061 install_element (RIPNG_NODE, &ripng_allow_ecmp_cmd);
3062 install_element (RIPNG_NODE, &no_ripng_allow_ecmp_cmd);
3065 ripng_debug_init ();
3067 /* Access list install. */
3068 access_list_init ();
3069 access_list_add_hook (ripng_distribute_update_all_wrapper);
3070 access_list_delete_hook (ripng_distribute_update_all_wrapper);
3072 /* Prefix list initialize.*/
3073 prefix_list_init ();
3074 prefix_list_add_hook (ripng_distribute_update_all);
3075 prefix_list_delete_hook (ripng_distribute_update_all);
3077 /* Distribute list install. */
3078 distribute_list_init (RIPNG_NODE);
3079 distribute_list_add_hook (ripng_distribute_update);
3080 distribute_list_delete_hook (ripng_distribute_update);
3082 /* Route-map for interface. */
3083 ripng_route_map_init ();
3084 ripng_offset_init ();
3086 route_map_add_hook (ripng_routemap_update);
3087 route_map_delete_hook (ripng_routemap_update);
3089 if_rmap_init (RIPNG_NODE);
3090 if_rmap_hook_add (ripng_if_rmap_update);
3091 if_rmap_hook_delete (ripng_if_rmap_update);