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_err("Can't make ripng socket");
114 setsockopt_so_recvbuf (sock
, 8096);
115 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
118 #ifdef IPTOS_PREC_INTERNETCONTROL
119 ret
= setsockopt_ipv6_tclass (sock
, IPTOS_PREC_INTERNETCONTROL
);
123 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
126 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
129 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
133 memset (&ripaddr
, 0, sizeof (ripaddr
));
134 ripaddr
.sin6_family
= AF_INET6
;
136 ripaddr
.sin6_len
= sizeof (struct sockaddr_in6
);
137 #endif /* SIN6_LEN */
138 ripaddr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
140 if (ripngd_privs
.change (ZPRIVS_RAISE
))
141 zlog_err ("ripng_make_socket: could not raise privs");
143 ret
= bind (sock
, (struct sockaddr
*) &ripaddr
, sizeof (ripaddr
));
146 zlog_err("Can't bind ripng socket: %s.", safe_strerror(errno
));
147 if (ripngd_privs
.change (ZPRIVS_LOWER
))
148 zlog_err ("ripng_make_socket: could not lower privs");
151 if (ripngd_privs
.change (ZPRIVS_LOWER
))
152 zlog_err ("ripng_make_socket: could not lower privs");
156 /* Send RIPng packet. */
158 ripng_send_packet (caddr_t buf
, int bufsize
, struct sockaddr_in6
*to
,
159 struct interface
*ifp
)
164 struct cmsghdr
*cmsgptr
;
166 struct in6_pktinfo
*pkt
;
167 struct sockaddr_in6 addr
;
169 if (IS_RIPNG_DEBUG_SEND
) {
171 zlog_debug ("send to %s", inet6_ntoa (to
->sin6_addr
));
172 zlog_debug (" send interface %s", ifp
->name
);
173 zlog_debug (" send packet size %d", bufsize
);
176 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
177 addr
.sin6_family
= AF_INET6
;
179 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
180 #endif /* SIN6_LEN */
181 addr
.sin6_flowinfo
= htonl (RIPNG_PRIORITY_DEFAULT
);
183 /* When destination is specified. */
186 addr
.sin6_addr
= to
->sin6_addr
;
187 addr
.sin6_port
= to
->sin6_port
;
191 inet_pton(AF_INET6
, RIPNG_GROUP
, &addr
.sin6_addr
);
192 addr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
195 msg
.msg_name
= (void *) &addr
;
196 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
199 msg
.msg_control
= (void *) adata
;
200 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
203 iov
.iov_len
= bufsize
;
205 cmsgptr
= (struct cmsghdr
*)adata
;
206 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof (struct in6_pktinfo
));
207 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
208 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
210 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
211 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
212 pkt
->ipi6_ifindex
= ifp
->ifindex
;
214 ret
= sendmsg (ripng
->sock
, &msg
, 0);
218 zlog_err ("RIPng send fail on %s to %s: %s", ifp
->name
,
219 inet6_ntoa (to
->sin6_addr
), safe_strerror (errno
));
221 zlog_err ("RIPng send fail on %s: %s", ifp
->name
, safe_strerror (errno
));
227 /* Receive UDP RIPng packet from socket. */
229 ripng_recv_packet (int sock
, u_char
*buf
, int bufsize
,
230 struct sockaddr_in6
*from
, ifindex_t
*ifindex
,
236 struct cmsghdr
*cmsgptr
;
237 struct in6_addr dst
= { .s6_addr
= { 0 } };
239 memset(&dst
, 0, sizeof(struct in6_addr
));
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 %"ROUTE_TAG_PRI
,
323 inet6_ntoa (rte
->addr
), rte
->prefixlen
,
324 rte
->metric
, (route_tag_t
)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 %"ROUTE_TAG_PRI
" prefixlen %d",
339 inet6_ntoa (rte
->addr
), (route_tag_t
)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 %"ROUTE_TAG_PRI
" from %s",
346 (route_tag_t
)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. Unless ECMP is disabled, keep "rinfo" null and
831 * the new route is added in the ECMP list in below. */
839 /* Redistributed route check. */
840 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
841 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
843 route_unlock_node (rp
);
847 /* Local static route. */
848 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
849 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
850 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
))
851 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
853 route_unlock_node (rp
);
860 /* Now, check to see whether there is already an explicit route
861 for the destination prefix. If there is no such route, add
862 this route to the routing table, unless the metric is
863 infinity (there is no point in adding a route which
865 if (rte
->metric
!= RIPNG_METRIC_INFINITY
)
866 ripng_ecmp_add (&newinfo
);
870 /* If there is an existing route, compare the next hop address
871 to the address of the router from which the datagram came.
872 If this datagram is from the same router as the existing
873 route, reinitialize the timeout. */
874 same
= (IN6_ARE_ADDR_EQUAL (&rinfo
->from
, &from
->sin6_addr
)
875 && (rinfo
->ifindex
== ifp
->ifindex
));
878 * RFC 2080 - Section 2.4.2:
879 * "If the new metric is the same as the old one, examine the timeout
880 * for the existing route. If it is at least halfway to the expiration
881 * point, switch to the new route. This heuristic is optional, but
882 * highly recommended".
884 if (!ripng
->ecmp
&& !same
&&
885 rinfo
->metric
== rte
->metric
&& rinfo
->t_timeout
&&
886 (thread_timer_remain_second (rinfo
->t_timeout
) < (ripng
->timeout_time
/ 2)))
888 ripng_ecmp_replace (&newinfo
);
890 /* Next, compare the metrics. If the datagram is from the same
891 router as the existing route, and the new metric is different
892 than the old one; or, if the new metric is lower than the old
893 one; do the following actions: */
894 else if ((same
&& rinfo
->metric
!= rte
->metric
) ||
895 rte
->metric
< rinfo
->metric
)
897 if (listcount (list
) == 1)
899 if (newinfo
.metric
!= RIPNG_METRIC_INFINITY
)
900 ripng_ecmp_replace (&newinfo
);
902 ripng_ecmp_delete (rinfo
);
906 if (newinfo
.metric
< rinfo
->metric
)
907 ripng_ecmp_replace (&newinfo
);
908 else /* newinfo.metric > rinfo->metric */
909 ripng_ecmp_delete (rinfo
);
912 else /* same & no change */
913 ripng_timeout_update (rinfo
);
915 /* Unlock tempolary lock of the route. */
916 route_unlock_node (rp
);
920 /* Add redistributed route to RIPng table. */
922 ripng_redistribute_add (int type
, int sub_type
, struct prefix_ipv6
*p
,
923 ifindex_t ifindex
, struct in6_addr
*nexthop
,
926 struct route_node
*rp
;
927 struct ripng_info
*rinfo
= NULL
, newinfo
;
928 struct list
*list
= NULL
;
930 /* Redistribute route */
931 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
933 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
936 rp
= route_node_get (ripng
->table
, (struct prefix
*) p
);
938 memset (&newinfo
, 0, sizeof (struct ripng_info
));
940 newinfo
.sub_type
= sub_type
;
941 newinfo
.ifindex
= ifindex
;
943 if (tag
<= UINT16_MAX
) /* RIPng only supports 16 bit tags */
946 if (nexthop
&& IN6_IS_ADDR_LINKLOCAL(nexthop
))
947 newinfo
.nexthop
= *nexthop
;
949 if ((list
= rp
->info
) != NULL
&& listcount (list
) != 0)
951 rinfo
= listgetdata (listhead (list
));
953 if (rinfo
->type
== ZEBRA_ROUTE_CONNECT
954 && rinfo
->sub_type
== RIPNG_ROUTE_INTERFACE
955 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
) {
956 route_unlock_node (rp
);
960 /* Manually configured RIPng route check.
961 * They have the precedence on all the other entries.
963 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
964 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
965 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
)) ) {
966 if (type
!= ZEBRA_ROUTE_RIPNG
|| ((sub_type
!= RIPNG_ROUTE_STATIC
) &&
967 (sub_type
!= RIPNG_ROUTE_DEFAULT
))) {
968 route_unlock_node (rp
);
973 rinfo
= ripng_ecmp_replace (&newinfo
);
974 route_unlock_node (rp
);
977 rinfo
= ripng_ecmp_add (&newinfo
);
979 if (IS_RIPNG_DEBUG_EVENT
) {
981 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
982 inet6_ntoa(p
->prefix
), p
->prefixlen
,
983 ifindex2ifname(ifindex
, VRF_DEFAULT
));
985 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
986 inet6_ntoa(p
->prefix
), p
->prefixlen
, inet6_ntoa(*nexthop
),
987 ifindex2ifname(ifindex
, VRF_DEFAULT
));
990 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
993 /* Delete redistributed route to RIPng table. */
995 ripng_redistribute_delete (int type
, int sub_type
, struct prefix_ipv6
*p
,
998 struct route_node
*rp
;
999 struct ripng_info
*rinfo
;
1001 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
1003 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
1006 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) p
);
1010 struct list
*list
= rp
->info
;
1012 if (list
!= NULL
&& listcount (list
) != 0)
1014 rinfo
= listgetdata (listhead (list
));
1016 && rinfo
->type
== type
1017 && rinfo
->sub_type
== sub_type
1018 && rinfo
->ifindex
== ifindex
)
1020 /* Perform poisoned reverse. */
1021 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1022 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1023 ripng_garbage_collect
, ripng
->garbage_time
);
1024 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1026 /* Aggregate count decrement. */
1027 ripng_aggregate_decrement (rp
, rinfo
);
1029 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1031 if (IS_RIPNG_DEBUG_EVENT
)
1032 zlog_debug ("Poisone %s/%d on the interface %s with an "
1033 "infinity metric [delete]",
1034 inet6_ntoa (p
->prefix
), p
->prefixlen
,
1035 ifindex2ifname (ifindex
, VRF_DEFAULT
));
1037 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1040 route_unlock_node (rp
);
1044 /* Withdraw redistributed route. */
1046 ripng_redistribute_withdraw (int type
)
1048 struct route_node
*rp
;
1049 struct ripng_info
*rinfo
= NULL
;
1050 struct list
*list
= NULL
;
1055 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1056 if ((list
= rp
->info
) != NULL
)
1058 rinfo
= listgetdata (listhead (list
));
1059 if ((rinfo
->type
== type
)
1060 && (rinfo
->sub_type
!= RIPNG_ROUTE_INTERFACE
))
1062 /* Perform poisoned reverse. */
1063 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1064 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1065 ripng_garbage_collect
, ripng
->garbage_time
);
1066 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1068 /* Aggregate count decrement. */
1069 ripng_aggregate_decrement (rp
, rinfo
);
1071 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1073 if (IS_RIPNG_DEBUG_EVENT
) {
1074 struct prefix_ipv6
*p
= (struct prefix_ipv6
*) &rp
->p
;
1076 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
1077 inet6_ntoa(p
->prefix
), p
->prefixlen
,
1078 ifindex2ifname(rinfo
->ifindex
, VRF_DEFAULT
));
1081 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1086 /* RIP routing information. */
1088 ripng_response_process (struct ripng_packet
*packet
, int size
,
1089 struct sockaddr_in6
*from
, struct interface
*ifp
,
1094 struct ripng_nexthop nexthop
;
1096 /* RFC2080 2.4.2 Response Messages:
1097 The Response must be ignored if it is not from the RIPng port. */
1098 if (ntohs (from
->sin6_port
) != RIPNG_PORT_DEFAULT
)
1100 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
1101 ntohs (from
->sin6_port
), inet6_ntoa (from
->sin6_addr
));
1102 ripng_peer_bad_packet (from
);
1106 /* The datagram's IPv6 source address should be checked to see
1107 whether the datagram is from a valid neighbor; the source of the
1108 datagram must be a link-local address. */
1109 if (! IN6_IS_ADDR_LINKLOCAL(&from
->sin6_addr
))
1111 zlog_warn ("RIPng packet comes from non link local address %s",
1112 inet6_ntoa (from
->sin6_addr
));
1113 ripng_peer_bad_packet (from
);
1117 /* It is also worth checking to see whether the response is from one
1118 of the router's own addresses. Interfaces on broadcast networks
1119 may receive copies of their own multicasts immediately. If a
1120 router processes its own output as new input, confusion is likely,
1121 and such datagrams must be ignored. */
1122 if (ripng_lladdr_check (ifp
, &from
->sin6_addr
))
1124 zlog_warn ("RIPng packet comes from my own link local address %s",
1125 inet6_ntoa (from
->sin6_addr
));
1126 ripng_peer_bad_packet (from
);
1130 /* As an additional check, periodic advertisements must have their
1131 hop counts set to 255, and inbound, multicast packets sent from the
1132 RIPng port (i.e. periodic advertisement or triggered update
1133 packets) must be examined to ensure that the hop count is 255. */
1134 if (hoplimit
>= 0 && hoplimit
!= 255)
1136 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
1137 hoplimit
, inet6_ntoa (from
->sin6_addr
));
1138 ripng_peer_bad_packet (from
);
1142 /* Update RIPng peer. */
1143 ripng_peer_update (from
, packet
->version
);
1145 /* Reset nexthop. */
1146 memset (&nexthop
, 0, sizeof (struct ripng_nexthop
));
1147 nexthop
.flag
= RIPNG_NEXTHOP_UNSPEC
;
1149 /* Set RTE pointer. */
1152 for (lim
= ((caddr_t
) packet
) + size
; (caddr_t
) rte
< lim
; rte
++)
1154 /* First of all, we have to check this RTE is next hop RTE or
1155 not. Next hop RTE is completely different with normal RTE so
1156 we need special treatment. */
1157 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
1159 ripng_nexthop_rte (rte
, from
, &nexthop
);
1163 /* RTE information validation. */
1165 /* - is the destination prefix valid (e.g., not a multicast
1166 prefix and not a link-local address) A link-local address
1167 should never be present in an RTE. */
1168 if (IN6_IS_ADDR_MULTICAST (&rte
->addr
))
1170 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
1171 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1172 ripng_peer_bad_route (from
);
1175 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
1177 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
1178 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1179 ripng_peer_bad_route (from
);
1182 if (IN6_IS_ADDR_LOOPBACK (&rte
->addr
))
1184 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
1185 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1186 ripng_peer_bad_route (from
);
1190 /* - is the prefix length valid (i.e., between 0 and 128,
1192 if (rte
->prefixlen
> 128)
1194 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
1195 inet6_ntoa (rte
->addr
), rte
->prefixlen
,
1196 inet6_ntoa (from
->sin6_addr
), ifp
->name
);
1197 ripng_peer_bad_route (from
);
1201 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1202 if (! (rte
->metric
>= 1 && rte
->metric
<= 16))
1204 zlog_warn ("Invalid metric %d from %s%%%s", rte
->metric
,
1205 inet6_ntoa (from
->sin6_addr
), ifp
->name
);
1206 ripng_peer_bad_route (from
);
1210 /* Vincent: XXX Should we compute the direclty reachable nexthop
1211 * for our RIPng network ?
1214 /* Routing table updates. */
1215 ripng_route_process (rte
, from
, &nexthop
, ifp
);
1219 /* Response to request message. */
1221 ripng_request_process (struct ripng_packet
*packet
,int size
,
1222 struct sockaddr_in6
*from
, struct interface
*ifp
)
1226 struct prefix_ipv6 p
;
1227 struct route_node
*rp
;
1228 struct ripng_info
*rinfo
;
1229 struct ripng_interface
*ri
;
1231 /* Does not reponse to the requests on the loopback interfaces */
1232 if (if_is_loopback (ifp
))
1235 /* Check RIPng process is enabled on this interface. */
1240 /* When passive interface is specified, suppress responses */
1244 /* RIPng peer update. */
1245 ripng_peer_update (from
, packet
->version
);
1247 lim
= ((caddr_t
) packet
) + size
;
1250 /* The Request is processed entry by entry. If there are no
1251 entries, no response is given. */
1252 if (lim
== (caddr_t
) rte
)
1255 /* There is one special case. If there is exactly one entry in the
1256 request, and it has a destination prefix of zero, a prefix length
1257 of zero, and a metric of infinity (i.e., 16), then this is a
1258 request to send the entire routing table. In that case, a call
1259 is made to the output process to send the routing table to the
1260 requesting address/port. */
1261 if (lim
== ((caddr_t
) (rte
+ 1)) &&
1262 IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
) &&
1263 rte
->prefixlen
== 0 &&
1264 rte
->metric
== RIPNG_METRIC_INFINITY
)
1266 /* All route with split horizon */
1267 ripng_output_process (ifp
, from
, ripng_all_route
);
1271 /* Except for this special case, processing is quite simple.
1272 Examine the list of RTEs in the Request one by one. For each
1273 entry, look up the destination in the router's routing
1274 database and, if there is a route, put that route's metric in
1275 the metric field of the RTE. If there is no explicit route
1276 to the specified destination, put infinity in the metric
1277 field. Once all the entries have been filled in, change the
1278 command from Request to Response and send the datagram back
1279 to the requestor. */
1280 memset (&p
, 0, sizeof (struct prefix_ipv6
));
1281 p
.family
= AF_INET6
;
1283 for (; ((caddr_t
) rte
) < lim
; rte
++)
1285 p
.prefix
= rte
->addr
;
1286 p
.prefixlen
= rte
->prefixlen
;
1287 apply_mask_ipv6 (&p
);
1289 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) &p
);
1293 rinfo
= listgetdata (listhead ((struct list
*)rp
->info
));
1294 rte
->metric
= rinfo
->metric
;
1295 route_unlock_node (rp
);
1298 rte
->metric
= RIPNG_METRIC_INFINITY
;
1300 packet
->command
= RIPNG_RESPONSE
;
1302 ripng_send_packet ((caddr_t
) packet
, size
, from
, ifp
);
1306 /* First entry point of reading RIPng packet. */
1308 ripng_read (struct thread
*thread
)
1312 struct sockaddr_in6 from
;
1313 struct ripng_packet
*packet
;
1314 ifindex_t ifindex
= 0;
1315 struct interface
*ifp
;
1318 /* Check ripng is active and alive. */
1319 assert (ripng
!= NULL
);
1320 assert (ripng
->sock
>= 0);
1322 /* Fetch thread data and set read pointer to empty for event
1323 managing. `sock' sould be same as ripng->sock. */
1324 sock
= THREAD_FD (thread
);
1325 ripng
->t_read
= NULL
;
1327 /* Add myself to the next event. */
1328 ripng_event (RIPNG_READ
, sock
);
1330 /* Read RIPng packet. */
1331 len
= ripng_recv_packet (sock
, STREAM_DATA (ripng
->ibuf
),
1332 STREAM_SIZE (ripng
->ibuf
), &from
, &ifindex
,
1336 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno
));
1340 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1341 (4)) must be multiple size of one RTE size (20). */
1342 if (((len
- 4) % 20) != 0)
1344 zlog_warn ("RIPng invalid packet size %d from %s", len
,
1345 inet6_ntoa (from
.sin6_addr
));
1346 ripng_peer_bad_packet (&from
);
1350 packet
= (struct ripng_packet
*) STREAM_DATA (ripng
->ibuf
);
1351 ifp
= if_lookup_by_index (ifindex
, VRF_DEFAULT
);
1353 /* RIPng packet received. */
1354 if (IS_RIPNG_DEBUG_EVENT
)
1355 zlog_debug ("RIPng packet received from %s port %d on %s",
1356 inet6_ntoa (from
.sin6_addr
), ntohs (from
.sin6_port
),
1357 ifp
? ifp
->name
: "unknown");
1359 /* Logging before packet checking. */
1360 if (IS_RIPNG_DEBUG_RECV
)
1361 ripng_packet_dump (packet
, len
, "RECV");
1363 /* Packet comes from unknown interface. */
1366 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex
);
1370 /* Packet version mismatch checking. */
1371 if (packet
->version
!= ripng
->version
)
1373 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1374 packet
->version
, ripng
->version
);
1375 ripng_peer_bad_packet (&from
);
1379 /* Process RIPng packet. */
1380 switch (packet
->command
)
1383 ripng_request_process (packet
, len
, &from
, ifp
);
1385 case RIPNG_RESPONSE
:
1386 ripng_response_process (packet
, len
, &from
, ifp
, hoplimit
);
1389 zlog_warn ("Invalid RIPng command %d", packet
->command
);
1390 ripng_peer_bad_packet (&from
);
1396 /* Walk down the RIPng routing table then clear changed flag. */
1398 ripng_clear_changed_flag (void)
1400 struct route_node
*rp
;
1401 struct ripng_info
*rinfo
= NULL
;
1402 struct list
*list
= NULL
;
1403 struct listnode
*listnode
= NULL
;
1405 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1406 if ((list
= rp
->info
) != NULL
)
1407 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, rinfo
))
1409 UNSET_FLAG (rinfo
->flags
, RIPNG_RTF_CHANGED
);
1410 /* This flag can be set only on the first entry. */
1415 /* Regular update of RIPng route. Send all routing formation to RIPng
1416 enabled interface. */
1418 ripng_update (struct thread
*t
)
1420 struct listnode
*node
;
1421 struct interface
*ifp
;
1422 struct ripng_interface
*ri
;
1424 /* Clear update timer thread. */
1425 ripng
->t_update
= NULL
;
1427 /* Logging update event. */
1428 if (IS_RIPNG_DEBUG_EVENT
)
1429 zlog_debug ("RIPng update timer expired!");
1431 /* Supply routes to each interface. */
1432 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
1436 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1442 /* When passive interface is specified, suppress announce to the
1448 if (ri
->ri_send
== RIPNG_SEND_OFF
)
1450 if (IS_RIPNG_DEBUG_EVENT
)
1451 zlog_debug ("[Event] RIPng send to if %d is suppressed by config",
1455 #endif /* RIPNG_ADVANCED */
1457 ripng_output_process (ifp
, NULL
, ripng_all_route
);
1460 /* Triggered updates may be suppressed if a regular update is due by
1461 the time the triggered update would be sent. */
1462 if (ripng
->t_triggered_interval
)
1464 thread_cancel (ripng
->t_triggered_interval
);
1465 ripng
->t_triggered_interval
= NULL
;
1469 /* Reset flush event. */
1470 ripng_event (RIPNG_UPDATE_EVENT
, 0);
1475 /* Triggered update interval timer. */
1477 ripng_triggered_interval (struct thread
*t
)
1479 ripng
->t_triggered_interval
= NULL
;
1484 ripng_triggered_update (t
);
1489 /* Execute triggered update. */
1491 ripng_triggered_update (struct thread
*t
)
1493 struct listnode
*node
;
1494 struct interface
*ifp
;
1495 struct ripng_interface
*ri
;
1498 ripng
->t_triggered_update
= NULL
;
1500 /* Cancel interval timer. */
1501 if (ripng
->t_triggered_interval
)
1503 thread_cancel (ripng
->t_triggered_interval
);
1504 ripng
->t_triggered_interval
= NULL
;
1508 /* Logging triggered update. */
1509 if (IS_RIPNG_DEBUG_EVENT
)
1510 zlog_debug ("RIPng triggered update!");
1512 /* Split Horizon processing is done when generating triggered
1513 updates as well as normal updates (see section 2.6). */
1514 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
1518 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1524 /* When passive interface is specified, suppress announce to the
1529 ripng_output_process (ifp
, NULL
, ripng_changed_route
);
1532 /* Once all of the triggered updates have been generated, the route
1533 change flags should be cleared. */
1534 ripng_clear_changed_flag ();
1536 /* After a triggered update is sent, a timer should be set for a
1537 random interval between 1 and 5 seconds. If other changes that
1538 would trigger updates occur before the timer expires, a single
1539 update is triggered when the timer expires. */
1540 interval
= (random () % 5) + 1;
1542 ripng
->t_triggered_interval
=
1543 thread_add_timer (master
, ripng_triggered_interval
, NULL
, interval
);
1548 /* Write routing table entry to the stream and return next index of
1549 the routing table entry in the stream. */
1551 ripng_write_rte (int num
, struct stream
*s
, struct prefix_ipv6
*p
,
1552 struct in6_addr
*nexthop
, u_int16_t tag
, u_char metric
)
1554 /* RIPng packet header. */
1557 stream_putc (s
, RIPNG_RESPONSE
);
1558 stream_putc (s
, RIPNG_V1
);
1562 /* Write routing table entry. */
1564 stream_write (s
, (u_char
*) &p
->prefix
, sizeof (struct in6_addr
));
1566 stream_write (s
, (u_char
*) nexthop
, sizeof (struct in6_addr
));
1567 stream_putw (s
, tag
);
1569 stream_putc (s
, p
->prefixlen
);
1572 stream_putc (s
, metric
);
1577 /* Send RESPONSE message to specified destination. */
1579 ripng_output_process (struct interface
*ifp
, struct sockaddr_in6
*to
,
1583 struct route_node
*rp
;
1584 struct ripng_info
*rinfo
;
1585 struct ripng_interface
*ri
;
1586 struct ripng_aggregate
*aggregate
;
1587 struct prefix_ipv6
*p
;
1588 struct list
* ripng_rte_list
;
1589 struct list
*list
= NULL
;
1590 struct listnode
*listnode
= NULL
;
1592 if (IS_RIPNG_DEBUG_EVENT
) {
1594 zlog_debug ("RIPng update routes to neighbor %s",
1595 inet6_ntoa(to
->sin6_addr
));
1597 zlog_debug ("RIPng update routes on interface %s", ifp
->name
);
1600 /* Get RIPng interface. */
1603 ripng_rte_list
= ripng_rte_new();
1605 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1607 if ((list
= rp
->info
) != NULL
&&
1608 (rinfo
= listgetdata (listhead (list
))) != NULL
&&
1609 rinfo
->suppress
== 0)
1611 /* If no route-map are applied, the RTE will be these following
1614 p
= (struct prefix_ipv6
*) &rp
->p
;
1615 rinfo
->metric_out
= rinfo
->metric
;
1616 rinfo
->tag_out
= rinfo
->tag
;
1617 memset(&rinfo
->nexthop_out
, 0, sizeof(rinfo
->nexthop_out
));
1618 /* In order to avoid some local loops,
1619 * if the RIPng route has a nexthop via this interface, keep the nexthop,
1620 * otherwise set it to 0. The nexthop should not be propagated
1621 * beyond the local broadcast/multicast area in order
1622 * to avoid an IGP multi-level recursive look-up.
1624 if (rinfo
->ifindex
== ifp
->ifindex
)
1625 rinfo
->nexthop_out
= rinfo
->nexthop
;
1627 /* Apply output filters. */
1628 ret
= ripng_filter (RIPNG_FILTER_OUT
, p
, ri
);
1632 /* Changed route only output. */
1633 if (route_type
== ripng_changed_route
&&
1634 (! (rinfo
->flags
& RIPNG_RTF_CHANGED
)))
1637 /* Split horizon. */
1638 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON
)
1640 /* We perform split horizon for RIPng routes. */
1642 struct ripng_info
*tmp_rinfo
= NULL
;
1644 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, tmp_rinfo
))
1645 if (tmp_rinfo
->type
== ZEBRA_ROUTE_RIPNG
&&
1646 tmp_rinfo
->ifindex
== ifp
->ifindex
)
1655 /* Preparation for route-map. */
1656 rinfo
->metric_set
= 0;
1659 * and tag_out are already initialized.
1662 /* Interface route-map */
1663 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1667 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1668 (struct prefix
*) p
, RMAP_RIPNG
,
1671 if (ret
== RMAP_DENYMATCH
)
1673 if (IS_RIPNG_DEBUG_PACKET
)
1674 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1675 inet6_ntoa (p
->prefix
), p
->prefixlen
);
1681 /* Redistribute route-map. */
1682 if (ripng
->route_map
[rinfo
->type
].name
)
1686 ret
= route_map_apply (ripng
->route_map
[rinfo
->type
].map
,
1687 (struct prefix
*) p
, RMAP_RIPNG
,
1690 if (ret
== RMAP_DENYMATCH
)
1692 if (IS_RIPNG_DEBUG_PACKET
)
1693 zlog_debug ("RIPng %s/%d is filtered by route-map",
1694 inet6_ntoa (p
->prefix
), p
->prefixlen
);
1699 /* When the route-map does not set metric. */
1700 if (! rinfo
->metric_set
)
1702 /* If the redistribute metric is set. */
1703 if (ripng
->route_map
[rinfo
->type
].metric_config
1704 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1706 rinfo
->metric_out
= ripng
->route_map
[rinfo
->type
].metric
;
1710 /* If the route is not connected or localy generated
1711 one, use default-metric value */
1712 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
1713 && rinfo
->type
!= ZEBRA_ROUTE_CONNECT
1714 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1715 rinfo
->metric_out
= ripng
->default_metric
;
1719 /* Apply offset-list */
1720 if (rinfo
->metric_out
!= RIPNG_METRIC_INFINITY
)
1721 ripng_offset_list_apply_out (p
, ifp
, &rinfo
->metric_out
);
1723 if (rinfo
->metric_out
> RIPNG_METRIC_INFINITY
)
1724 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1726 /* Perform split-horizon with poisoned reverse
1729 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON_POISONED_REVERSE
) {
1730 struct ripng_info
*tmp_rinfo
= NULL
;
1732 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, tmp_rinfo
))
1733 if ((tmp_rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1734 tmp_rinfo
->ifindex
== ifp
->ifindex
)
1735 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1738 /* Add RTE to the list */
1739 ripng_rte_add(ripng_rte_list
, p
, rinfo
, NULL
);
1742 /* Process the aggregated RTE entry */
1743 if ((aggregate
= rp
->aggregate
) != NULL
&&
1744 aggregate
->count
> 0 &&
1745 aggregate
->suppress
== 0)
1747 /* If no route-map are applied, the RTE will be these following
1750 p
= (struct prefix_ipv6
*) &rp
->p
;
1751 aggregate
->metric_set
= 0;
1752 aggregate
->metric_out
= aggregate
->metric
;
1753 aggregate
->tag_out
= aggregate
->tag
;
1754 memset(&aggregate
->nexthop_out
, 0, sizeof(aggregate
->nexthop_out
));
1756 /* Apply output filters.*/
1757 ret
= ripng_filter (RIPNG_FILTER_OUT
, p
, ri
);
1761 /* Interface route-map */
1762 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1765 struct ripng_info newinfo
;
1767 /* let's cast the aggregate structure to ripng_info */
1768 memset (&newinfo
, 0, sizeof (struct ripng_info
));
1769 /* the nexthop is :: */
1770 newinfo
.metric
= aggregate
->metric
;
1771 newinfo
.metric_out
= aggregate
->metric_out
;
1772 newinfo
.tag
= aggregate
->tag
;
1773 newinfo
.tag_out
= aggregate
->tag_out
;
1775 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1776 (struct prefix
*) p
, RMAP_RIPNG
,
1779 if (ret
== RMAP_DENYMATCH
)
1781 if (IS_RIPNG_DEBUG_PACKET
)
1782 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1783 inet6_ntoa (p
->prefix
), p
->prefixlen
);
1787 aggregate
->metric_out
= newinfo
.metric_out
;
1788 aggregate
->tag_out
= newinfo
.tag_out
;
1789 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop_out
))
1790 aggregate
->nexthop_out
= newinfo
.nexthop_out
;
1793 /* There is no redistribute routemap for the aggregated RTE */
1795 /* Changed route only output. */
1796 /* XXX, vincent, in order to increase time convergence,
1797 * it should be announced if a child has changed.
1799 if (route_type
== ripng_changed_route
)
1802 /* Apply offset-list */
1803 if (aggregate
->metric_out
!= RIPNG_METRIC_INFINITY
)
1804 ripng_offset_list_apply_out (p
, ifp
, &aggregate
->metric_out
);
1806 if (aggregate
->metric_out
> RIPNG_METRIC_INFINITY
)
1807 aggregate
->metric_out
= RIPNG_METRIC_INFINITY
;
1809 /* Add RTE to the list */
1810 ripng_rte_add(ripng_rte_list
, p
, NULL
, aggregate
);
1815 /* Flush the list */
1816 ripng_rte_send(ripng_rte_list
, ifp
, to
);
1817 ripng_rte_free(ripng_rte_list
);
1820 /* Create new RIPng instance and set it to global variable. */
1824 /* ripng should be NULL. */
1825 assert (ripng
== NULL
);
1827 /* Allocaste RIPng instance. */
1828 ripng
= XCALLOC (MTYPE_RIPNG
, sizeof (struct ripng
));
1830 /* Default version and timer values. */
1831 ripng
->version
= RIPNG_V1
;
1832 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
1833 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
1834 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
1835 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
1838 ripng
->ibuf
= stream_new (RIPNG_MAX_PACKET_SIZE
* 5);
1839 ripng
->obuf
= stream_new (RIPNG_MAX_PACKET_SIZE
);
1841 /* Initialize RIPng routig table. */
1842 ripng
->table
= route_table_init ();
1843 ripng
->route
= route_table_init ();
1844 ripng
->aggregate
= route_table_init ();
1847 ripng
->sock
= ripng_make_socket ();
1848 if (ripng
->sock
< 0)
1852 ripng_event (RIPNG_READ
, ripng
->sock
);
1853 ripng_event (RIPNG_UPDATE_EVENT
, 1);
1858 /* Send RIPng request to the interface. */
1860 ripng_request (struct interface
*ifp
)
1863 struct ripng_packet ripng_packet
;
1865 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
1866 if (if_is_loopback(ifp
))
1869 /* If interface is down, don't send RIP packet. */
1870 if (! if_is_up (ifp
))
1873 if (IS_RIPNG_DEBUG_EVENT
)
1874 zlog_debug ("RIPng send request to %s", ifp
->name
);
1876 memset (&ripng_packet
, 0, sizeof (ripng_packet
));
1877 ripng_packet
.command
= RIPNG_REQUEST
;
1878 ripng_packet
.version
= RIPNG_V1
;
1879 rte
= ripng_packet
.rte
;
1880 rte
->metric
= RIPNG_METRIC_INFINITY
;
1882 return ripng_send_packet ((caddr_t
) &ripng_packet
, sizeof (ripng_packet
),
1888 ripng_update_jitter (int time
)
1890 return ((random () % (time
+ 1)) - (time
/ 2));
1894 ripng_event (enum ripng_event event
, int sock
)
1902 ripng
->t_read
= thread_add_read (master
, ripng_read
, NULL
, sock
);
1904 case RIPNG_UPDATE_EVENT
:
1905 if (ripng
->t_update
)
1907 thread_cancel (ripng
->t_update
);
1908 ripng
->t_update
= NULL
;
1910 /* Update timer jitter. */
1911 jitter
= ripng_update_jitter (ripng
->update_time
);
1914 thread_add_timer (master
, ripng_update
, NULL
,
1915 sock
? 2 : ripng
->update_time
+ jitter
);
1917 case RIPNG_TRIGGERED_UPDATE
:
1918 if (ripng
->t_triggered_interval
)
1920 else if (! ripng
->t_triggered_update
)
1921 ripng
->t_triggered_update
=
1922 thread_add_event (master
, ripng_triggered_update
, NULL
, 0);
1930 /* Print out routes update time. */
1932 ripng_vty_out_uptime (struct vty
*vty
, struct ripng_info
*rinfo
)
1937 char timebuf
[TIME_BUF
];
1938 struct thread
*thread
;
1940 if ((thread
= rinfo
->t_timeout
) != NULL
)
1942 clock
= thread_timer_remain_second (thread
);
1943 tm
= gmtime (&clock
);
1944 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1945 vty_out (vty
, "%5s", timebuf
);
1947 else if ((thread
= rinfo
->t_garbage_collect
) != NULL
)
1949 clock
= thread_timer_remain_second (thread
);
1950 tm
= gmtime (&clock
);
1951 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1952 vty_out (vty
, "%5s", timebuf
);
1957 ripng_route_subtype_print (struct ripng_info
*rinfo
)
1962 if (rinfo
->suppress
)
1965 switch (rinfo
->sub_type
)
1967 case RIPNG_ROUTE_RTE
:
1970 case RIPNG_ROUTE_STATIC
:
1973 case RIPNG_ROUTE_DEFAULT
:
1976 case RIPNG_ROUTE_REDISTRIBUTE
:
1979 case RIPNG_ROUTE_INTERFACE
:
1990 DEFUN (show_ipv6_ripng
,
1991 show_ipv6_ripng_cmd
,
1995 "Show RIPng routes\n")
1997 struct route_node
*rp
;
1998 struct ripng_info
*rinfo
;
1999 struct ripng_aggregate
*aggregate
;
2000 struct prefix_ipv6
*p
;
2001 struct list
*list
= NULL
;
2002 struct listnode
*listnode
= NULL
;
2008 /* Header of display. */
2009 vty_out (vty
, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2011 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2012 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2013 " Network Next Hop Via Metric Tag Time%s",
2014 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2015 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
2017 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2019 if ((aggregate
= rp
->aggregate
) != NULL
)
2021 p
= (struct prefix_ipv6
*) &rp
->p
;
2024 len
= vty_out (vty
, "R(a) %d/%d %s/%d ",
2025 aggregate
->count
, aggregate
->suppress
,
2026 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2028 len
= vty_out (vty
, "R(a) %s/%d ",
2029 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2031 vty_out (vty
, "%s", VTY_NEWLINE
);
2032 vty_out (vty
, "%*s", 18, " ");
2034 vty_out (vty
, "%*s", 28, " ");
2035 vty_out (vty
, "self %2d %3"ROUTE_TAG_PRI
"%s", aggregate
->metric
,
2036 (route_tag_t
)aggregate
->tag
,
2040 if ((list
= rp
->info
) != NULL
)
2041 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, rinfo
))
2043 p
= (struct prefix_ipv6
*) &rp
->p
;
2046 len
= vty_out (vty
, "%c(%s) 0/%d %s/%d ",
2047 zebra_route_char(rinfo
->type
),
2048 ripng_route_subtype_print(rinfo
),
2050 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2052 len
= vty_out (vty
, "%c(%s) %s/%d ",
2053 zebra_route_char(rinfo
->type
),
2054 ripng_route_subtype_print(rinfo
),
2055 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2057 vty_out (vty
, "%s", VTY_NEWLINE
);
2058 vty_out (vty
, "%*s", 18, " ");
2059 len
= vty_out (vty
, "%s", inet6_ntoa (rinfo
->nexthop
));
2063 len
= vty_out (vty
, "%*s", len
, " ");
2066 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2067 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2069 len
= vty_out (vty
, "%s", ifindex2ifname(rinfo
->ifindex
, VRF_DEFAULT
));
2070 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2072 len
= vty_out (vty
, "kill");
2074 len
= vty_out (vty
, "self");
2078 vty_out (vty
, "%*s", len
, " ");
2080 vty_out (vty
, " %2d %3"ROUTE_TAG_PRI
" ",
2081 rinfo
->metric
, (route_tag_t
)rinfo
->tag
);
2084 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2085 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2087 /* RTE from remote RIP routers */
2088 ripng_vty_out_uptime (vty
, rinfo
);
2089 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2091 /* poisonous reversed routes (gc) */
2092 ripng_vty_out_uptime (vty
, rinfo
);
2095 vty_out (vty
, "%s", VTY_NEWLINE
);
2102 DEFUN (show_ipv6_ripng_status
,
2103 show_ipv6_ripng_status_cmd
,
2104 "show ipv6 ripng status",
2107 "Show RIPng routes\n"
2108 "IPv6 routing protocol process parameters and statistics\n")
2110 struct listnode
*node
;
2111 struct interface
*ifp
;
2116 vty_out (vty
, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE
);
2117 vty_out (vty
, " Sending updates every %ld seconds with +/-50%%,",
2118 ripng
->update_time
);
2119 vty_out (vty
, " next due in %lu seconds%s",
2120 thread_timer_remain_second (ripng
->t_update
),
2122 vty_out (vty
, " Timeout after %ld seconds,", ripng
->timeout_time
);
2123 vty_out (vty
, " garbage collect after %ld seconds%s", ripng
->garbage_time
,
2126 /* Filtering status show. */
2127 config_show_distribute (vty
);
2129 /* Default metric information. */
2130 vty_out (vty
, " Default redistribution metric is %d%s",
2131 ripng
->default_metric
, VTY_NEWLINE
);
2133 /* Redistribute information. */
2134 vty_out (vty
, " Redistributing:");
2135 ripng_redistribute_write (vty
, 0);
2136 vty_out (vty
, "%s", VTY_NEWLINE
);
2138 vty_out (vty
, " Default version control: send version %d,", ripng
->version
);
2139 vty_out (vty
, " receive version %d %s", ripng
->version
,
2142 vty_out (vty
, " Interface Send Recv%s", VTY_NEWLINE
);
2144 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
2146 struct ripng_interface
*ri
;
2150 if (ri
->enable_network
|| ri
->enable_interface
)
2153 vty_out (vty
, " %-17s%-3d %-3d%s", ifp
->name
,
2160 vty_out (vty
, " Routing for Networks:%s", VTY_NEWLINE
);
2161 ripng_network_write (vty
, 0);
2163 vty_out (vty
, " Routing Information Sources:%s", VTY_NEWLINE
);
2164 vty_out (vty
, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE
);
2165 ripng_peer_display (vty
);
2170 DEFUN (clear_ipv6_rip
,
2175 "Clear IPv6 RIP database")
2177 struct route_node
*rp
;
2178 struct ripng_info
*rinfo
;
2180 struct listnode
*listnode
;
2182 /* Clear received RIPng routes */
2183 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2189 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, rinfo
))
2191 if (! ripng_route_rte (rinfo
))
2194 if (CHECK_FLAG (rinfo
->flags
, RIPNG_RTF_FIB
))
2195 ripng_zebra_ipv6_delete (rp
);
2201 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
2202 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
2203 listnode_delete (list
, rinfo
);
2204 ripng_info_free (rinfo
);
2207 if (list_isempty (list
))
2211 route_unlock_node (rp
);
2218 DEFUN_NOSH (router_ripng
,
2221 "Enable a routing process\n"
2222 "Make RIPng instance command\n")
2226 vty
->node
= RIPNG_NODE
;
2230 ret
= ripng_create ();
2232 /* Notice to user we couldn't create RIPng. */
2235 zlog_warn ("can't create RIPng");
2243 DEFUN (no_router_ripng
,
2244 no_router_ripng_cmd
,
2247 "Enable a routing process\n"
2248 "Make RIPng instance command\n")
2258 "Static route setup\n"
2259 "Set static RIPng route announcement\n")
2261 int idx_ipv6addr
= 1;
2263 struct prefix_ipv6 p
;
2264 struct route_node
*rp
;
2266 ret
= str2prefix_ipv6 (argv
[idx_ipv6addr
]->arg
, (struct prefix_ipv6
*)&p
);
2269 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2272 apply_mask_ipv6 (&p
);
2274 rp
= route_node_get (ripng
->route
, (struct prefix
*) &p
);
2277 vty_out (vty
, "There is already same static route.%s", VTY_NEWLINE
);
2278 route_unlock_node (rp
);
2281 rp
->info
= (void *)1;
2283 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0, NULL
, 0);
2288 DEFUN (no_ripng_route
,
2290 "no route IPV6ADDR",
2292 "Static route setup\n"
2293 "Delete static RIPng route announcement\n")
2295 int idx_ipv6addr
= 2;
2297 struct prefix_ipv6 p
;
2298 struct route_node
*rp
;
2300 ret
= str2prefix_ipv6 (argv
[idx_ipv6addr
]->arg
, (struct prefix_ipv6
*)&p
);
2303 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2306 apply_mask_ipv6 (&p
);
2308 rp
= route_node_lookup (ripng
->route
, (struct prefix
*) &p
);
2311 vty_out (vty
, "Can't find static route.%s", VTY_NEWLINE
);
2315 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0);
2316 route_unlock_node (rp
);
2319 route_unlock_node (rp
);
2324 DEFUN (ripng_aggregate_address
,
2325 ripng_aggregate_address_cmd
,
2326 "aggregate-address X:X::X:X/M",
2327 "Set aggregate RIPng route announcement\n"
2328 "Aggregate network\n")
2330 int idx_ipv6_prefixlen
= 1;
2333 struct route_node
*node
;
2335 ret
= str2prefix_ipv6 (argv
[idx_ipv6_prefixlen
]->arg
, (struct prefix_ipv6
*)&p
);
2338 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2342 /* Check aggregate alredy exist or not. */
2343 node
= route_node_get (ripng
->aggregate
, &p
);
2346 vty_out (vty
, "There is already same aggregate route.%s", VTY_NEWLINE
);
2347 route_unlock_node (node
);
2350 node
->info
= (void *)1;
2352 ripng_aggregate_add (&p
);
2357 DEFUN (no_ripng_aggregate_address
,
2358 no_ripng_aggregate_address_cmd
,
2359 "no aggregate-address X:X::X:X/M",
2361 "Delete aggregate RIPng route announcement\n"
2362 "Aggregate network")
2364 int idx_ipv6_prefixlen
= 2;
2367 struct route_node
*rn
;
2369 ret
= str2prefix_ipv6 (argv
[idx_ipv6_prefixlen
]->arg
, (struct prefix_ipv6
*) &p
);
2372 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2376 rn
= route_node_lookup (ripng
->aggregate
, &p
);
2379 vty_out (vty
, "Can't find aggregate route.%s", VTY_NEWLINE
);
2382 route_unlock_node (rn
);
2384 route_unlock_node (rn
);
2386 ripng_aggregate_delete (&p
);
2391 DEFUN (ripng_default_metric
,
2392 ripng_default_metric_cmd
,
2393 "default-metric (1-16)",
2394 "Set a metric of redistribute routes\n"
2400 ripng
->default_metric
= atoi (argv
[idx_number
]->arg
);
2405 DEFUN (no_ripng_default_metric
,
2406 no_ripng_default_metric_cmd
,
2407 "no default-metric [(1-16)]",
2409 "Set a metric of redistribute routes\n"
2414 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
2421 /* RIPng update timer setup. */
2422 DEFUN (ripng_update_timer
,
2423 ripng_update_timer_cmd
,
2424 "update-timer SECOND",
2425 "Set RIPng update timer in seconds\n"
2428 unsigned long update
;
2429 char *endptr
= NULL
;
2431 update
= strtoul (argv
[0], &endptr
, 10);
2432 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2434 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2438 ripng
->update_time
= update
;
2440 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2444 DEFUN (no_ripng_update_timer
,
2445 no_ripng_update_timer_cmd
,
2446 "no update-timer SECOND",
2448 "Unset RIPng update timer in seconds\n"
2451 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2452 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2456 /* RIPng timeout timer setup. */
2457 DEFUN (ripng_timeout_timer
,
2458 ripng_timeout_timer_cmd
,
2459 "timeout-timer SECOND",
2460 "Set RIPng timeout timer in seconds\n"
2463 unsigned long timeout
;
2464 char *endptr
= NULL
;
2466 timeout
= strtoul (argv
[0], &endptr
, 10);
2467 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2469 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2473 ripng
->timeout_time
= timeout
;
2478 DEFUN (no_ripng_timeout_timer
,
2479 no_ripng_timeout_timer_cmd
,
2480 "no timeout-timer SECOND",
2482 "Unset RIPng timeout timer in seconds\n"
2485 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2489 /* RIPng garbage timer setup. */
2490 DEFUN (ripng_garbage_timer
,
2491 ripng_garbage_timer_cmd
,
2492 "garbage-timer SECOND",
2493 "Set RIPng garbage timer in seconds\n"
2496 unsigned long garbage
;
2497 char *endptr
= NULL
;
2499 garbage
= strtoul (argv
[0], &endptr
, 10);
2500 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2502 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2506 ripng
->garbage_time
= garbage
;
2511 DEFUN (no_ripng_garbage_timer
,
2512 no_ripng_garbage_timer_cmd
,
2513 "no garbage-timer SECOND",
2515 "Unset RIPng garbage timer in seconds\n"
2518 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2523 DEFUN (ripng_timers
,
2525 "timers basic (0-65535) (0-65535) (0-65535)",
2526 "RIPng timers setup\n"
2528 "Routing table update timer value in second. Default is 30.\n"
2529 "Routing information timeout timer. Default is 180.\n"
2530 "Garbage collection timer. Default is 120.\n")
2533 int idx_number_2
= 3;
2534 int idx_number_3
= 4;
2535 unsigned long update
;
2536 unsigned long timeout
;
2537 unsigned long garbage
;
2539 VTY_GET_INTEGER_RANGE("update timer", update
, argv
[idx_number
]->arg
, 0, 65535);
2540 VTY_GET_INTEGER_RANGE("timeout timer", timeout
, argv
[idx_number_2
]->arg
, 0, 65535);
2541 VTY_GET_INTEGER_RANGE("garbage timer", garbage
, argv
[idx_number_3
]->arg
, 0, 65535);
2543 /* Set each timer value. */
2544 ripng
->update_time
= update
;
2545 ripng
->timeout_time
= timeout
;
2546 ripng
->garbage_time
= garbage
;
2548 /* Reset update timer thread. */
2549 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2554 DEFUN (no_ripng_timers
,
2555 no_ripng_timers_cmd
,
2556 "no timers basic [(0-65535) (0-65535) (0-65535)]",
2558 "RIPng timers setup\n"
2560 "Routing table update timer value in second. Default is 30.\n"
2561 "Routing information timeout timer. Default is 180.\n"
2562 "Garbage collection timer. Default is 120.\n")
2564 /* Set each timer value to the default. */
2565 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2566 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2567 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2569 /* Reset update timer thread. */
2570 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2576 DEFUN (show_ipv6_protocols
,
2577 show_ipv6_protocols_cmd
,
2578 "show ipv6 protocols",
2581 "Routing protocol information")
2586 vty_out (vty
, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE
);
2588 vty_out (vty
, "Sending updates every %ld seconds, next due in %d seconds%s",
2589 ripng
->update_time
, 0,
2592 vty_out (vty
, "Timerout after %ld seconds, garbage correct %ld%s",
2593 ripng
->timeout_time
,
2594 ripng
->garbage_time
,
2597 vty_out (vty
, "Outgoing update filter list for all interfaces is not set");
2598 vty_out (vty
, "Incoming update filter list for all interfaces is not set");
2604 /* Please be carefull to use this command. */
2605 DEFUN (ripng_default_information_originate
,
2606 ripng_default_information_originate_cmd
,
2607 "default-information originate",
2608 "Default route information\n"
2609 "Distribute default route\n")
2611 struct prefix_ipv6 p
;
2613 if (! ripng
->default_information
) {
2614 ripng
->default_information
= 1;
2616 str2prefix_ipv6 ("::/0", &p
);
2617 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0, NULL
, 0);
2623 DEFUN (no_ripng_default_information_originate
,
2624 no_ripng_default_information_originate_cmd
,
2625 "no default-information originate",
2627 "Default route information\n"
2628 "Distribute default route\n")
2630 struct prefix_ipv6 p
;
2632 if (ripng
->default_information
) {
2633 ripng
->default_information
= 0;
2635 str2prefix_ipv6 ("::/0", &p
);
2636 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0);
2642 /* Update ECMP routes to zebra when ECMP is disabled. */
2644 ripng_ecmp_disable (void)
2646 struct route_node
*rp
;
2647 struct ripng_info
*rinfo
, *tmp_rinfo
;
2649 struct listnode
*node
, *nextnode
;
2654 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2655 if ((list
= rp
->info
) != NULL
&& listcount (list
) > 1)
2657 rinfo
= listgetdata (listhead (list
));
2658 if (!ripng_route_rte (rinfo
))
2661 /* Drop all other entries, except the first one. */
2662 for (ALL_LIST_ELEMENTS (list
, node
, nextnode
, tmp_rinfo
))
2663 if (tmp_rinfo
!= rinfo
)
2665 RIPNG_TIMER_OFF (tmp_rinfo
->t_timeout
);
2666 RIPNG_TIMER_OFF (tmp_rinfo
->t_garbage_collect
);
2667 list_delete_node (list
, node
);
2668 ripng_info_free (tmp_rinfo
);
2672 ripng_zebra_ipv6_add (rp
);
2674 /* Set the route change flag. */
2675 SET_FLAG (rinfo
->flags
, RIPNG_RTF_CHANGED
);
2677 /* Signal the output process to trigger an update. */
2678 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
2682 DEFUN (ripng_allow_ecmp
,
2683 ripng_allow_ecmp_cmd
,
2685 "Allow Equal Cost MultiPath\n")
2689 vty_out (vty
, "ECMP is already enabled.%s", VTY_NEWLINE
);
2694 zlog_info ("ECMP is enabled.");
2698 DEFUN (no_ripng_allow_ecmp
,
2699 no_ripng_allow_ecmp_cmd
,
2702 "Allow Equal Cost MultiPath\n")
2706 vty_out (vty
, "ECMP is already disabled.%s", VTY_NEWLINE
);
2711 zlog_info ("ECMP is disabled.");
2712 ripng_ecmp_disable ();
2716 /* RIPng configuration write function. */
2718 ripng_config_write (struct vty
*vty
)
2720 int ripng_network_write (struct vty
*, int);
2721 void ripng_redistribute_write (struct vty
*, int);
2723 struct route_node
*rp
;
2729 vty_out (vty
, "router ripng%s", VTY_NEWLINE
);
2731 if (ripng
->default_information
)
2732 vty_out (vty
, " default-information originate%s", VTY_NEWLINE
);
2734 ripng_network_write (vty
, 1);
2736 /* RIPng default metric configuration */
2737 if (ripng
->default_metric
!= RIPNG_DEFAULT_METRIC_DEFAULT
)
2738 vty_out (vty
, " default-metric %d%s",
2739 ripng
->default_metric
, VTY_NEWLINE
);
2741 ripng_redistribute_write (vty
, 1);
2743 /* RIP offset-list configuration. */
2744 config_write_ripng_offset_list (vty
);
2746 /* RIPng aggregate routes. */
2747 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2748 if (rp
->info
!= NULL
)
2749 vty_out (vty
, " aggregate-address %s/%d%s",
2750 inet6_ntoa (rp
->p
.u
.prefix6
),
2755 /* ECMP configuration. */
2757 vty_out (vty
, " allow-ecmp%s", VTY_NEWLINE
);
2759 /* RIPng static routes. */
2760 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2761 if (rp
->info
!= NULL
)
2762 vty_out (vty
, " route %s/%d%s", inet6_ntoa (rp
->p
.u
.prefix6
),
2766 /* RIPng timers configuration. */
2767 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
||
2768 ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
||
2769 ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2771 vty_out (vty
, " timers basic %ld %ld %ld%s",
2773 ripng
->timeout_time
,
2774 ripng
->garbage_time
,
2778 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
)
2779 vty_out (vty
, " update-timer %d%s", ripng
->update_time
,
2781 if (ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
)
2782 vty_out (vty
, " timeout-timer %d%s", ripng
->timeout_time
,
2784 if (ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2785 vty_out (vty
, " garbage-timer %d%s", ripng
->garbage_time
,
2789 write
+= config_write_distribute (vty
);
2791 write
+= config_write_if_rmap (vty
);
2798 /* RIPng node structure. */
2799 static struct cmd_node cmd_ripng_node
=
2802 "%s(config-router)# ",
2807 ripng_distribute_update (struct distribute
*dist
)
2809 struct interface
*ifp
;
2810 struct ripng_interface
*ri
;
2811 struct access_list
*alist
;
2812 struct prefix_list
*plist
;
2817 ifp
= if_lookup_by_name (dist
->ifname
, VRF_DEFAULT
);
2823 if (dist
->list
[DISTRIBUTE_V6_IN
])
2825 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_V6_IN
]);
2827 ri
->list
[RIPNG_FILTER_IN
] = alist
;
2829 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2832 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2834 if (dist
->list
[DISTRIBUTE_V6_OUT
])
2836 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_V6_OUT
]);
2838 ri
->list
[RIPNG_FILTER_OUT
] = alist
;
2840 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2843 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2845 if (dist
->prefix
[DISTRIBUTE_V6_IN
])
2847 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_V6_IN
]);
2849 ri
->prefix
[RIPNG_FILTER_IN
] = plist
;
2851 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2854 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2856 if (dist
->prefix
[DISTRIBUTE_V6_OUT
])
2858 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_V6_OUT
]);
2860 ri
->prefix
[RIPNG_FILTER_OUT
] = plist
;
2862 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2865 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2869 ripng_distribute_update_interface (struct interface
*ifp
)
2871 struct distribute
*dist
;
2873 dist
= distribute_lookup (ifp
->name
);
2875 ripng_distribute_update (dist
);
2878 /* Update all interface's distribute list. */
2880 ripng_distribute_update_all (struct prefix_list
*notused
)
2882 struct interface
*ifp
;
2883 struct listnode
*node
;
2885 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
2886 ripng_distribute_update_interface (ifp
);
2890 ripng_distribute_update_all_wrapper (struct access_list
*notused
)
2892 ripng_distribute_update_all(NULL
);
2895 /* delete all the added ripng routes. */
2900 struct route_node
*rp
;
2901 struct ripng_info
*rinfo
;
2902 struct ripng_aggregate
*aggregate
;
2903 struct list
*list
= NULL
;
2904 struct listnode
*listnode
= NULL
;
2907 /* Clear RIPng routes */
2908 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2910 if ((list
= rp
->info
) != NULL
)
2912 rinfo
= listgetdata (listhead (list
));
2913 if (ripng_route_rte (rinfo
))
2914 ripng_zebra_ipv6_delete (rp
);
2916 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, rinfo
))
2918 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
2919 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
2920 ripng_info_free (rinfo
);
2924 route_unlock_node (rp
);
2927 if ((aggregate
= rp
->aggregate
) != NULL
)
2929 ripng_aggregate_free (aggregate
);
2930 rp
->aggregate
= NULL
;
2931 route_unlock_node (rp
);
2935 /* Cancel the RIPng timers */
2936 RIPNG_TIMER_OFF (ripng
->t_update
);
2937 RIPNG_TIMER_OFF (ripng
->t_triggered_update
);
2938 RIPNG_TIMER_OFF (ripng
->t_triggered_interval
);
2940 /* Cancel the read thread */
2941 if (ripng
->t_read
) {
2942 thread_cancel (ripng
->t_read
);
2943 ripng
->t_read
= NULL
;
2946 /* Close the RIPng socket */
2947 if (ripng
->sock
>= 0) {
2952 /* Static RIPng route configuration. */
2953 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2956 route_unlock_node (rp
);
2959 /* RIPng aggregated prefixes */
2960 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2963 route_unlock_node (rp
);
2966 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2967 if (ripng
->route_map
[i
].name
)
2968 free (ripng
->route_map
[i
].name
);
2970 XFREE (MTYPE_ROUTE_TABLE
, ripng
->table
);
2971 XFREE (MTYPE_ROUTE_TABLE
, ripng
->route
);
2972 XFREE (MTYPE_ROUTE_TABLE
, ripng
->aggregate
);
2974 XFREE (MTYPE_RIPNG
, ripng
);
2978 ripng_clean_network();
2979 ripng_passive_interface_clean ();
2980 ripng_offset_clean ();
2981 ripng_interface_clean ();
2982 ripng_redistribute_clean ();
2985 /* Reset all values to the default settings. */
2989 /* Call ripd related reset functions. */
2990 ripng_debug_reset ();
2991 ripng_route_map_reset ();
2993 /* Call library reset functions. */
2995 access_list_reset ();
2996 prefix_list_reset ();
2998 distribute_list_reset ();
3000 ripng_interface_reset ();
3002 ripng_zclient_reset ();
3006 ripng_if_rmap_update (struct if_rmap
*if_rmap
)
3008 struct interface
*ifp
;
3009 struct ripng_interface
*ri
;
3010 struct route_map
*rmap
;
3012 ifp
= if_lookup_by_name (if_rmap
->ifname
, VRF_DEFAULT
);
3018 if (if_rmap
->routemap
[IF_RMAP_IN
])
3020 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_IN
]);
3022 ri
->routemap
[IF_RMAP_IN
] = rmap
;
3024 ri
->routemap
[IF_RMAP_IN
] = NULL
;
3027 ri
->routemap
[RIPNG_FILTER_IN
] = NULL
;
3029 if (if_rmap
->routemap
[IF_RMAP_OUT
])
3031 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_OUT
]);
3033 ri
->routemap
[IF_RMAP_OUT
] = rmap
;
3035 ri
->routemap
[IF_RMAP_OUT
] = NULL
;
3038 ri
->routemap
[RIPNG_FILTER_OUT
] = NULL
;
3042 ripng_if_rmap_update_interface (struct interface
*ifp
)
3044 struct if_rmap
*if_rmap
;
3046 if_rmap
= if_rmap_lookup (ifp
->name
);
3048 ripng_if_rmap_update (if_rmap
);
3052 ripng_routemap_update_redistribute (void)
3058 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
3060 if (ripng
->route_map
[i
].name
)
3061 ripng
->route_map
[i
].map
=
3062 route_map_lookup_by_name (ripng
->route_map
[i
].name
);
3068 ripng_routemap_update (const char *unused
)
3070 struct interface
*ifp
;
3071 struct listnode
*node
;
3073 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
3074 ripng_if_rmap_update_interface (ifp
);
3076 ripng_routemap_update_redistribute ();
3079 /* Initialize ripng structure and set commands. */
3083 /* Install RIPNG_NODE. */
3084 install_node (&cmd_ripng_node
, ripng_config_write
);
3086 /* Install ripng commands. */
3087 install_element (VIEW_NODE
, &show_ipv6_ripng_cmd
);
3088 install_element (VIEW_NODE
, &show_ipv6_ripng_status_cmd
);
3090 install_element (ENABLE_NODE
, &clear_ipv6_rip_cmd
);
3092 install_element (CONFIG_NODE
, &router_ripng_cmd
);
3093 install_element (CONFIG_NODE
, &no_router_ripng_cmd
);
3095 install_default (RIPNG_NODE
);
3096 install_element (RIPNG_NODE
, &ripng_route_cmd
);
3097 install_element (RIPNG_NODE
, &no_ripng_route_cmd
);
3098 install_element (RIPNG_NODE
, &ripng_aggregate_address_cmd
);
3099 install_element (RIPNG_NODE
, &no_ripng_aggregate_address_cmd
);
3101 install_element (RIPNG_NODE
, &ripng_default_metric_cmd
);
3102 install_element (RIPNG_NODE
, &no_ripng_default_metric_cmd
);
3104 install_element (RIPNG_NODE
, &ripng_timers_cmd
);
3105 install_element (RIPNG_NODE
, &no_ripng_timers_cmd
);
3107 install_element (VIEW_NODE
, &show_ipv6_protocols_cmd
);
3108 install_element (RIPNG_NODE
, &ripng_update_timer_cmd
);
3109 install_element (RIPNG_NODE
, &no_ripng_update_timer_cmd
);
3110 install_element (RIPNG_NODE
, &ripng_timeout_timer_cmd
);
3111 install_element (RIPNG_NODE
, &no_ripng_timeout_timer_cmd
);
3112 install_element (RIPNG_NODE
, &ripng_garbage_timer_cmd
);
3113 install_element (RIPNG_NODE
, &no_ripng_garbage_timer_cmd
);
3116 install_element (RIPNG_NODE
, &ripng_default_information_originate_cmd
);
3117 install_element (RIPNG_NODE
, &no_ripng_default_information_originate_cmd
);
3119 install_element (RIPNG_NODE
, &ripng_allow_ecmp_cmd
);
3120 install_element (RIPNG_NODE
, &no_ripng_allow_ecmp_cmd
);
3123 ripng_debug_init ();
3125 /* Access list install. */
3126 access_list_init ();
3127 access_list_add_hook (ripng_distribute_update_all_wrapper
);
3128 access_list_delete_hook (ripng_distribute_update_all_wrapper
);
3130 /* Prefix list initialize.*/
3131 prefix_list_init ();
3132 prefix_list_add_hook (ripng_distribute_update_all
);
3133 prefix_list_delete_hook (ripng_distribute_update_all
);
3135 /* Distribute list install. */
3136 distribute_list_init (RIPNG_NODE
);
3137 distribute_list_add_hook (ripng_distribute_update
);
3138 distribute_list_delete_hook (ripng_distribute_update
);
3140 /* Route-map for interface. */
3141 ripng_route_map_init ();
3142 ripng_offset_init ();
3144 route_map_add_hook (ripng_routemap_update
);
3145 route_map_delete_hook (ripng_routemap_update
);
3147 if_rmap_init (RIPNG_NODE
);
3148 if_rmap_hook_add (ripng_if_rmap_update
);
3149 if_rmap_hook_delete (ripng_if_rmap_update
);