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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "distribute.h"
39 #include "ripngd/ripngd.h"
40 #include "ripngd/ripng_route.h"
41 #include "ripngd/ripng_debug.h"
42 #include "ripngd/ripng_nexthop.h"
44 /* RIPng structure which includes many parameters related to RIPng
45 protocol. If ripng couldn't active or ripng doesn't configured,
46 ripng->fd must be negative value. */
47 struct ripng
*ripng
= NULL
;
55 extern struct zebra_privs_t ripngd_privs
;
59 ripng_output_process (struct interface
*, struct sockaddr_in6
*, int);
62 ripng_triggered_update (struct thread
*);
64 /* RIPng next hop specification. */
67 enum ripng_nexthop_type
72 struct in6_addr address
;
76 ripng_route_rte (struct ripng_info
*rinfo
)
78 return (rinfo
->type
== ZEBRA_ROUTE_RIPNG
&& rinfo
->sub_type
== RIPNG_ROUTE_RTE
);
81 /* Allocate new ripng information. */
85 struct ripng_info
*new;
87 new = XCALLOC (MTYPE_RIPNG_ROUTE
, sizeof (struct ripng_info
));
91 /* Free ripng information. */
93 ripng_info_free (struct ripng_info
*rinfo
)
95 XFREE (MTYPE_RIPNG_ROUTE
, rinfo
);
98 /* Create ripng socket. */
100 ripng_make_socket (void)
104 struct sockaddr_in6 ripaddr
;
106 sock
= socket (AF_INET6
, SOCK_DGRAM
, 0);
109 zlog_err("Can't make ripng socket");
113 setsockopt_so_recvbuf (sock
, 8096);
114 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
117 #ifdef IPTOS_PREC_INTERNETCONTROL
118 ret
= setsockopt_ipv6_tclass (sock
, IPTOS_PREC_INTERNETCONTROL
);
122 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
125 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
128 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
132 memset (&ripaddr
, 0, sizeof (ripaddr
));
133 ripaddr
.sin6_family
= AF_INET6
;
135 ripaddr
.sin6_len
= sizeof (struct sockaddr_in6
);
136 #endif /* SIN6_LEN */
137 ripaddr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
139 if (ripngd_privs
.change (ZPRIVS_RAISE
))
140 zlog_err ("ripng_make_socket: could not raise privs");
142 ret
= bind (sock
, (struct sockaddr
*) &ripaddr
, sizeof (ripaddr
));
145 zlog_err("Can't bind ripng socket: %s.", safe_strerror(errno
));
146 if (ripngd_privs
.change (ZPRIVS_LOWER
))
147 zlog_err ("ripng_make_socket: could not lower privs");
150 if (ripngd_privs
.change (ZPRIVS_LOWER
))
151 zlog_err ("ripng_make_socket: could not lower privs");
155 /* Send RIPng packet. */
157 ripng_send_packet (caddr_t buf
, int bufsize
, struct sockaddr_in6
*to
,
158 struct interface
*ifp
)
163 struct cmsghdr
*cmsgptr
;
165 struct in6_pktinfo
*pkt
;
166 struct sockaddr_in6 addr
;
168 if (IS_RIPNG_DEBUG_SEND
) {
170 zlog_debug ("send to %s", inet6_ntoa (to
->sin6_addr
));
171 zlog_debug (" send interface %s", ifp
->name
);
172 zlog_debug (" send packet size %d", bufsize
);
175 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
176 addr
.sin6_family
= AF_INET6
;
178 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
179 #endif /* SIN6_LEN */
180 addr
.sin6_flowinfo
= htonl (RIPNG_PRIORITY_DEFAULT
);
182 /* When destination is specified. */
185 addr
.sin6_addr
= to
->sin6_addr
;
186 addr
.sin6_port
= to
->sin6_port
;
190 inet_pton(AF_INET6
, RIPNG_GROUP
, &addr
.sin6_addr
);
191 addr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
194 msg
.msg_name
= (void *) &addr
;
195 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
198 msg
.msg_control
= (void *) adata
;
199 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
202 iov
.iov_len
= bufsize
;
204 cmsgptr
= (struct cmsghdr
*)adata
;
205 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof (struct in6_pktinfo
));
206 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
207 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
209 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
210 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
211 pkt
->ipi6_ifindex
= ifp
->ifindex
;
213 ret
= sendmsg (ripng
->sock
, &msg
, 0);
217 zlog_err ("RIPng send fail on %s to %s: %s", ifp
->name
,
218 inet6_ntoa (to
->sin6_addr
), safe_strerror (errno
));
220 zlog_err ("RIPng send fail on %s: %s", ifp
->name
, safe_strerror (errno
));
226 /* Receive UDP RIPng packet from socket. */
228 ripng_recv_packet (int sock
, u_char
*buf
, int bufsize
,
229 struct sockaddr_in6
*from
, ifindex_t
*ifindex
,
235 struct cmsghdr
*cmsgptr
;
236 struct in6_addr dst
= { .s6_addr
= { 0 } };
238 memset(&dst
, 0, sizeof(struct in6_addr
));
240 /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this
241 point I can't determine size of cmsghdr */
244 /* Fill in message and iovec. */
245 msg
.msg_name
= (void *) from
;
246 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
249 msg
.msg_control
= (void *) adata
;
250 msg
.msg_controllen
= sizeof adata
;
252 iov
.iov_len
= bufsize
;
254 /* If recvmsg fail return minus value. */
255 ret
= recvmsg (sock
, &msg
, 0);
259 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
260 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
262 /* I want interface index which this packet comes from. */
263 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
264 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
266 struct in6_pktinfo
*ptr
;
268 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
269 *ifindex
= ptr
->ipi6_ifindex
;
270 dst
= ptr
->ipi6_addr
;
273 zlog_warn ("Interface index returned by IPV6_PKTINFO is zero");
276 /* Incoming packet's multicast hop limit. */
277 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
278 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
280 int *phoplimit
= (int *) CMSG_DATA (cmsgptr
);
281 *hoplimit
= *phoplimit
;
285 /* Hoplimit check shold be done when destination address is
286 multicast address. */
287 if (! IN6_IS_ADDR_MULTICAST (&dst
))
293 /* Dump rip packet */
295 ripng_packet_dump (struct ripng_packet
*packet
, int size
, const char *sndrcv
)
299 const char *command_str
;
301 /* Set command string. */
302 if (packet
->command
== RIPNG_REQUEST
)
303 command_str
= "request";
304 else if (packet
->command
== RIPNG_RESPONSE
)
305 command_str
= "response";
307 command_str
= "unknown";
309 /* Dump packet header. */
310 zlog_debug ("%s %s version %d packet size %d",
311 sndrcv
, command_str
, packet
->version
, size
);
313 /* Dump each routing table entry. */
316 for (lim
= (caddr_t
) packet
+ size
; (caddr_t
) rte
< lim
; rte
++)
318 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
319 zlog_debug (" nexthop %s/%d", inet6_ntoa (rte
->addr
), rte
->prefixlen
);
321 zlog_debug (" %s/%d metric %d tag %"ROUTE_TAG_PRI
,
322 inet6_ntoa (rte
->addr
), rte
->prefixlen
,
323 rte
->metric
, (route_tag_t
)ntohs (rte
->tag
));
327 /* RIPng next hop address RTE (Route Table Entry). */
329 ripng_nexthop_rte (struct rte
*rte
,
330 struct sockaddr_in6
*from
,
331 struct ripng_nexthop
*nexthop
)
333 char buf
[INET6_BUFSIZ
];
335 /* Logging before checking RTE. */
336 if (IS_RIPNG_DEBUG_RECV
)
337 zlog_debug ("RIPng nexthop RTE address %s tag %"ROUTE_TAG_PRI
" prefixlen %d",
338 inet6_ntoa (rte
->addr
), (route_tag_t
)ntohs (rte
->tag
), rte
->prefixlen
);
340 /* RFC2080 2.1.1 Next Hop:
341 The route tag and prefix length in the next hop RTE must be
342 set to zero on sending and ignored on receiption. */
343 if (ntohs (rte
->tag
) != 0)
344 zlog_warn ("RIPng nexthop RTE with non zero tag value %"ROUTE_TAG_PRI
" from %s",
345 (route_tag_t
)ntohs (rte
->tag
), inet6_ntoa (from
->sin6_addr
));
347 if (rte
->prefixlen
!= 0)
348 zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
349 rte
->prefixlen
, inet6_ntoa (from
->sin6_addr
));
351 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
352 next hop RTE indicates that the next hop address should be the
353 originator of the RIPng advertisement. An address specified as a
354 next hop must be a link-local address. */
355 if (IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
))
357 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
358 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
362 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
364 nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
365 IPV6_ADDR_COPY (&nexthop
->address
, &rte
->addr
);
369 /* The purpose of the next hop RTE is to eliminate packets being
370 routed through extra hops in the system. It is particularly useful
371 when RIPng is not being run on all of the routers on a network.
372 Note that next hop RTE is "advisory". That is, if the provided
373 information is ignored, a possibly sub-optimal, but absolutely
374 valid, route may be taken. If the received next hop address is not
375 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
376 zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s",
377 inet6_ntoa (rte
->addr
),
378 inet_ntop (AF_INET6
, &from
->sin6_addr
, buf
, INET6_BUFSIZ
));
380 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
381 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
386 /* If ifp has same link-local address then return 1. */
388 ripng_lladdr_check (struct interface
*ifp
, struct in6_addr
*addr
)
390 struct listnode
*node
;
391 struct connected
*connected
;
394 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, connected
))
396 p
= connected
->address
;
398 if (p
->family
== AF_INET6
&&
399 IN6_IS_ADDR_LINKLOCAL (&p
->u
.prefix6
) &&
400 IN6_ARE_ADDR_EQUAL (&p
->u
.prefix6
, addr
))
406 /* RIPng route garbage collect timer. */
408 ripng_garbage_collect (struct thread
*t
)
410 struct ripng_info
*rinfo
;
411 struct route_node
*rp
;
413 rinfo
= THREAD_ARG (t
);
414 rinfo
->t_garbage_collect
= NULL
;
416 /* Off timeout timer. */
417 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
419 /* Get route_node pointer. */
422 /* Unlock route_node. */
423 listnode_delete (rp
->info
, rinfo
);
424 if (list_isempty ((struct list
*)rp
->info
))
426 list_free (rp
->info
);
428 route_unlock_node (rp
);
431 /* Free RIPng routing information. */
432 ripng_info_free (rinfo
);
437 static void ripng_timeout_update (struct ripng_info
*rinfo
);
439 /* Add new route to the ECMP list.
440 * RETURN: the new entry added in the list, or NULL if it is not the first
441 * entry and ECMP is not allowed.
444 ripng_ecmp_add (struct ripng_info
*rinfo_new
)
446 struct route_node
*rp
= rinfo_new
->rp
;
447 struct ripng_info
*rinfo
= NULL
;
448 struct list
*list
= NULL
;
450 if (rp
->info
== NULL
)
451 rp
->info
= list_new ();
452 list
= (struct list
*)rp
->info
;
454 /* If ECMP is not allowed and some entry already exists in the list,
456 if (listcount (list
) && !ripng
->ecmp
)
459 rinfo
= ripng_info_new ();
460 memcpy (rinfo
, rinfo_new
, sizeof (struct ripng_info
));
461 listnode_add (list
, rinfo
);
463 if (ripng_route_rte (rinfo
))
465 ripng_timeout_update (rinfo
);
466 ripng_zebra_ipv6_add (rp
);
469 ripng_aggregate_increment (rp
, rinfo
);
471 /* Set the route change flag on the first entry. */
472 rinfo
= listgetdata (listhead (list
));
473 SET_FLAG (rinfo
->flags
, RIPNG_RTF_CHANGED
);
475 /* Signal the output process to trigger an update. */
476 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
481 /* Replace the ECMP list with the new route.
482 * RETURN: the new entry added in the list
485 ripng_ecmp_replace (struct ripng_info
*rinfo_new
)
487 struct route_node
*rp
= rinfo_new
->rp
;
488 struct list
*list
= (struct list
*)rp
->info
;
489 struct ripng_info
*rinfo
= NULL
, *tmp_rinfo
= NULL
;
490 struct listnode
*node
= NULL
, *nextnode
= NULL
;
492 if (list
== NULL
|| listcount (list
) == 0)
493 return ripng_ecmp_add (rinfo_new
);
495 /* Get the first entry */
496 rinfo
= listgetdata (listhead (list
));
498 /* Learnt route replaced by a local one. Delete it from zebra. */
499 if (ripng_route_rte (rinfo
) && !ripng_route_rte (rinfo_new
))
500 if (CHECK_FLAG (rinfo
->flags
, RIPNG_RTF_FIB
))
501 ripng_zebra_ipv6_delete (rp
);
503 if (rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
504 ripng_aggregate_decrement_list (rp
, list
);
506 /* Re-use the first entry, and delete the others. */
507 for (ALL_LIST_ELEMENTS (list
, node
, nextnode
, tmp_rinfo
))
508 if (tmp_rinfo
!= rinfo
)
510 RIPNG_TIMER_OFF (tmp_rinfo
->t_timeout
);
511 RIPNG_TIMER_OFF (tmp_rinfo
->t_garbage_collect
);
512 list_delete_node (list
, node
);
513 ripng_info_free (tmp_rinfo
);
516 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
517 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
518 memcpy (rinfo
, rinfo_new
, sizeof (struct ripng_info
));
520 if (ripng_route_rte (rinfo
))
522 ripng_timeout_update (rinfo
);
523 /* The ADD message implies an update. */
524 ripng_zebra_ipv6_add (rp
);
527 ripng_aggregate_increment (rp
, rinfo
);
529 /* Set the route change flag. */
530 SET_FLAG (rinfo
->flags
, RIPNG_RTF_CHANGED
);
532 /* Signal the output process to trigger an update. */
533 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
538 /* Delete one route from the ECMP list.
540 * null - the entry is freed, and other entries exist in the list
541 * the entry - the entry is the last one in the list; its metric is set
542 * to INFINITY, and the garbage collector is started for it
545 ripng_ecmp_delete (struct ripng_info
*rinfo
)
547 struct route_node
*rp
= rinfo
->rp
;
548 struct list
*list
= (struct list
*)rp
->info
;
550 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
552 if (rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
553 ripng_aggregate_decrement (rp
, rinfo
);
555 if (listcount (list
) > 1)
557 /* Some other ECMP entries still exist. Just delete this entry. */
558 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
559 listnode_delete (list
, rinfo
);
560 if (ripng_route_rte (rinfo
) && CHECK_FLAG (rinfo
->flags
, RIPNG_RTF_FIB
))
561 /* The ADD message implies the update. */
562 ripng_zebra_ipv6_add (rp
);
563 ripng_info_free (rinfo
);
568 assert (rinfo
== listgetdata (listhead (list
)));
570 /* This is the only entry left in the list. We must keep it in
571 * the list for garbage collection time, with INFINITY metric. */
573 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
574 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
575 ripng_garbage_collect
, ripng
->garbage_time
);
577 if (ripng_route_rte (rinfo
) && CHECK_FLAG (rinfo
->flags
, RIPNG_RTF_FIB
))
578 ripng_zebra_ipv6_delete (rp
);
581 /* Set the route change flag on the first entry. */
582 rinfo
= listgetdata (listhead (list
));
583 SET_FLAG (rinfo
->flags
, RIPNG_RTF_CHANGED
);
585 /* Signal the output process to trigger an update. */
586 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
591 /* Timeout RIPng routes. */
593 ripng_timeout (struct thread
*t
)
595 ripng_ecmp_delete ((struct ripng_info
*)THREAD_ARG (t
));
600 ripng_timeout_update (struct ripng_info
*rinfo
)
602 if (rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
604 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
605 RIPNG_TIMER_ON (rinfo
->t_timeout
, ripng_timeout
, ripng
->timeout_time
);
610 ripng_filter (int ripng_distribute
, struct prefix_ipv6
*p
,
611 struct ripng_interface
*ri
)
613 struct distribute
*dist
;
614 struct access_list
*alist
;
615 struct prefix_list
*plist
;
616 int distribute
= ripng_distribute
== RIPNG_FILTER_OUT
?
617 DISTRIBUTE_V6_OUT
: DISTRIBUTE_V6_IN
;
618 const char *inout
= ripng_distribute
== RIPNG_FILTER_OUT
? "out" : "in";
620 /* Input distribute-list filtering. */
621 if (ri
->list
[ripng_distribute
])
623 if (access_list_apply (ri
->list
[ripng_distribute
],
624 (struct prefix
*) p
) == FILTER_DENY
)
626 if (IS_RIPNG_DEBUG_PACKET
)
627 zlog_debug ("%s/%d filtered by distribute %s",
628 inet6_ntoa (p
->prefix
), p
->prefixlen
, inout
);
632 if (ri
->prefix
[ripng_distribute
])
634 if (prefix_list_apply (ri
->prefix
[ripng_distribute
],
635 (struct prefix
*) p
) == PREFIX_DENY
)
637 if (IS_RIPNG_DEBUG_PACKET
)
638 zlog_debug ("%s/%d filtered by prefix-list %s",
639 inet6_ntoa (p
->prefix
), p
->prefixlen
, inout
);
644 /* All interface filter check. */
645 dist
= distribute_lookup (NULL
);
648 if (dist
->list
[distribute
])
650 alist
= access_list_lookup (AFI_IP6
, dist
->list
[distribute
]);
654 if (access_list_apply (alist
,
655 (struct prefix
*) p
) == FILTER_DENY
)
657 if (IS_RIPNG_DEBUG_PACKET
)
658 zlog_debug ("%s/%d filtered by distribute %s",
659 inet6_ntoa (p
->prefix
), p
->prefixlen
, inout
);
664 if (dist
->prefix
[distribute
])
666 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[distribute
]);
670 if (prefix_list_apply (plist
,
671 (struct prefix
*) p
) == PREFIX_DENY
)
673 if (IS_RIPNG_DEBUG_PACKET
)
674 zlog_debug ("%s/%d filtered by prefix-list %s",
675 inet6_ntoa (p
->prefix
), p
->prefixlen
, inout
);
684 /* Process RIPng route according to RFC2080. */
686 ripng_route_process (struct rte
*rte
, struct sockaddr_in6
*from
,
687 struct ripng_nexthop
*ripng_nexthop
,
688 struct interface
*ifp
)
691 struct prefix_ipv6 p
;
692 struct route_node
*rp
;
693 struct ripng_info
*rinfo
= NULL
, newinfo
;
694 struct ripng_interface
*ri
;
695 struct in6_addr
*nexthop
;
697 struct list
*list
= NULL
;
698 struct listnode
*node
= NULL
;
700 /* Make prefix structure. */
701 memset (&p
, 0, sizeof (struct prefix_ipv6
));
703 /* p.prefix = rte->addr; */
704 IPV6_ADDR_COPY (&p
.prefix
, &rte
->addr
);
705 p
.prefixlen
= rte
->prefixlen
;
707 /* Make sure mask is applied. */
708 /* XXX We have to check the prefix is valid or not before call
710 apply_mask_ipv6 (&p
);
712 /* Apply input filters. */
715 ret
= ripng_filter (RIPNG_FILTER_IN
, &p
, ri
);
719 memset (&newinfo
, 0, sizeof (newinfo
));
720 newinfo
.type
= ZEBRA_ROUTE_RIPNG
;
721 newinfo
.sub_type
= RIPNG_ROUTE_RTE
;
722 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
723 newinfo
.nexthop
= ripng_nexthop
->address
;
725 newinfo
.nexthop
= from
->sin6_addr
;
726 newinfo
.from
= from
->sin6_addr
;
727 newinfo
.ifindex
= ifp
->ifindex
;
728 newinfo
.metric
= rte
->metric
;
729 newinfo
.metric_out
= rte
->metric
; /* XXX */
730 newinfo
.tag
= ntohs (rte
->tag
); /* XXX */
733 if (ri
->routemap
[RIPNG_FILTER_IN
])
737 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_IN
],
738 (struct prefix
*)&p
, RMAP_RIPNG
, &newinfo
);
740 if (ret
== RMAP_DENYMATCH
)
742 if (IS_RIPNG_DEBUG_PACKET
)
743 zlog_debug ("RIPng %s/%d is filtered by route-map in",
744 inet6_ntoa (p
.prefix
), p
.prefixlen
);
748 /* Get back the object */
749 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
) {
750 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &ripng_nexthop
->address
) ) {
751 /* the nexthop get changed by the routemap */
752 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
))
753 ripng_nexthop
->address
= newinfo
.nexthop
;
755 ripng_nexthop
->address
= in6addr_any
;
758 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &from
->sin6_addr
) ) {
759 /* the nexthop get changed by the routemap */
760 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
)) {
761 ripng_nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
762 ripng_nexthop
->address
= newinfo
.nexthop
;
766 rte
->tag
= htons(newinfo
.tag_out
); /* XXX */
767 rte
->metric
= newinfo
.metric_out
; /* XXX: the routemap uses the metric_out field */
770 /* Once the entry has been validated, update the metric by
771 * adding the cost of the network on wich the message
772 * arrived. If the result is greater than infinity, use infinity
773 * (RFC2453 Sec. 3.9.2)
776 /* Zebra ripngd can handle offset-list in. */
777 ret
= ripng_offset_list_apply_in (&p
, ifp
, &rte
->metric
);
779 /* If offset-list does not modify the metric use interface's
782 rte
->metric
+= ifp
->metric
? ifp
->metric
: 1;
784 if (rte
->metric
> RIPNG_METRIC_INFINITY
)
785 rte
->metric
= RIPNG_METRIC_INFINITY
;
787 /* Set nexthop pointer. */
788 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
789 nexthop
= &ripng_nexthop
->address
;
791 nexthop
= &from
->sin6_addr
;
793 /* Lookup RIPng routing table. */
794 rp
= route_node_get (ripng
->table
, (struct prefix
*) &p
);
797 newinfo
.nexthop
= *nexthop
;
798 newinfo
.metric
= rte
->metric
;
799 newinfo
.tag
= ntohs (rte
->tag
);
801 /* Check to see whether there is already RIPng route on the table. */
802 if ((list
= rp
->info
) != NULL
)
803 for (ALL_LIST_ELEMENTS_RO (list
, node
, rinfo
))
805 /* Need to compare with redistributed entry or local entry */
806 if (!ripng_route_rte (rinfo
))
809 if (IPV6_ADDR_SAME (&rinfo
->from
, &from
->sin6_addr
) &&
810 IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
813 if (!listnextnode (node
))
815 /* Not found in the list */
817 if (rte
->metric
> rinfo
->metric
)
819 /* New route has a greater metric. Discard it. */
820 route_unlock_node (rp
);
824 if (rte
->metric
< rinfo
->metric
)
825 /* New route has a smaller metric. Replace the ECMP list
826 * with the new one in below. */
829 /* Metrics are same. Unless ECMP is disabled, keep "rinfo" null and
830 * the new route is added in the ECMP list in below. */
838 /* Redistributed route check. */
839 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
840 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
842 route_unlock_node (rp
);
846 /* Local static route. */
847 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
848 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
849 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
))
850 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
852 route_unlock_node (rp
);
859 /* Now, check to see whether there is already an explicit route
860 for the destination prefix. If there is no such route, add
861 this route to the routing table, unless the metric is
862 infinity (there is no point in adding a route which
864 if (rte
->metric
!= RIPNG_METRIC_INFINITY
)
865 ripng_ecmp_add (&newinfo
);
869 /* If there is an existing route, compare the next hop address
870 to the address of the router from which the datagram came.
871 If this datagram is from the same router as the existing
872 route, reinitialize the timeout. */
873 same
= (IN6_ARE_ADDR_EQUAL (&rinfo
->from
, &from
->sin6_addr
)
874 && (rinfo
->ifindex
== ifp
->ifindex
));
877 * RFC 2080 - Section 2.4.2:
878 * "If the new metric is the same as the old one, examine the timeout
879 * for the existing route. If it is at least halfway to the expiration
880 * point, switch to the new route. This heuristic is optional, but
881 * highly recommended".
883 if (!ripng
->ecmp
&& !same
&&
884 rinfo
->metric
== rte
->metric
&& rinfo
->t_timeout
&&
885 (thread_timer_remain_second (rinfo
->t_timeout
) < (ripng
->timeout_time
/ 2)))
887 ripng_ecmp_replace (&newinfo
);
889 /* Next, compare the metrics. If the datagram is from the same
890 router as the existing route, and the new metric is different
891 than the old one; or, if the new metric is lower than the old
892 one; do the following actions: */
893 else if ((same
&& rinfo
->metric
!= rte
->metric
) ||
894 rte
->metric
< rinfo
->metric
)
896 if (listcount (list
) == 1)
898 if (newinfo
.metric
!= RIPNG_METRIC_INFINITY
)
899 ripng_ecmp_replace (&newinfo
);
901 ripng_ecmp_delete (rinfo
);
905 if (newinfo
.metric
< rinfo
->metric
)
906 ripng_ecmp_replace (&newinfo
);
907 else /* newinfo.metric > rinfo->metric */
908 ripng_ecmp_delete (rinfo
);
911 else /* same & no change */
912 ripng_timeout_update (rinfo
);
914 /* Unlock tempolary lock of the route. */
915 route_unlock_node (rp
);
919 /* Add redistributed route to RIPng table. */
921 ripng_redistribute_add (int type
, int sub_type
, struct prefix_ipv6
*p
,
922 ifindex_t ifindex
, struct in6_addr
*nexthop
,
925 struct route_node
*rp
;
926 struct ripng_info
*rinfo
= NULL
, newinfo
;
927 struct list
*list
= NULL
;
929 /* Redistribute route */
930 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
932 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
935 rp
= route_node_get (ripng
->table
, (struct prefix
*) p
);
937 memset (&newinfo
, 0, sizeof (struct ripng_info
));
939 newinfo
.sub_type
= sub_type
;
940 newinfo
.ifindex
= ifindex
;
942 if (tag
<= UINT16_MAX
) /* RIPng only supports 16 bit tags */
945 if (nexthop
&& IN6_IS_ADDR_LINKLOCAL(nexthop
))
946 newinfo
.nexthop
= *nexthop
;
948 if ((list
= rp
->info
) != NULL
&& listcount (list
) != 0)
950 rinfo
= listgetdata (listhead (list
));
952 if (rinfo
->type
== ZEBRA_ROUTE_CONNECT
953 && rinfo
->sub_type
== RIPNG_ROUTE_INTERFACE
954 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
) {
955 route_unlock_node (rp
);
959 /* Manually configured RIPng route check.
960 * They have the precedence on all the other entries.
962 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
963 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
964 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
)) ) {
965 if (type
!= ZEBRA_ROUTE_RIPNG
|| ((sub_type
!= RIPNG_ROUTE_STATIC
) &&
966 (sub_type
!= RIPNG_ROUTE_DEFAULT
))) {
967 route_unlock_node (rp
);
972 ripng_ecmp_replace (&newinfo
);
973 route_unlock_node (rp
);
976 ripng_ecmp_add (&newinfo
);
978 if (IS_RIPNG_DEBUG_EVENT
) {
980 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
981 inet6_ntoa(p
->prefix
), p
->prefixlen
,
982 ifindex2ifname(ifindex
, VRF_DEFAULT
));
984 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
985 inet6_ntoa(p
->prefix
), p
->prefixlen
, inet6_ntoa(*nexthop
),
986 ifindex2ifname(ifindex
, VRF_DEFAULT
));
989 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
992 /* Delete redistributed route to RIPng table. */
994 ripng_redistribute_delete (int type
, int sub_type
, struct prefix_ipv6
*p
,
997 struct route_node
*rp
;
998 struct ripng_info
*rinfo
;
1000 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
1002 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
1005 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) p
);
1009 struct list
*list
= rp
->info
;
1011 if (list
!= NULL
&& listcount (list
) != 0)
1013 rinfo
= listgetdata (listhead (list
));
1015 && rinfo
->type
== type
1016 && rinfo
->sub_type
== sub_type
1017 && rinfo
->ifindex
== ifindex
)
1019 /* Perform poisoned reverse. */
1020 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1021 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1022 ripng_garbage_collect
, ripng
->garbage_time
);
1023 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1025 /* Aggregate count decrement. */
1026 ripng_aggregate_decrement (rp
, rinfo
);
1028 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1030 if (IS_RIPNG_DEBUG_EVENT
)
1031 zlog_debug ("Poisone %s/%d on the interface %s with an "
1032 "infinity metric [delete]",
1033 inet6_ntoa (p
->prefix
), p
->prefixlen
,
1034 ifindex2ifname (ifindex
, VRF_DEFAULT
));
1036 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1039 route_unlock_node (rp
);
1043 /* Withdraw redistributed route. */
1045 ripng_redistribute_withdraw (int type
)
1047 struct route_node
*rp
;
1048 struct ripng_info
*rinfo
= NULL
;
1049 struct list
*list
= NULL
;
1054 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1055 if ((list
= rp
->info
) != NULL
)
1057 rinfo
= listgetdata (listhead (list
));
1058 if ((rinfo
->type
== type
)
1059 && (rinfo
->sub_type
!= RIPNG_ROUTE_INTERFACE
))
1061 /* Perform poisoned reverse. */
1062 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1063 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1064 ripng_garbage_collect
, ripng
->garbage_time
);
1065 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1067 /* Aggregate count decrement. */
1068 ripng_aggregate_decrement (rp
, rinfo
);
1070 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1072 if (IS_RIPNG_DEBUG_EVENT
) {
1073 struct prefix_ipv6
*p
= (struct prefix_ipv6
*) &rp
->p
;
1075 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
1076 inet6_ntoa(p
->prefix
), p
->prefixlen
,
1077 ifindex2ifname(rinfo
->ifindex
, VRF_DEFAULT
));
1080 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1085 /* RIP routing information. */
1087 ripng_response_process (struct ripng_packet
*packet
, int size
,
1088 struct sockaddr_in6
*from
, struct interface
*ifp
,
1093 struct ripng_nexthop nexthop
;
1095 /* RFC2080 2.4.2 Response Messages:
1096 The Response must be ignored if it is not from the RIPng port. */
1097 if (ntohs (from
->sin6_port
) != RIPNG_PORT_DEFAULT
)
1099 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
1100 ntohs (from
->sin6_port
), inet6_ntoa (from
->sin6_addr
));
1101 ripng_peer_bad_packet (from
);
1105 /* The datagram's IPv6 source address should be checked to see
1106 whether the datagram is from a valid neighbor; the source of the
1107 datagram must be a link-local address. */
1108 if (! IN6_IS_ADDR_LINKLOCAL(&from
->sin6_addr
))
1110 zlog_warn ("RIPng packet comes from non link local address %s",
1111 inet6_ntoa (from
->sin6_addr
));
1112 ripng_peer_bad_packet (from
);
1116 /* It is also worth checking to see whether the response is from one
1117 of the router's own addresses. Interfaces on broadcast networks
1118 may receive copies of their own multicasts immediately. If a
1119 router processes its own output as new input, confusion is likely,
1120 and such datagrams must be ignored. */
1121 if (ripng_lladdr_check (ifp
, &from
->sin6_addr
))
1123 zlog_warn ("RIPng packet comes from my own link local address %s",
1124 inet6_ntoa (from
->sin6_addr
));
1125 ripng_peer_bad_packet (from
);
1129 /* As an additional check, periodic advertisements must have their
1130 hop counts set to 255, and inbound, multicast packets sent from the
1131 RIPng port (i.e. periodic advertisement or triggered update
1132 packets) must be examined to ensure that the hop count is 255. */
1133 if (hoplimit
>= 0 && hoplimit
!= 255)
1135 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
1136 hoplimit
, inet6_ntoa (from
->sin6_addr
));
1137 ripng_peer_bad_packet (from
);
1141 /* Update RIPng peer. */
1142 ripng_peer_update (from
, packet
->version
);
1144 /* Reset nexthop. */
1145 memset (&nexthop
, 0, sizeof (struct ripng_nexthop
));
1146 nexthop
.flag
= RIPNG_NEXTHOP_UNSPEC
;
1148 /* Set RTE pointer. */
1151 for (lim
= ((caddr_t
) packet
) + size
; (caddr_t
) rte
< lim
; rte
++)
1153 /* First of all, we have to check this RTE is next hop RTE or
1154 not. Next hop RTE is completely different with normal RTE so
1155 we need special treatment. */
1156 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
1158 ripng_nexthop_rte (rte
, from
, &nexthop
);
1162 /* RTE information validation. */
1164 /* - is the destination prefix valid (e.g., not a multicast
1165 prefix and not a link-local address) A link-local address
1166 should never be present in an RTE. */
1167 if (IN6_IS_ADDR_MULTICAST (&rte
->addr
))
1169 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
1170 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1171 ripng_peer_bad_route (from
);
1174 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
1176 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
1177 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1178 ripng_peer_bad_route (from
);
1181 if (IN6_IS_ADDR_LOOPBACK (&rte
->addr
))
1183 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
1184 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1185 ripng_peer_bad_route (from
);
1189 /* - is the prefix length valid (i.e., between 0 and 128,
1191 if (rte
->prefixlen
> 128)
1193 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
1194 inet6_ntoa (rte
->addr
), rte
->prefixlen
,
1195 inet6_ntoa (from
->sin6_addr
), ifp
->name
);
1196 ripng_peer_bad_route (from
);
1200 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1201 if (! (rte
->metric
>= 1 && rte
->metric
<= 16))
1203 zlog_warn ("Invalid metric %d from %s%%%s", rte
->metric
,
1204 inet6_ntoa (from
->sin6_addr
), ifp
->name
);
1205 ripng_peer_bad_route (from
);
1209 /* Vincent: XXX Should we compute the direclty reachable nexthop
1210 * for our RIPng network ?
1213 /* Routing table updates. */
1214 ripng_route_process (rte
, from
, &nexthop
, ifp
);
1218 /* Response to request message. */
1220 ripng_request_process (struct ripng_packet
*packet
,int size
,
1221 struct sockaddr_in6
*from
, struct interface
*ifp
)
1225 struct prefix_ipv6 p
;
1226 struct route_node
*rp
;
1227 struct ripng_info
*rinfo
;
1228 struct ripng_interface
*ri
;
1230 /* Does not reponse to the requests on the loopback interfaces */
1231 if (if_is_loopback (ifp
))
1234 /* Check RIPng process is enabled on this interface. */
1239 /* When passive interface is specified, suppress responses */
1243 /* RIPng peer update. */
1244 ripng_peer_update (from
, packet
->version
);
1246 lim
= ((caddr_t
) packet
) + size
;
1249 /* The Request is processed entry by entry. If there are no
1250 entries, no response is given. */
1251 if (lim
== (caddr_t
) rte
)
1254 /* There is one special case. If there is exactly one entry in the
1255 request, and it has a destination prefix of zero, a prefix length
1256 of zero, and a metric of infinity (i.e., 16), then this is a
1257 request to send the entire routing table. In that case, a call
1258 is made to the output process to send the routing table to the
1259 requesting address/port. */
1260 if (lim
== ((caddr_t
) (rte
+ 1)) &&
1261 IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
) &&
1262 rte
->prefixlen
== 0 &&
1263 rte
->metric
== RIPNG_METRIC_INFINITY
)
1265 /* All route with split horizon */
1266 ripng_output_process (ifp
, from
, ripng_all_route
);
1270 /* Except for this special case, processing is quite simple.
1271 Examine the list of RTEs in the Request one by one. For each
1272 entry, look up the destination in the router's routing
1273 database and, if there is a route, put that route's metric in
1274 the metric field of the RTE. If there is no explicit route
1275 to the specified destination, put infinity in the metric
1276 field. Once all the entries have been filled in, change the
1277 command from Request to Response and send the datagram back
1278 to the requestor. */
1279 memset (&p
, 0, sizeof (struct prefix_ipv6
));
1280 p
.family
= AF_INET6
;
1282 for (; ((caddr_t
) rte
) < lim
; rte
++)
1284 p
.prefix
= rte
->addr
;
1285 p
.prefixlen
= rte
->prefixlen
;
1286 apply_mask_ipv6 (&p
);
1288 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) &p
);
1292 rinfo
= listgetdata (listhead ((struct list
*)rp
->info
));
1293 rte
->metric
= rinfo
->metric
;
1294 route_unlock_node (rp
);
1297 rte
->metric
= RIPNG_METRIC_INFINITY
;
1299 packet
->command
= RIPNG_RESPONSE
;
1301 ripng_send_packet ((caddr_t
) packet
, size
, from
, ifp
);
1305 /* First entry point of reading RIPng packet. */
1307 ripng_read (struct thread
*thread
)
1311 struct sockaddr_in6 from
;
1312 struct ripng_packet
*packet
;
1313 ifindex_t ifindex
= 0;
1314 struct interface
*ifp
;
1317 /* Check ripng is active and alive. */
1318 assert (ripng
!= NULL
);
1319 assert (ripng
->sock
>= 0);
1321 /* Fetch thread data and set read pointer to empty for event
1322 managing. `sock' sould be same as ripng->sock. */
1323 sock
= THREAD_FD (thread
);
1324 ripng
->t_read
= NULL
;
1326 /* Add myself to the next event. */
1327 ripng_event (RIPNG_READ
, sock
);
1329 /* Read RIPng packet. */
1330 len
= ripng_recv_packet (sock
, STREAM_DATA (ripng
->ibuf
),
1331 STREAM_SIZE (ripng
->ibuf
), &from
, &ifindex
,
1335 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno
));
1339 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1340 (4)) must be multiple size of one RTE size (20). */
1341 if (((len
- 4) % 20) != 0)
1343 zlog_warn ("RIPng invalid packet size %d from %s", len
,
1344 inet6_ntoa (from
.sin6_addr
));
1345 ripng_peer_bad_packet (&from
);
1349 packet
= (struct ripng_packet
*) STREAM_DATA (ripng
->ibuf
);
1350 ifp
= if_lookup_by_index (ifindex
, VRF_DEFAULT
);
1352 /* RIPng packet received. */
1353 if (IS_RIPNG_DEBUG_EVENT
)
1354 zlog_debug ("RIPng packet received from %s port %d on %s",
1355 inet6_ntoa (from
.sin6_addr
), ntohs (from
.sin6_port
),
1356 ifp
? ifp
->name
: "unknown");
1358 /* Logging before packet checking. */
1359 if (IS_RIPNG_DEBUG_RECV
)
1360 ripng_packet_dump (packet
, len
, "RECV");
1362 /* Packet comes from unknown interface. */
1365 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex
);
1369 /* Packet version mismatch checking. */
1370 if (packet
->version
!= ripng
->version
)
1372 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1373 packet
->version
, ripng
->version
);
1374 ripng_peer_bad_packet (&from
);
1378 /* Process RIPng packet. */
1379 switch (packet
->command
)
1382 ripng_request_process (packet
, len
, &from
, ifp
);
1384 case RIPNG_RESPONSE
:
1385 ripng_response_process (packet
, len
, &from
, ifp
, hoplimit
);
1388 zlog_warn ("Invalid RIPng command %d", packet
->command
);
1389 ripng_peer_bad_packet (&from
);
1395 /* Walk down the RIPng routing table then clear changed flag. */
1397 ripng_clear_changed_flag (void)
1399 struct route_node
*rp
;
1400 struct ripng_info
*rinfo
= NULL
;
1401 struct list
*list
= NULL
;
1402 struct listnode
*listnode
= NULL
;
1404 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1405 if ((list
= rp
->info
) != NULL
)
1406 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, rinfo
))
1408 UNSET_FLAG (rinfo
->flags
, RIPNG_RTF_CHANGED
);
1409 /* This flag can be set only on the first entry. */
1414 /* Regular update of RIPng route. Send all routing formation to RIPng
1415 enabled interface. */
1417 ripng_update (struct thread
*t
)
1419 struct listnode
*node
;
1420 struct interface
*ifp
;
1421 struct ripng_interface
*ri
;
1423 /* Clear update timer thread. */
1424 ripng
->t_update
= NULL
;
1426 /* Logging update event. */
1427 if (IS_RIPNG_DEBUG_EVENT
)
1428 zlog_debug ("RIPng update timer expired!");
1430 /* Supply routes to each interface. */
1431 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
1435 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1441 /* When passive interface is specified, suppress announce to the
1447 if (ri
->ri_send
== RIPNG_SEND_OFF
)
1449 if (IS_RIPNG_DEBUG_EVENT
)
1450 zlog_debug ("[Event] RIPng send to if %d is suppressed by config",
1454 #endif /* RIPNG_ADVANCED */
1456 ripng_output_process (ifp
, NULL
, ripng_all_route
);
1459 /* Triggered updates may be suppressed if a regular update is due by
1460 the time the triggered update would be sent. */
1461 if (ripng
->t_triggered_interval
)
1463 thread_cancel (ripng
->t_triggered_interval
);
1464 ripng
->t_triggered_interval
= NULL
;
1468 /* Reset flush event. */
1469 ripng_event (RIPNG_UPDATE_EVENT
, 0);
1474 /* Triggered update interval timer. */
1476 ripng_triggered_interval (struct thread
*t
)
1478 ripng
->t_triggered_interval
= NULL
;
1483 ripng_triggered_update (t
);
1488 /* Execute triggered update. */
1490 ripng_triggered_update (struct thread
*t
)
1492 struct listnode
*node
;
1493 struct interface
*ifp
;
1494 struct ripng_interface
*ri
;
1497 ripng
->t_triggered_update
= NULL
;
1499 /* Cancel interval timer. */
1500 if (ripng
->t_triggered_interval
)
1502 thread_cancel (ripng
->t_triggered_interval
);
1503 ripng
->t_triggered_interval
= NULL
;
1507 /* Logging triggered update. */
1508 if (IS_RIPNG_DEBUG_EVENT
)
1509 zlog_debug ("RIPng triggered update!");
1511 /* Split Horizon processing is done when generating triggered
1512 updates as well as normal updates (see section 2.6). */
1513 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
1517 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1523 /* When passive interface is specified, suppress announce to the
1528 ripng_output_process (ifp
, NULL
, ripng_changed_route
);
1531 /* Once all of the triggered updates have been generated, the route
1532 change flags should be cleared. */
1533 ripng_clear_changed_flag ();
1535 /* After a triggered update is sent, a timer should be set for a
1536 random interval between 1 and 5 seconds. If other changes that
1537 would trigger updates occur before the timer expires, a single
1538 update is triggered when the timer expires. */
1539 interval
= (random () % 5) + 1;
1541 ripng
->t_triggered_interval
= NULL
;
1542 thread_add_timer(master
, ripng_triggered_interval
, NULL
, interval
,
1543 &ripng
->t_triggered_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
)
1901 thread_add_read(master
, ripng_read
, NULL
, sock
, &ripng
->t_read
);
1903 case RIPNG_UPDATE_EVENT
:
1904 if (ripng
->t_update
)
1906 thread_cancel (ripng
->t_update
);
1907 ripng
->t_update
= NULL
;
1909 /* Update timer jitter. */
1910 jitter
= ripng_update_jitter (ripng
->update_time
);
1912 ripng
->t_update
= NULL
;
1913 thread_add_timer(master
, ripng_update
, NULL
, sock
? 2 : ripng
->update_time
+ jitter
,
1916 case RIPNG_TRIGGERED_UPDATE
:
1917 if (ripng
->t_triggered_interval
)
1919 else thread_add_event(master
, ripng_triggered_update
, NULL
, 0,
1920 &ripng
->t_triggered_update
);
1928 /* Print out routes update time. */
1930 ripng_vty_out_uptime (struct vty
*vty
, struct ripng_info
*rinfo
)
1935 char timebuf
[TIME_BUF
];
1936 struct thread
*thread
;
1938 if ((thread
= rinfo
->t_timeout
) != NULL
)
1940 clock
= thread_timer_remain_second (thread
);
1941 tm
= gmtime (&clock
);
1942 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1943 vty_out (vty
, "%5s", timebuf
);
1945 else if ((thread
= rinfo
->t_garbage_collect
) != NULL
)
1947 clock
= thread_timer_remain_second (thread
);
1948 tm
= gmtime (&clock
);
1949 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1950 vty_out (vty
, "%5s", timebuf
);
1955 ripng_route_subtype_print (struct ripng_info
*rinfo
)
1960 if (rinfo
->suppress
)
1963 switch (rinfo
->sub_type
)
1965 case RIPNG_ROUTE_RTE
:
1968 case RIPNG_ROUTE_STATIC
:
1971 case RIPNG_ROUTE_DEFAULT
:
1974 case RIPNG_ROUTE_REDISTRIBUTE
:
1977 case RIPNG_ROUTE_INTERFACE
:
1988 DEFUN (show_ipv6_ripng
,
1989 show_ipv6_ripng_cmd
,
1993 "Show RIPng routes\n")
1995 struct route_node
*rp
;
1996 struct ripng_info
*rinfo
;
1997 struct ripng_aggregate
*aggregate
;
1998 struct prefix_ipv6
*p
;
1999 struct list
*list
= NULL
;
2000 struct listnode
*listnode
= NULL
;
2006 /* Header of display. */
2007 vty_outln (vty
, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2009 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2010 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2011 " Network Next Hop Via Metric Tag Time",
2012 VTYNL
, VTYNL
, VTYNL
,
2015 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2017 if ((aggregate
= rp
->aggregate
) != NULL
)
2019 p
= (struct prefix_ipv6
*) &rp
->p
;
2022 vty_out (vty
, "R(a) %d/%d %s/%d ",
2023 aggregate
->count
, aggregate
->suppress
,
2024 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2026 vty_out (vty
, "R(a) %s/%d ",
2027 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2029 vty_out (vty
, VTYNL
);
2030 vty_out (vty
, "%*s", 18, " ");
2032 vty_out (vty
, "%*s", 28, " ");
2033 vty_outln (vty
, "self %2d %3"ROUTE_TAG_PRI
"", aggregate
->metric
,
2034 (route_tag_t
)aggregate
->tag
);
2037 if ((list
= rp
->info
) != NULL
)
2038 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, rinfo
))
2040 p
= (struct prefix_ipv6
*) &rp
->p
;
2043 vty_out (vty
, "%c(%s) 0/%d %s/%d ",
2044 zebra_route_char(rinfo
->type
),
2045 ripng_route_subtype_print(rinfo
),
2047 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2049 vty_out (vty
, "%c(%s) %s/%d ",
2050 zebra_route_char(rinfo
->type
),
2051 ripng_route_subtype_print(rinfo
),
2052 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2054 vty_out (vty
, VTYNL
);
2055 vty_out (vty
, "%*s", 18, " ");
2056 len
= vty_out (vty
, "%s", inet6_ntoa (rinfo
->nexthop
));
2060 len
= vty_out (vty
, "%*s", len
, " ");
2063 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2064 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2066 len
= vty_out (vty
, "%s", ifindex2ifname(rinfo
->ifindex
, VRF_DEFAULT
));
2067 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2069 len
= vty_out (vty
, "kill");
2071 len
= vty_out (vty
, "self");
2075 vty_out (vty
, "%*s", len
, " ");
2077 vty_out (vty
, " %2d %3"ROUTE_TAG_PRI
" ",
2078 rinfo
->metric
, (route_tag_t
)rinfo
->tag
);
2081 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2082 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2084 /* RTE from remote RIP routers */
2085 ripng_vty_out_uptime (vty
, rinfo
);
2086 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2088 /* poisonous reversed routes (gc) */
2089 ripng_vty_out_uptime (vty
, rinfo
);
2092 vty_out (vty
, VTYNL
);
2099 DEFUN (show_ipv6_ripng_status
,
2100 show_ipv6_ripng_status_cmd
,
2101 "show ipv6 ripng status",
2104 "Show RIPng routes\n"
2105 "IPv6 routing protocol process parameters and statistics\n")
2107 struct listnode
*node
;
2108 struct interface
*ifp
;
2113 vty_outln (vty
, "Routing Protocol is \"RIPng\"");
2114 vty_out (vty
, " Sending updates every %ld seconds with +/-50%%,",
2115 ripng
->update_time
);
2116 vty_outln (vty
, " next due in %lu seconds",
2117 thread_timer_remain_second(ripng
->t_update
));
2118 vty_out (vty
, " Timeout after %ld seconds,", ripng
->timeout_time
);
2119 vty_outln (vty
, " garbage collect after %ld seconds",ripng
->garbage_time
);
2121 /* Filtering status show. */
2122 config_show_distribute (vty
);
2124 /* Default metric information. */
2125 vty_outln (vty
, " Default redistribution metric is %d",
2126 ripng
->default_metric
);
2128 /* Redistribute information. */
2129 vty_out (vty
, " Redistributing:");
2130 ripng_redistribute_write (vty
, 0);
2131 vty_out (vty
, VTYNL
);
2133 vty_out (vty
, " Default version control: send version %d,", ripng
->version
);
2134 vty_outln (vty
, " receive version %d ",ripng
->version
);
2136 vty_outln (vty
, " Interface Send Recv");
2138 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
2140 struct ripng_interface
*ri
;
2144 if (ri
->enable_network
|| ri
->enable_interface
)
2147 vty_outln (vty
, " %-17s%-3d %-3d", ifp
->name
,
2153 vty_outln (vty
, " Routing for Networks:");
2154 ripng_network_write (vty
, 0);
2156 vty_outln (vty
, " Routing Information Sources:");
2158 " Gateway BadPackets BadRoutes Distance Last Update");
2159 ripng_peer_display (vty
);
2164 DEFUN (clear_ipv6_rip
,
2169 "Clear IPv6 RIP database\n")
2171 struct route_node
*rp
;
2172 struct ripng_info
*rinfo
;
2174 struct listnode
*listnode
;
2176 /* Clear received RIPng routes */
2177 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2183 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, rinfo
))
2185 if (! ripng_route_rte (rinfo
))
2188 if (CHECK_FLAG (rinfo
->flags
, RIPNG_RTF_FIB
))
2189 ripng_zebra_ipv6_delete (rp
);
2195 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
2196 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
2197 listnode_delete (list
, rinfo
);
2198 ripng_info_free (rinfo
);
2201 if (list_isempty (list
))
2205 route_unlock_node (rp
);
2212 DEFUN_NOSH (router_ripng
,
2215 "Enable a routing process\n"
2216 "Make RIPng instance command\n")
2220 vty
->node
= RIPNG_NODE
;
2224 ret
= ripng_create ();
2226 /* Notice to user we couldn't create RIPng. */
2229 zlog_warn ("can't create RIPng");
2230 return CMD_WARNING_CONFIG_FAILED
;
2237 DEFUN (no_router_ripng
,
2238 no_router_ripng_cmd
,
2241 "Enable a routing process\n"
2242 "Make RIPng instance command\n")
2252 "Static route setup\n"
2253 "Set static RIPng route announcement\n")
2255 int idx_ipv6addr
= 1;
2257 struct prefix_ipv6 p
;
2258 struct route_node
*rp
;
2260 ret
= str2prefix_ipv6 (argv
[idx_ipv6addr
]->arg
, (struct prefix_ipv6
*)&p
);
2263 vty_outln (vty
, "Malformed address");
2264 return CMD_WARNING_CONFIG_FAILED
;
2266 apply_mask_ipv6 (&p
);
2268 rp
= route_node_get (ripng
->route
, (struct prefix
*) &p
);
2271 vty_outln (vty
, "There is already same static route.");
2272 route_unlock_node (rp
);
2273 return CMD_WARNING_CONFIG_FAILED
;
2275 rp
->info
= (void *)1;
2277 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0, NULL
, 0);
2282 DEFUN (no_ripng_route
,
2284 "no route IPV6ADDR",
2286 "Static route setup\n"
2287 "Delete static RIPng route announcement\n")
2289 int idx_ipv6addr
= 2;
2291 struct prefix_ipv6 p
;
2292 struct route_node
*rp
;
2294 ret
= str2prefix_ipv6 (argv
[idx_ipv6addr
]->arg
, (struct prefix_ipv6
*)&p
);
2297 vty_outln (vty
, "Malformed address");
2298 return CMD_WARNING_CONFIG_FAILED
;
2300 apply_mask_ipv6 (&p
);
2302 rp
= route_node_lookup (ripng
->route
, (struct prefix
*) &p
);
2305 vty_outln (vty
, "Can't find static route.");
2306 return CMD_WARNING_CONFIG_FAILED
;
2309 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0);
2310 route_unlock_node (rp
);
2313 route_unlock_node (rp
);
2318 DEFUN (ripng_aggregate_address
,
2319 ripng_aggregate_address_cmd
,
2320 "aggregate-address X:X::X:X/M",
2321 "Set aggregate RIPng route announcement\n"
2322 "Aggregate network\n")
2324 int idx_ipv6_prefixlen
= 1;
2327 struct route_node
*node
;
2329 ret
= str2prefix_ipv6 (argv
[idx_ipv6_prefixlen
]->arg
, (struct prefix_ipv6
*)&p
);
2332 vty_outln (vty
, "Malformed address");
2333 return CMD_WARNING_CONFIG_FAILED
;
2336 /* Check aggregate alredy exist or not. */
2337 node
= route_node_get (ripng
->aggregate
, &p
);
2340 vty_outln (vty
, "There is already same aggregate route.");
2341 route_unlock_node (node
);
2342 return CMD_WARNING_CONFIG_FAILED
;
2344 node
->info
= (void *)1;
2346 ripng_aggregate_add (&p
);
2351 DEFUN (no_ripng_aggregate_address
,
2352 no_ripng_aggregate_address_cmd
,
2353 "no aggregate-address X:X::X:X/M",
2355 "Delete aggregate RIPng route announcement\n"
2356 "Aggregate network\n")
2358 int idx_ipv6_prefixlen
= 2;
2361 struct route_node
*rn
;
2363 ret
= str2prefix_ipv6 (argv
[idx_ipv6_prefixlen
]->arg
, (struct prefix_ipv6
*) &p
);
2366 vty_outln (vty
, "Malformed address");
2367 return CMD_WARNING_CONFIG_FAILED
;
2370 rn
= route_node_lookup (ripng
->aggregate
, &p
);
2373 vty_outln (vty
, "Can't find aggregate route.");
2374 return CMD_WARNING_CONFIG_FAILED
;
2376 route_unlock_node (rn
);
2378 route_unlock_node (rn
);
2380 ripng_aggregate_delete (&p
);
2385 DEFUN (ripng_default_metric
,
2386 ripng_default_metric_cmd
,
2387 "default-metric (1-16)",
2388 "Set a metric of redistribute routes\n"
2394 ripng
->default_metric
= atoi (argv
[idx_number
]->arg
);
2399 DEFUN (no_ripng_default_metric
,
2400 no_ripng_default_metric_cmd
,
2401 "no default-metric [(1-16)]",
2403 "Set a metric of redistribute routes\n"
2408 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
2415 /* RIPng update timer setup. */
2416 DEFUN (ripng_update_timer
,
2417 ripng_update_timer_cmd
,
2418 "update-timer SECOND",
2419 "Set RIPng update timer in seconds\n"
2422 unsigned long update
;
2423 char *endptr
= NULL
;
2425 update
= strtoul (argv
[0], &endptr
, 10);
2426 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2428 vty_out (vty
, "update timer value error%s", VTYNL
);
2429 return CMD_WARNING_CONFIG_FAILED
;
2432 ripng
->update_time
= update
;
2434 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2438 DEFUN (no_ripng_update_timer
,
2439 no_ripng_update_timer_cmd
,
2440 "no update-timer SECOND",
2442 "Unset RIPng update timer in seconds\n"
2445 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2446 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2450 /* RIPng timeout timer setup. */
2451 DEFUN (ripng_timeout_timer
,
2452 ripng_timeout_timer_cmd
,
2453 "timeout-timer SECOND",
2454 "Set RIPng timeout timer in seconds\n"
2457 unsigned long timeout
;
2458 char *endptr
= NULL
;
2460 timeout
= strtoul (argv
[0], &endptr
, 10);
2461 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2463 vty_out (vty
, "timeout timer value error%s", VTYNL
);
2464 return CMD_WARNING_CONFIG_FAILED
;
2467 ripng
->timeout_time
= timeout
;
2472 DEFUN (no_ripng_timeout_timer
,
2473 no_ripng_timeout_timer_cmd
,
2474 "no timeout-timer SECOND",
2476 "Unset RIPng timeout timer in seconds\n"
2479 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2483 /* RIPng garbage timer setup. */
2484 DEFUN (ripng_garbage_timer
,
2485 ripng_garbage_timer_cmd
,
2486 "garbage-timer SECOND",
2487 "Set RIPng garbage timer in seconds\n"
2490 unsigned long garbage
;
2491 char *endptr
= NULL
;
2493 garbage
= strtoul (argv
[0], &endptr
, 10);
2494 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2496 vty_out (vty
, "garbage timer value error%s", VTYNL
);
2497 return CMD_WARNING_CONFIG_FAILED
;
2500 ripng
->garbage_time
= garbage
;
2505 DEFUN (no_ripng_garbage_timer
,
2506 no_ripng_garbage_timer_cmd
,
2507 "no garbage-timer SECOND",
2509 "Unset RIPng garbage timer in seconds\n"
2512 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2517 DEFUN (ripng_timers
,
2519 "timers basic (0-65535) (0-65535) (0-65535)",
2520 "RIPng timers setup\n"
2522 "Routing table update timer value in second. Default is 30.\n"
2523 "Routing information timeout timer. Default is 180.\n"
2524 "Garbage collection timer. Default is 120.\n")
2527 int idx_number_2
= 3;
2528 int idx_number_3
= 4;
2529 unsigned long update
;
2530 unsigned long timeout
;
2531 unsigned long garbage
;
2533 update
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2534 timeout
= strtoul(argv
[idx_number_2
]->arg
, NULL
, 10);
2535 garbage
= strtoul(argv
[idx_number_3
]->arg
, NULL
, 10);
2537 /* Set each timer value. */
2538 ripng
->update_time
= update
;
2539 ripng
->timeout_time
= timeout
;
2540 ripng
->garbage_time
= garbage
;
2542 /* Reset update timer thread. */
2543 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2548 DEFUN (no_ripng_timers
,
2549 no_ripng_timers_cmd
,
2550 "no timers basic [(0-65535) (0-65535) (0-65535)]",
2552 "RIPng timers setup\n"
2554 "Routing table update timer value in second. Default is 30.\n"
2555 "Routing information timeout timer. Default is 180.\n"
2556 "Garbage collection timer. Default is 120.\n")
2558 /* Set each timer value to the default. */
2559 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2560 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2561 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2563 /* Reset update timer thread. */
2564 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2570 DEFUN (show_ipv6_protocols
,
2571 show_ipv6_protocols_cmd
,
2572 "show ipv6 protocols",
2575 "Routing protocol information\n")
2580 vty_out (vty
, "Routing Protocol is \"ripng\"%s", VTYNL
);
2582 vty_out (vty
, "Sending updates every %ld seconds, next due in %d seconds%s",
2583 ripng
->update_time
, 0,
2586 vty_out (vty
, "Timerout after %ld seconds, garbage correct %ld%s",
2587 ripng
->timeout_time
,
2588 ripng
->garbage_time
,
2591 vty_out (vty
, "Outgoing update filter list for all interfaces is not set");
2592 vty_out (vty
, "Incoming update filter list for all interfaces is not set");
2598 /* Please be carefull to use this command. */
2599 DEFUN (ripng_default_information_originate
,
2600 ripng_default_information_originate_cmd
,
2601 "default-information originate",
2602 "Default route information\n"
2603 "Distribute default route\n")
2605 struct prefix_ipv6 p
;
2607 if (! ripng
->default_information
) {
2608 ripng
->default_information
= 1;
2610 str2prefix_ipv6 ("::/0", &p
);
2611 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0, NULL
, 0);
2617 DEFUN (no_ripng_default_information_originate
,
2618 no_ripng_default_information_originate_cmd
,
2619 "no default-information originate",
2621 "Default route information\n"
2622 "Distribute default route\n")
2624 struct prefix_ipv6 p
;
2626 if (ripng
->default_information
) {
2627 ripng
->default_information
= 0;
2629 str2prefix_ipv6 ("::/0", &p
);
2630 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0);
2636 /* Update ECMP routes to zebra when ECMP is disabled. */
2638 ripng_ecmp_disable (void)
2640 struct route_node
*rp
;
2641 struct ripng_info
*rinfo
, *tmp_rinfo
;
2643 struct listnode
*node
, *nextnode
;
2648 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2649 if ((list
= rp
->info
) != NULL
&& listcount (list
) > 1)
2651 rinfo
= listgetdata (listhead (list
));
2652 if (!ripng_route_rte (rinfo
))
2655 /* Drop all other entries, except the first one. */
2656 for (ALL_LIST_ELEMENTS (list
, node
, nextnode
, tmp_rinfo
))
2657 if (tmp_rinfo
!= rinfo
)
2659 RIPNG_TIMER_OFF (tmp_rinfo
->t_timeout
);
2660 RIPNG_TIMER_OFF (tmp_rinfo
->t_garbage_collect
);
2661 list_delete_node (list
, node
);
2662 ripng_info_free (tmp_rinfo
);
2666 ripng_zebra_ipv6_add (rp
);
2668 /* Set the route change flag. */
2669 SET_FLAG (rinfo
->flags
, RIPNG_RTF_CHANGED
);
2671 /* Signal the output process to trigger an update. */
2672 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
2676 DEFUN (ripng_allow_ecmp
,
2677 ripng_allow_ecmp_cmd
,
2679 "Allow Equal Cost MultiPath\n")
2683 vty_outln (vty
, "ECMP is already enabled.");
2684 return CMD_WARNING_CONFIG_FAILED
;
2688 zlog_info ("ECMP is enabled.");
2692 DEFUN (no_ripng_allow_ecmp
,
2693 no_ripng_allow_ecmp_cmd
,
2696 "Allow Equal Cost MultiPath\n")
2700 vty_outln (vty
, "ECMP is already disabled.");
2701 return CMD_WARNING_CONFIG_FAILED
;
2705 zlog_info ("ECMP is disabled.");
2706 ripng_ecmp_disable ();
2710 /* RIPng configuration write function. */
2712 ripng_config_write (struct vty
*vty
)
2714 int ripng_network_write (struct vty
*, int);
2715 void ripng_redistribute_write (struct vty
*, int);
2717 struct route_node
*rp
;
2723 vty_outln (vty
, "router ripng");
2725 if (ripng
->default_information
)
2726 vty_outln (vty
, " default-information originate");
2728 ripng_network_write (vty
, 1);
2730 /* RIPng default metric configuration */
2731 if (ripng
->default_metric
!= RIPNG_DEFAULT_METRIC_DEFAULT
)
2732 vty_outln (vty
, " default-metric %d",
2733 ripng
->default_metric
);
2735 ripng_redistribute_write (vty
, 1);
2737 /* RIP offset-list configuration. */
2738 config_write_ripng_offset_list (vty
);
2740 /* RIPng aggregate routes. */
2741 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2742 if (rp
->info
!= NULL
)
2743 vty_outln (vty
, " aggregate-address %s/%d",
2744 inet6_ntoa (rp
->p
.u
.prefix6
),
2747 /* ECMP configuration. */
2749 vty_outln (vty
, " allow-ecmp");
2751 /* RIPng static routes. */
2752 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2753 if (rp
->info
!= NULL
)
2754 vty_outln (vty
, " route %s/%d", inet6_ntoa (rp
->p
.u
.prefix6
),
2757 /* RIPng timers configuration. */
2758 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
||
2759 ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
||
2760 ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2762 vty_outln (vty
, " timers basic %ld %ld %ld",
2764 ripng
->timeout_time
,
2765 ripng
->garbage_time
);
2768 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
)
2769 vty_out (vty
, " update-timer %d%s", ripng
->update_time
,
2771 if (ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
)
2772 vty_out (vty
, " timeout-timer %d%s", ripng
->timeout_time
,
2774 if (ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2775 vty_out (vty
, " garbage-timer %d%s", ripng
->garbage_time
,
2779 write
+= config_write_distribute (vty
);
2781 write
+= config_write_if_rmap (vty
);
2788 /* RIPng node structure. */
2789 static struct cmd_node cmd_ripng_node
=
2792 "%s(config-router)# ",
2797 ripng_distribute_update (struct distribute
*dist
)
2799 struct interface
*ifp
;
2800 struct ripng_interface
*ri
;
2801 struct access_list
*alist
;
2802 struct prefix_list
*plist
;
2807 ifp
= if_lookup_by_name (dist
->ifname
, VRF_DEFAULT
);
2813 if (dist
->list
[DISTRIBUTE_V6_IN
])
2815 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_V6_IN
]);
2817 ri
->list
[RIPNG_FILTER_IN
] = alist
;
2819 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2822 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2824 if (dist
->list
[DISTRIBUTE_V6_OUT
])
2826 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_V6_OUT
]);
2828 ri
->list
[RIPNG_FILTER_OUT
] = alist
;
2830 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2833 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2835 if (dist
->prefix
[DISTRIBUTE_V6_IN
])
2837 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_V6_IN
]);
2839 ri
->prefix
[RIPNG_FILTER_IN
] = plist
;
2841 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2844 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2846 if (dist
->prefix
[DISTRIBUTE_V6_OUT
])
2848 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_V6_OUT
]);
2850 ri
->prefix
[RIPNG_FILTER_OUT
] = plist
;
2852 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2855 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2859 ripng_distribute_update_interface (struct interface
*ifp
)
2861 struct distribute
*dist
;
2863 dist
= distribute_lookup (ifp
->name
);
2865 ripng_distribute_update (dist
);
2868 /* Update all interface's distribute list. */
2870 ripng_distribute_update_all (struct prefix_list
*notused
)
2872 struct interface
*ifp
;
2873 struct listnode
*node
;
2875 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
2876 ripng_distribute_update_interface (ifp
);
2880 ripng_distribute_update_all_wrapper (struct access_list
*notused
)
2882 ripng_distribute_update_all(NULL
);
2885 /* delete all the added ripng routes. */
2890 struct route_node
*rp
;
2891 struct ripng_info
*rinfo
;
2892 struct ripng_aggregate
*aggregate
;
2893 struct list
*list
= NULL
;
2894 struct listnode
*listnode
= NULL
;
2897 /* Clear RIPng routes */
2898 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2900 if ((list
= rp
->info
) != NULL
)
2902 rinfo
= listgetdata (listhead (list
));
2903 if (ripng_route_rte (rinfo
))
2904 ripng_zebra_ipv6_delete (rp
);
2906 for (ALL_LIST_ELEMENTS_RO (list
, listnode
, rinfo
))
2908 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
2909 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
2910 ripng_info_free (rinfo
);
2914 route_unlock_node (rp
);
2917 if ((aggregate
= rp
->aggregate
) != NULL
)
2919 ripng_aggregate_free (aggregate
);
2920 rp
->aggregate
= NULL
;
2921 route_unlock_node (rp
);
2925 /* Cancel the RIPng timers */
2926 RIPNG_TIMER_OFF (ripng
->t_update
);
2927 RIPNG_TIMER_OFF (ripng
->t_triggered_update
);
2928 RIPNG_TIMER_OFF (ripng
->t_triggered_interval
);
2930 /* Cancel the read thread */
2931 if (ripng
->t_read
) {
2932 thread_cancel (ripng
->t_read
);
2933 ripng
->t_read
= NULL
;
2936 /* Close the RIPng socket */
2937 if (ripng
->sock
>= 0) {
2942 /* Static RIPng route configuration. */
2943 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2946 route_unlock_node (rp
);
2949 /* RIPng aggregated prefixes */
2950 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2953 route_unlock_node (rp
);
2956 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2957 if (ripng
->route_map
[i
].name
)
2958 free (ripng
->route_map
[i
].name
);
2960 XFREE (MTYPE_ROUTE_TABLE
, ripng
->table
);
2961 XFREE (MTYPE_ROUTE_TABLE
, ripng
->route
);
2962 XFREE (MTYPE_ROUTE_TABLE
, ripng
->aggregate
);
2964 stream_free (ripng
->ibuf
);
2965 stream_free (ripng
->obuf
);
2967 XFREE (MTYPE_RIPNG
, ripng
);
2971 ripng_clean_network();
2972 ripng_passive_interface_clean ();
2973 ripng_offset_clean ();
2974 ripng_interface_clean ();
2975 ripng_redistribute_clean ();
2978 /* Reset all values to the default settings. */
2982 /* Call ripd related reset functions. */
2983 ripng_debug_reset ();
2984 ripng_route_map_reset ();
2986 /* Call library reset functions. */
2988 access_list_reset ();
2989 prefix_list_reset ();
2991 distribute_list_reset ();
2993 ripng_interface_reset ();
2995 ripng_zclient_reset ();
2999 ripng_if_rmap_update (struct if_rmap
*if_rmap
)
3001 struct interface
*ifp
;
3002 struct ripng_interface
*ri
;
3003 struct route_map
*rmap
;
3005 ifp
= if_lookup_by_name (if_rmap
->ifname
, VRF_DEFAULT
);
3011 if (if_rmap
->routemap
[IF_RMAP_IN
])
3013 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_IN
]);
3015 ri
->routemap
[IF_RMAP_IN
] = rmap
;
3017 ri
->routemap
[IF_RMAP_IN
] = NULL
;
3020 ri
->routemap
[RIPNG_FILTER_IN
] = NULL
;
3022 if (if_rmap
->routemap
[IF_RMAP_OUT
])
3024 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_OUT
]);
3026 ri
->routemap
[IF_RMAP_OUT
] = rmap
;
3028 ri
->routemap
[IF_RMAP_OUT
] = NULL
;
3031 ri
->routemap
[RIPNG_FILTER_OUT
] = NULL
;
3035 ripng_if_rmap_update_interface (struct interface
*ifp
)
3037 struct if_rmap
*if_rmap
;
3039 if_rmap
= if_rmap_lookup (ifp
->name
);
3041 ripng_if_rmap_update (if_rmap
);
3045 ripng_routemap_update_redistribute (void)
3051 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
3053 if (ripng
->route_map
[i
].name
)
3054 ripng
->route_map
[i
].map
=
3055 route_map_lookup_by_name (ripng
->route_map
[i
].name
);
3061 ripng_routemap_update (const char *unused
)
3063 struct interface
*ifp
;
3064 struct listnode
*node
;
3066 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
3067 ripng_if_rmap_update_interface (ifp
);
3069 ripng_routemap_update_redistribute ();
3072 /* Initialize ripng structure and set commands. */
3076 /* Install RIPNG_NODE. */
3077 install_node (&cmd_ripng_node
, ripng_config_write
);
3079 /* Install ripng commands. */
3080 install_element (VIEW_NODE
, &show_ipv6_ripng_cmd
);
3081 install_element (VIEW_NODE
, &show_ipv6_ripng_status_cmd
);
3083 install_element (ENABLE_NODE
, &clear_ipv6_rip_cmd
);
3085 install_element (CONFIG_NODE
, &router_ripng_cmd
);
3086 install_element (CONFIG_NODE
, &no_router_ripng_cmd
);
3088 install_default (RIPNG_NODE
);
3089 install_element (RIPNG_NODE
, &ripng_route_cmd
);
3090 install_element (RIPNG_NODE
, &no_ripng_route_cmd
);
3091 install_element (RIPNG_NODE
, &ripng_aggregate_address_cmd
);
3092 install_element (RIPNG_NODE
, &no_ripng_aggregate_address_cmd
);
3094 install_element (RIPNG_NODE
, &ripng_default_metric_cmd
);
3095 install_element (RIPNG_NODE
, &no_ripng_default_metric_cmd
);
3097 install_element (RIPNG_NODE
, &ripng_timers_cmd
);
3098 install_element (RIPNG_NODE
, &no_ripng_timers_cmd
);
3100 install_element (VIEW_NODE
, &show_ipv6_protocols_cmd
);
3101 install_element (RIPNG_NODE
, &ripng_update_timer_cmd
);
3102 install_element (RIPNG_NODE
, &no_ripng_update_timer_cmd
);
3103 install_element (RIPNG_NODE
, &ripng_timeout_timer_cmd
);
3104 install_element (RIPNG_NODE
, &no_ripng_timeout_timer_cmd
);
3105 install_element (RIPNG_NODE
, &ripng_garbage_timer_cmd
);
3106 install_element (RIPNG_NODE
, &no_ripng_garbage_timer_cmd
);
3109 install_element (RIPNG_NODE
, &ripng_default_information_originate_cmd
);
3110 install_element (RIPNG_NODE
, &no_ripng_default_information_originate_cmd
);
3112 install_element (RIPNG_NODE
, &ripng_allow_ecmp_cmd
);
3113 install_element (RIPNG_NODE
, &no_ripng_allow_ecmp_cmd
);
3116 ripng_debug_init ();
3118 /* Access list install. */
3119 access_list_init ();
3120 access_list_add_hook (ripng_distribute_update_all_wrapper
);
3121 access_list_delete_hook (ripng_distribute_update_all_wrapper
);
3123 /* Prefix list initialize.*/
3124 prefix_list_init ();
3125 prefix_list_add_hook (ripng_distribute_update_all
);
3126 prefix_list_delete_hook (ripng_distribute_update_all
);
3128 /* Distribute list install. */
3129 distribute_list_init (RIPNG_NODE
);
3130 distribute_list_add_hook (ripng_distribute_update
);
3131 distribute_list_delete_hook (ripng_distribute_update
);
3133 /* Route-map for interface. */
3134 ripng_route_map_init ();
3135 ripng_offset_init ();
3137 route_map_add_hook (ripng_routemap_update
);
3138 route_map_delete_hook (ripng_routemap_update
);
3140 if_rmap_init (RIPNG_NODE
);
3141 if_rmap_hook_add (ripng_if_rmap_update
);
3142 if_rmap_hook_delete (ripng_if_rmap_update
);