2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
34 #include "distribute.h"
40 #include "ripngd/ripngd.h"
41 #include "ripngd/ripng_route.h"
42 #include "ripngd/ripng_debug.h"
43 #include "ripngd/ripng_nexthop.h"
45 /* RIPng structure which includes many parameters related to RIPng
46 protocol. If ripng couldn't active or ripng doesn't configured,
47 ripng->fd must be negative value. */
48 struct ripng
*ripng
= NULL
;
56 extern struct zebra_privs_t ripngd_privs
;
60 ripng_output_process (struct interface
*, struct sockaddr_in6
*, int);
63 ripng_triggered_update (struct thread
*);
65 /* RIPng next hop specification. */
68 enum ripng_nexthop_type
73 struct in6_addr address
;
77 ripng_route_rte (struct ripng_info
*rinfo
)
79 return (rinfo
->type
== ZEBRA_ROUTE_RIPNG
&& rinfo
->sub_type
== RIPNG_ROUTE_RTE
);
82 /* Allocate new ripng information. */
86 struct ripng_info
*new;
88 new = XCALLOC (MTYPE_RIPNG_ROUTE
, sizeof (struct ripng_info
));
92 /* Free ripng information. */
94 ripng_info_free (struct ripng_info
*rinfo
)
96 XFREE (MTYPE_RIPNG_ROUTE
, rinfo
);
99 /* Create ripng socket. */
101 ripng_make_socket (void)
105 struct sockaddr_in6 ripaddr
;
107 sock
= socket (AF_INET6
, SOCK_DGRAM
, 0);
110 zlog (NULL
, LOG_ERR
, "Can't make ripng socket");
114 ret
= setsockopt_so_recvbuf (sock
, 8096);
117 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
120 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
123 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
126 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
130 memset (&ripaddr
, 0, sizeof (ripaddr
));
131 ripaddr
.sin6_family
= AF_INET6
;
133 ripaddr
.sin6_len
= sizeof (struct sockaddr_in6
);
134 #endif /* SIN6_LEN */
135 ripaddr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
137 if (ripngd_privs
.change (ZPRIVS_RAISE
))
138 zlog_err ("ripng_make_socket: could not raise privs");
140 ret
= bind (sock
, (struct sockaddr
*) &ripaddr
, sizeof (ripaddr
));
143 zlog (NULL
, LOG_ERR
, "Can't bind ripng socket: %s.", safe_strerror (errno
));
144 if (ripngd_privs
.change (ZPRIVS_LOWER
))
145 zlog_err ("ripng_make_socket: could not lower privs");
148 if (ripngd_privs
.change (ZPRIVS_LOWER
))
149 zlog_err ("ripng_make_socket: could not lower privs");
153 /* Send RIPng packet. */
155 ripng_send_packet (caddr_t buf
, int bufsize
, struct sockaddr_in6
*to
,
156 struct interface
*ifp
)
161 struct cmsghdr
*cmsgptr
;
163 struct in6_pktinfo
*pkt
;
164 struct sockaddr_in6 addr
;
166 if (IS_RIPNG_DEBUG_SEND
) {
168 zlog_debug ("send to %s", inet6_ntoa (to
->sin6_addr
));
169 zlog_debug (" send interface %s", ifp
->name
);
170 zlog_debug (" send packet size %d", bufsize
);
173 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
174 addr
.sin6_family
= AF_INET6
;
176 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
177 #endif /* SIN6_LEN */
178 addr
.sin6_flowinfo
= htonl (RIPNG_PRIORITY_DEFAULT
);
180 /* When destination is specified. */
183 addr
.sin6_addr
= to
->sin6_addr
;
184 addr
.sin6_port
= to
->sin6_port
;
188 inet_pton(AF_INET6
, RIPNG_GROUP
, &addr
.sin6_addr
);
189 addr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
192 msg
.msg_name
= (void *) &addr
;
193 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
196 msg
.msg_control
= (void *) adata
;
197 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
200 iov
.iov_len
= bufsize
;
202 cmsgptr
= (struct cmsghdr
*)adata
;
203 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof (struct in6_pktinfo
));
204 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
205 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
207 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
208 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
209 pkt
->ipi6_ifindex
= ifp
->ifindex
;
211 ret
= sendmsg (ripng
->sock
, &msg
, 0);
215 zlog_err ("RIPng send fail on %s to %s: %s", ifp
->name
,
216 inet6_ntoa (to
->sin6_addr
), safe_strerror (errno
));
218 zlog_err ("RIPng send fail on %s: %s", ifp
->name
, safe_strerror (errno
));
224 /* Receive UDP RIPng packet from socket. */
226 ripng_recv_packet (int sock
, u_char
*buf
, int bufsize
,
227 struct sockaddr_in6
*from
, unsigned int *ifindex
,
233 struct cmsghdr
*cmsgptr
;
236 /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this
237 point I can't determine size of cmsghdr */
240 /* Fill in message and iovec. */
241 msg
.msg_name
= (void *) from
;
242 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
245 msg
.msg_control
= (void *) adata
;
246 msg
.msg_controllen
= sizeof adata
;
248 iov
.iov_len
= bufsize
;
250 /* If recvmsg fail return minus value. */
251 ret
= recvmsg (sock
, &msg
, 0);
255 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
256 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
258 /* I want interface index which this packet comes from. */
259 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
260 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
262 struct in6_pktinfo
*ptr
;
264 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
265 *ifindex
= ptr
->ipi6_ifindex
;
266 dst
= ptr
->ipi6_addr
;
269 zlog_warn ("Interface index returned by IPV6_PKTINFO is zero");
272 /* Incoming packet's multicast hop limit. */
273 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
274 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
276 int *phoplimit
= (int *) CMSG_DATA (cmsgptr
);
277 *hoplimit
= *phoplimit
;
281 /* Hoplimit check shold be done when destination address is
282 multicast address. */
283 if (! IN6_IS_ADDR_MULTICAST (&dst
))
289 /* Dump rip packet */
291 ripng_packet_dump (struct ripng_packet
*packet
, int size
, const char *sndrcv
)
295 const char *command_str
;
297 /* Set command string. */
298 if (packet
->command
== RIPNG_REQUEST
)
299 command_str
= "request";
300 else if (packet
->command
== RIPNG_RESPONSE
)
301 command_str
= "response";
303 command_str
= "unknown";
305 /* Dump packet header. */
306 zlog_debug ("%s %s version %d packet size %d",
307 sndrcv
, command_str
, packet
->version
, size
);
309 /* Dump each routing table entry. */
312 for (lim
= (caddr_t
) packet
+ size
; (caddr_t
) rte
< lim
; rte
++)
314 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
315 zlog_debug (" nexthop %s/%d", inet6_ntoa (rte
->addr
), rte
->prefixlen
);
317 zlog_debug (" %s/%d metric %d tag %d",
318 inet6_ntoa (rte
->addr
), rte
->prefixlen
,
319 rte
->metric
, ntohs (rte
->tag
));
323 /* RIPng next hop address RTE (Route Table Entry). */
325 ripng_nexthop_rte (struct rte
*rte
,
326 struct sockaddr_in6
*from
,
327 struct ripng_nexthop
*nexthop
)
329 char buf
[INET6_BUFSIZ
];
331 /* Logging before checking RTE. */
332 if (IS_RIPNG_DEBUG_RECV
)
333 zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d",
334 inet6_ntoa (rte
->addr
), ntohs (rte
->tag
), rte
->prefixlen
);
336 /* RFC2080 2.1.1 Next Hop:
337 The route tag and prefix length in the next hop RTE must be
338 set to zero on sending and ignored on receiption. */
339 if (ntohs (rte
->tag
) != 0)
340 zlog_warn ("RIPng nexthop RTE with non zero tag value %d from %s",
341 ntohs (rte
->tag
), inet6_ntoa (from
->sin6_addr
));
343 if (rte
->prefixlen
!= 0)
344 zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
345 rte
->prefixlen
, inet6_ntoa (from
->sin6_addr
));
347 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
348 next hop RTE indicates that the next hop address should be the
349 originator of the RIPng advertisement. An address specified as a
350 next hop must be a link-local address. */
351 if (IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
))
353 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
354 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
358 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
360 nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
361 IPV6_ADDR_COPY (&nexthop
->address
, &rte
->addr
);
365 /* The purpose of the next hop RTE is to eliminate packets being
366 routed through extra hops in the system. It is particularly useful
367 when RIPng is not being run on all of the routers on a network.
368 Note that next hop RTE is "advisory". That is, if the provided
369 information is ignored, a possibly sub-optimal, but absolutely
370 valid, route may be taken. If the received next hop address is not
371 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
372 zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s",
373 inet6_ntoa (rte
->addr
),
374 inet_ntop (AF_INET6
, &from
->sin6_addr
, buf
, INET6_BUFSIZ
));
376 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
377 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
382 /* If ifp has same link-local address then return 1. */
384 ripng_lladdr_check (struct interface
*ifp
, struct in6_addr
*addr
)
386 struct listnode
*node
;
387 struct connected
*connected
;
390 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, connected
))
392 p
= connected
->address
;
394 if (p
->family
== AF_INET6
&&
395 IN6_IS_ADDR_LINKLOCAL (&p
->u
.prefix6
) &&
396 IN6_ARE_ADDR_EQUAL (&p
->u
.prefix6
, addr
))
402 /* RIPng route garbage collect timer. */
404 ripng_garbage_collect (struct thread
*t
)
406 struct ripng_info
*rinfo
;
407 struct route_node
*rp
;
409 rinfo
= THREAD_ARG (t
);
410 rinfo
->t_garbage_collect
= NULL
;
412 /* Off timeout timer. */
413 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
415 /* Get route_node pointer. */
418 /* Unlock route_node. */
420 route_unlock_node (rp
);
422 /* Free RIPng routing information. */
423 ripng_info_free (rinfo
);
428 /* Timeout RIPng routes. */
430 ripng_timeout (struct thread
*t
)
432 struct ripng_info
*rinfo
;
433 struct route_node
*rp
;
435 rinfo
= THREAD_ARG (t
);
436 rinfo
->t_timeout
= NULL
;
438 /* Get route_node pointer. */
441 /* - The garbage-collection timer is set for 120 seconds. */
442 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
, ripng_garbage_collect
,
443 ripng
->garbage_time
);
445 /* Delete this route from the kernel. */
446 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
448 /* - The metric for the route is set to 16 (infinity). This causes
449 the route to be removed from service. */
450 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
451 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
453 /* Aggregate count decrement. */
454 ripng_aggregate_decrement (rp
, rinfo
);
456 /* - The route change flag is to indicate that this entry has been
458 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
460 /* - The output process is signalled to trigger a response. */
461 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
467 ripng_timeout_update (struct ripng_info
*rinfo
)
469 if (rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
471 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
472 RIPNG_TIMER_ON (rinfo
->t_timeout
, ripng_timeout
, ripng
->timeout_time
);
477 ripng_incoming_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
479 struct distribute
*dist
;
480 struct access_list
*alist
;
481 struct prefix_list
*plist
;
483 /* Input distribute-list filtering. */
484 if (ri
->list
[RIPNG_FILTER_IN
])
486 if (access_list_apply (ri
->list
[RIPNG_FILTER_IN
],
487 (struct prefix
*) p
) == FILTER_DENY
)
489 if (IS_RIPNG_DEBUG_PACKET
)
490 zlog_debug ("%s/%d filtered by distribute in",
491 inet6_ntoa (p
->prefix
), p
->prefixlen
);
495 if (ri
->prefix
[RIPNG_FILTER_IN
])
497 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_IN
],
498 (struct prefix
*) p
) == PREFIX_DENY
)
500 if (IS_RIPNG_DEBUG_PACKET
)
501 zlog_debug ("%s/%d filtered by prefix-list in",
502 inet6_ntoa (p
->prefix
), p
->prefixlen
);
507 /* All interface filter check. */
508 dist
= distribute_lookup (NULL
);
511 if (dist
->list
[DISTRIBUTE_IN
])
513 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
517 if (access_list_apply (alist
,
518 (struct prefix
*) p
) == FILTER_DENY
)
520 if (IS_RIPNG_DEBUG_PACKET
)
521 zlog_debug ("%s/%d filtered by distribute in",
522 inet6_ntoa (p
->prefix
), p
->prefixlen
);
527 if (dist
->prefix
[DISTRIBUTE_IN
])
529 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
533 if (prefix_list_apply (plist
,
534 (struct prefix
*) p
) == PREFIX_DENY
)
536 if (IS_RIPNG_DEBUG_PACKET
)
537 zlog_debug ("%s/%d filtered by prefix-list in",
538 inet6_ntoa (p
->prefix
), p
->prefixlen
);
548 ripng_outgoing_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
550 struct distribute
*dist
;
551 struct access_list
*alist
;
552 struct prefix_list
*plist
;
554 if (ri
->list
[RIPNG_FILTER_OUT
])
556 if (access_list_apply (ri
->list
[RIPNG_FILTER_OUT
],
557 (struct prefix
*) p
) == FILTER_DENY
)
559 if (IS_RIPNG_DEBUG_PACKET
)
560 zlog_debug ("%s/%d is filtered by distribute out",
561 inet6_ntoa (p
->prefix
), p
->prefixlen
);
565 if (ri
->prefix
[RIPNG_FILTER_OUT
])
567 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_OUT
],
568 (struct prefix
*) p
) == PREFIX_DENY
)
570 if (IS_RIPNG_DEBUG_PACKET
)
571 zlog_debug ("%s/%d is filtered by prefix-list out",
572 inet6_ntoa (p
->prefix
), p
->prefixlen
);
577 /* All interface filter check. */
578 dist
= distribute_lookup (NULL
);
581 if (dist
->list
[DISTRIBUTE_OUT
])
583 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
587 if (access_list_apply (alist
,
588 (struct prefix
*) p
) == FILTER_DENY
)
590 if (IS_RIPNG_DEBUG_PACKET
)
591 zlog_debug ("%s/%d filtered by distribute out",
592 inet6_ntoa (p
->prefix
), p
->prefixlen
);
597 if (dist
->prefix
[DISTRIBUTE_OUT
])
599 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
603 if (prefix_list_apply (plist
,
604 (struct prefix
*) p
) == PREFIX_DENY
)
606 if (IS_RIPNG_DEBUG_PACKET
)
607 zlog_debug ("%s/%d filtered by prefix-list out",
608 inet6_ntoa (p
->prefix
), p
->prefixlen
);
617 /* Process RIPng route according to RFC2080. */
619 ripng_route_process (struct rte
*rte
, struct sockaddr_in6
*from
,
620 struct ripng_nexthop
*ripng_nexthop
,
621 struct interface
*ifp
)
624 struct prefix_ipv6 p
;
625 struct route_node
*rp
;
626 struct ripng_info
*rinfo
;
627 struct ripng_interface
*ri
;
628 struct in6_addr
*nexthop
;
632 /* Make prefix structure. */
633 memset (&p
, 0, sizeof (struct prefix_ipv6
));
635 /* p.prefix = rte->addr; */
636 IPV6_ADDR_COPY (&p
.prefix
, &rte
->addr
);
637 p
.prefixlen
= rte
->prefixlen
;
639 /* Make sure mask is applied. */
640 /* XXX We have to check the prefix is valid or not before call
642 apply_mask_ipv6 (&p
);
644 /* Apply input filters. */
647 ret
= ripng_incoming_filter (&p
, ri
);
652 if (ri
->routemap
[RIPNG_FILTER_IN
])
655 struct ripng_info newinfo
;
657 memset (&newinfo
, 0, sizeof (struct ripng_info
));
658 newinfo
.type
= ZEBRA_ROUTE_RIPNG
;
659 newinfo
.sub_type
= RIPNG_ROUTE_RTE
;
660 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
661 newinfo
.nexthop
= ripng_nexthop
->address
;
663 newinfo
.nexthop
= from
->sin6_addr
;
664 newinfo
.from
= from
->sin6_addr
;
665 newinfo
.ifindex
= ifp
->ifindex
;
666 newinfo
.metric
= rte
->metric
;
667 newinfo
.metric_out
= rte
->metric
; /* XXX */
668 newinfo
.tag
= ntohs(rte
->tag
); /* XXX */
670 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_IN
],
671 (struct prefix
*)&p
, RMAP_RIPNG
, &newinfo
);
673 if (ret
== RMAP_DENYMATCH
)
675 if (IS_RIPNG_DEBUG_PACKET
)
676 zlog_debug ("RIPng %s/%d is filtered by route-map in",
677 inet6_ntoa (p
.prefix
), p
.prefixlen
);
681 /* Get back the object */
682 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
) {
683 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &ripng_nexthop
->address
) ) {
684 /* the nexthop get changed by the routemap */
685 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
))
686 ripng_nexthop
->address
= newinfo
.nexthop
;
688 ripng_nexthop
->address
= in6addr_any
;
691 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &from
->sin6_addr
) ) {
692 /* the nexthop get changed by the routemap */
693 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
)) {
694 ripng_nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
695 ripng_nexthop
->address
= newinfo
.nexthop
;
699 rte
->tag
= htons(newinfo
.tag_out
); /* XXX */
700 rte
->metric
= newinfo
.metric_out
; /* XXX: the routemap uses the metric_out field */
703 /* Once the entry has been validated, update the metric by
704 * adding the cost of the network on wich the message
705 * arrived. If the result is greater than infinity, use infinity
706 * (RFC2453 Sec. 3.9.2)
709 /* Zebra ripngd can handle offset-list in. */
710 ret
= ripng_offset_list_apply_in (&p
, ifp
, &rte
->metric
);
712 /* If offset-list does not modify the metric use interface's
715 rte
->metric
+= ifp
->metric
;
717 if (rte
->metric
> RIPNG_METRIC_INFINITY
)
718 rte
->metric
= RIPNG_METRIC_INFINITY
;
720 /* Set nexthop pointer. */
721 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
722 nexthop
= &ripng_nexthop
->address
;
724 nexthop
= &from
->sin6_addr
;
726 /* Lookup RIPng routing table. */
727 rp
= route_node_get (ripng
->table
, (struct prefix
*) &p
);
733 /* Redistributed route check. */
734 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
735 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
738 /* Local static route. */
739 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
740 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
741 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
))
742 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
746 if (rp
->info
== NULL
)
748 /* Now, check to see whether there is already an explicit route
749 for the destination prefix. If there is no such route, add
750 this route to the routing table, unless the metric is
751 infinity (there is no point in adding a route which
753 if (rte
->metric
!= RIPNG_METRIC_INFINITY
)
755 rinfo
= ripng_info_new ();
757 /* - Setting the destination prefix and length to those in
762 /* - Setting the metric to the newly calculated metric (as
764 rinfo
->metric
= rte
->metric
;
765 rinfo
->tag
= ntohs (rte
->tag
);
767 /* - Set the next hop address to be the address of the router
768 from which the datagram came or the next hop address
769 specified by a next hop RTE. */
770 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
771 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
772 rinfo
->ifindex
= ifp
->ifindex
;
774 /* - Initialize the timeout for the route. If the
775 garbage-collection timer is running for this route, stop it. */
776 ripng_timeout_update (rinfo
);
778 /* - Set the route change flag. */
779 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
781 /* - Signal the output process to trigger an update (see section
783 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
785 /* Finally, route goes into the kernel. */
786 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
787 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
789 ripng_zebra_ipv6_add (&p
, &rinfo
->nexthop
, rinfo
->ifindex
,
791 rinfo
->flags
|= RIPNG_RTF_FIB
;
793 /* Aggregate check. */
794 ripng_aggregate_increment (rp
, rinfo
);
801 /* If there is an existing route, compare the next hop address
802 to the address of the router from which the datagram came.
803 If this datagram is from the same router as the existing
804 route, reinitialize the timeout. */
805 same
= (IN6_ARE_ADDR_EQUAL (&rinfo
->from
, &from
->sin6_addr
)
806 && (rinfo
->ifindex
== ifp
->ifindex
));
809 ripng_timeout_update (rinfo
);
811 /* Next, compare the metrics. If the datagram is from the same
812 router as the existing route, and the new metric is different
813 than the old one; or, if the new metric is lower than the old
814 one; do the following actions: */
815 if ((same
&& rinfo
->metric
!= rte
->metric
) ||
816 rte
->metric
< rinfo
->metric
)
818 /* - Adopt the route from the datagram. That is, put the
819 new metric in, and adjust the next hop address (if
821 oldmetric
= rinfo
->metric
;
822 rinfo
->metric
= rte
->metric
;
823 rinfo
->tag
= ntohs (rte
->tag
);
824 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
825 rinfo
->ifindex
= ifp
->ifindex
;
827 /* Should a new route to this network be established
828 while the garbage-collection timer is running, the
829 new route will replace the one that is about to be
830 deleted. In this case the garbage-collection timer
833 if (oldmetric
== RIPNG_METRIC_INFINITY
&&
834 rinfo
->metric
< RIPNG_METRIC_INFINITY
)
836 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
837 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
839 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
841 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
842 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
844 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
, rinfo
->metric
);
845 rinfo
->flags
|= RIPNG_RTF_FIB
;
847 /* The aggregation counter needs to be updated because
848 the prefixes, which are into the gc, have been
849 removed from the aggregator (see ripng_timout). */
850 ripng_aggregate_increment (rp
, rinfo
);
853 /* Update nexthop and/or metric value. */
854 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
856 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
857 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
, rinfo
->metric
);
858 rinfo
->flags
|= RIPNG_RTF_FIB
;
860 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
861 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
864 /* - Set the route change flag and signal the output process
865 to trigger an update. */
866 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
867 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
869 /* - If the new metric is infinity, start the deletion
870 process (described above); */
871 if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
873 /* If the new metric is infinity, the deletion process
874 begins for the route, which is no longer used for
875 routing packets. Note that the deletion process is
876 started only when the metric is first set to
877 infinity. If the metric was already infinity, then a
878 new deletion process is not started. */
879 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
881 /* - The garbage-collection timer is set for 120 seconds. */
882 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
883 ripng_garbage_collect
, ripng
->garbage_time
);
884 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
886 /* - The metric for the route is set to 16
887 (infinity). This causes the route to be removed
889 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
890 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
892 /* Aggregate count decrement. */
893 ripng_aggregate_decrement (rp
, rinfo
);
895 /* - The route change flag is to indicate that this
896 entry has been changed. */
897 /* - The output process is signalled to trigger a
899 ; /* Above processes are already done previously. */
904 /* otherwise, re-initialize the timeout. */
905 ripng_timeout_update (rinfo
);
908 /* Unlock tempolary lock of the route. */
909 route_unlock_node (rp
);
913 /* Add redistributed route to RIPng table. */
915 ripng_redistribute_add (int type
, int sub_type
, struct prefix_ipv6
*p
,
916 unsigned int ifindex
, struct in6_addr
*nexthop
)
918 struct route_node
*rp
;
919 struct ripng_info
*rinfo
;
921 /* Redistribute route */
922 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
924 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
926 #if defined (MUSICA) || defined (LINUX)
927 /* XXX As long as the RIPng redistribution is applied to all the connected
928 * routes, one needs to filter the ::/96 prefixes.
929 * However it could be a wanted case, it will be removed soon.
931 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
932 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
934 #endif /* MUSICA or LINUX */
936 rp
= route_node_get (ripng
->table
, (struct prefix
*) p
);
941 if (rinfo
->type
== ZEBRA_ROUTE_CONNECT
942 && rinfo
->sub_type
== RIPNG_ROUTE_INTERFACE
943 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
) {
944 route_unlock_node (rp
);
948 /* Manually configured RIPng route check.
949 * They have the precedence on all the other entries.
951 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
952 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
953 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
)) ) {
954 if (type
!= ZEBRA_ROUTE_RIPNG
|| ((sub_type
!= RIPNG_ROUTE_STATIC
) &&
955 (sub_type
!= RIPNG_ROUTE_DEFAULT
))) {
956 route_unlock_node (rp
);
961 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
962 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
964 /* Tells the other daemons about the deletion of
967 if (ripng_route_rte (rinfo
))
968 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
972 ripng_info_free (rinfo
);
974 route_unlock_node (rp
);
978 rinfo
= ripng_info_new ();
981 rinfo
->sub_type
= sub_type
;
982 rinfo
->ifindex
= ifindex
;
986 if (nexthop
&& IN6_IS_ADDR_LINKLOCAL(nexthop
))
987 rinfo
->nexthop
= *nexthop
;
989 rinfo
->flags
|= RIPNG_RTF_FIB
;
992 /* Aggregate check. */
993 ripng_aggregate_increment (rp
, rinfo
);
995 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
997 if (IS_RIPNG_DEBUG_EVENT
) {
999 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
1000 inet6_ntoa(p
->prefix
), p
->prefixlen
,
1001 ifindex2ifname(ifindex
));
1003 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1004 inet6_ntoa(p
->prefix
), p
->prefixlen
, inet6_ntoa(*nexthop
),
1005 ifindex2ifname(ifindex
));
1008 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1011 /* Delete redistributed route to RIPng table. */
1013 ripng_redistribute_delete (int type
, int sub_type
, struct prefix_ipv6
*p
,
1014 unsigned int ifindex
)
1016 struct route_node
*rp
;
1017 struct ripng_info
*rinfo
;
1019 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
1021 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
1023 #if defined (MUSICA) || defined (LINUX)
1024 /* XXX As long as the RIPng redistribution is applied to all the connected
1025 * routes, one needs to filter the ::/96 prefixes.
1026 * However it could be a wanted case, it will be removed soon.
1028 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
1029 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
1031 #endif /* MUSICA or LINUX */
1033 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) p
);
1040 && rinfo
->type
== type
1041 && rinfo
->sub_type
== sub_type
1042 && rinfo
->ifindex
== ifindex
)
1044 /* Perform poisoned reverse. */
1045 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1046 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1047 ripng_garbage_collect
, ripng
->garbage_time
);
1048 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1050 /* Aggregate count decrement. */
1051 ripng_aggregate_decrement (rp
, rinfo
);
1053 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1055 if (IS_RIPNG_DEBUG_EVENT
)
1056 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1057 inet6_ntoa(p
->prefix
), p
->prefixlen
,
1058 ifindex2ifname(ifindex
));
1060 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1065 /* Withdraw redistributed route. */
1067 ripng_redistribute_withdraw (int type
)
1069 struct route_node
*rp
;
1070 struct ripng_info
*rinfo
;
1075 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1076 if ((rinfo
= rp
->info
) != NULL
)
1078 if ((rinfo
->type
== type
)
1079 && (rinfo
->sub_type
!= RIPNG_ROUTE_INTERFACE
))
1081 /* Perform poisoned reverse. */
1082 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1083 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1084 ripng_garbage_collect
, ripng
->garbage_time
);
1085 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1087 /* Aggregate count decrement. */
1088 ripng_aggregate_decrement (rp
, rinfo
);
1090 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1092 if (IS_RIPNG_DEBUG_EVENT
) {
1093 struct prefix_ipv6
*p
= (struct prefix_ipv6
*) &rp
->p
;
1095 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
1096 inet6_ntoa(p
->prefix
), p
->prefixlen
,
1097 ifindex2ifname(rinfo
->ifindex
));
1100 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1105 /* RIP routing information. */
1107 ripng_response_process (struct ripng_packet
*packet
, int size
,
1108 struct sockaddr_in6
*from
, struct interface
*ifp
,
1113 struct ripng_nexthop nexthop
;
1115 /* RFC2080 2.4.2 Response Messages:
1116 The Response must be ignored if it is not from the RIPng port. */
1117 if (ntohs (from
->sin6_port
) != RIPNG_PORT_DEFAULT
)
1119 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
1120 ntohs (from
->sin6_port
), inet6_ntoa (from
->sin6_addr
));
1121 ripng_peer_bad_packet (from
);
1125 /* The datagram's IPv6 source address should be checked to see
1126 whether the datagram is from a valid neighbor; the source of the
1127 datagram must be a link-local address. */
1128 if (! IN6_IS_ADDR_LINKLOCAL(&from
->sin6_addr
))
1130 zlog_warn ("RIPng packet comes from non link local address %s",
1131 inet6_ntoa (from
->sin6_addr
));
1132 ripng_peer_bad_packet (from
);
1136 /* It is also worth checking to see whether the response is from one
1137 of the router's own addresses. Interfaces on broadcast networks
1138 may receive copies of their own multicasts immediately. If a
1139 router processes its own output as new input, confusion is likely,
1140 and such datagrams must be ignored. */
1141 if (ripng_lladdr_check (ifp
, &from
->sin6_addr
))
1143 zlog_warn ("RIPng packet comes from my own link local address %s",
1144 inet6_ntoa (from
->sin6_addr
));
1145 ripng_peer_bad_packet (from
);
1149 /* As an additional check, periodic advertisements must have their
1150 hop counts set to 255, and inbound, multicast packets sent from the
1151 RIPng port (i.e. periodic advertisement or triggered update
1152 packets) must be examined to ensure that the hop count is 255. */
1153 if (hoplimit
>= 0 && hoplimit
!= 255)
1155 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
1156 hoplimit
, inet6_ntoa (from
->sin6_addr
));
1157 ripng_peer_bad_packet (from
);
1161 /* Update RIPng peer. */
1162 ripng_peer_update (from
, packet
->version
);
1164 /* Reset nexthop. */
1165 memset (&nexthop
, 0, sizeof (struct ripng_nexthop
));
1166 nexthop
.flag
= RIPNG_NEXTHOP_UNSPEC
;
1168 /* Set RTE pointer. */
1171 for (lim
= ((caddr_t
) packet
) + size
; (caddr_t
) rte
< lim
; rte
++)
1173 /* First of all, we have to check this RTE is next hop RTE or
1174 not. Next hop RTE is completely different with normal RTE so
1175 we need special treatment. */
1176 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
1178 ripng_nexthop_rte (rte
, from
, &nexthop
);
1182 /* RTE information validation. */
1184 /* - is the destination prefix valid (e.g., not a multicast
1185 prefix and not a link-local address) A link-local address
1186 should never be present in an RTE. */
1187 if (IN6_IS_ADDR_MULTICAST (&rte
->addr
))
1189 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
1190 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1191 ripng_peer_bad_route (from
);
1194 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
1196 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
1197 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1198 ripng_peer_bad_route (from
);
1201 if (IN6_IS_ADDR_LOOPBACK (&rte
->addr
))
1203 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
1204 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1205 ripng_peer_bad_route (from
);
1209 /* - is the prefix length valid (i.e., between 0 and 128,
1211 if (rte
->prefixlen
> 128)
1213 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
1214 inet6_ntoa (rte
->addr
), rte
->prefixlen
,
1215 inet6_ntoa (from
->sin6_addr
), ifp
->name
);
1216 ripng_peer_bad_route (from
);
1220 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1221 if (! (rte
->metric
>= 1 && rte
->metric
<= 16))
1223 zlog_warn ("Invalid metric %d from %s%%%s", rte
->metric
,
1224 inet6_ntoa (from
->sin6_addr
), ifp
->name
);
1225 ripng_peer_bad_route (from
);
1229 /* Vincent: XXX Should we compute the direclty reachable nexthop
1230 * for our RIPng network ?
1233 /* Routing table updates. */
1234 ripng_route_process (rte
, from
, &nexthop
, ifp
);
1238 /* Response to request message. */
1240 ripng_request_process (struct ripng_packet
*packet
,int size
,
1241 struct sockaddr_in6
*from
, struct interface
*ifp
)
1245 struct prefix_ipv6 p
;
1246 struct route_node
*rp
;
1247 struct ripng_info
*rinfo
;
1248 struct ripng_interface
*ri
;
1250 /* Does not reponse to the requests on the loopback interfaces */
1251 if (if_is_loopback (ifp
))
1254 /* Check RIPng process is enabled on this interface. */
1259 /* When passive interface is specified, suppress responses */
1263 /* RIPng peer update. */
1264 ripng_peer_update (from
, packet
->version
);
1266 lim
= ((caddr_t
) packet
) + size
;
1269 /* The Request is processed entry by entry. If there are no
1270 entries, no response is given. */
1271 if (lim
== (caddr_t
) rte
)
1274 /* There is one special case. If there is exactly one entry in the
1275 request, and it has a destination prefix of zero, a prefix length
1276 of zero, and a metric of infinity (i.e., 16), then this is a
1277 request to send the entire routing table. In that case, a call
1278 is made to the output process to send the routing table to the
1279 requesting address/port. */
1280 if (lim
== ((caddr_t
) (rte
+ 1)) &&
1281 IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
) &&
1282 rte
->prefixlen
== 0 &&
1283 rte
->metric
== RIPNG_METRIC_INFINITY
)
1285 /* All route with split horizon */
1286 ripng_output_process (ifp
, from
, ripng_all_route
);
1290 /* Except for this special case, processing is quite simple.
1291 Examine the list of RTEs in the Request one by one. For each
1292 entry, look up the destination in the router's routing
1293 database and, if there is a route, put that route's metric in
1294 the metric field of the RTE. If there is no explicit route
1295 to the specified destination, put infinity in the metric
1296 field. Once all the entries have been filled in, change the
1297 command from Request to Response and send the datagram back
1298 to the requestor. */
1299 memset (&p
, 0, sizeof (struct prefix_ipv6
));
1300 p
.family
= AF_INET6
;
1302 for (; ((caddr_t
) rte
) < lim
; rte
++)
1304 p
.prefix
= rte
->addr
;
1305 p
.prefixlen
= rte
->prefixlen
;
1306 apply_mask_ipv6 (&p
);
1308 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) &p
);
1313 rte
->metric
= rinfo
->metric
;
1314 route_unlock_node (rp
);
1317 rte
->metric
= RIPNG_METRIC_INFINITY
;
1319 packet
->command
= RIPNG_RESPONSE
;
1321 ripng_send_packet ((caddr_t
) packet
, size
, from
, ifp
);
1325 /* First entry point of reading RIPng packet. */
1327 ripng_read (struct thread
*thread
)
1331 struct sockaddr_in6 from
;
1332 struct ripng_packet
*packet
;
1333 unsigned int ifindex
;
1334 struct interface
*ifp
;
1337 /* Check ripng is active and alive. */
1338 assert (ripng
!= NULL
);
1339 assert (ripng
->sock
>= 0);
1341 /* Fetch thread data and set read pointer to empty for event
1342 managing. `sock' sould be same as ripng->sock. */
1343 sock
= THREAD_FD (thread
);
1344 ripng
->t_read
= NULL
;
1346 /* Add myself to the next event. */
1347 ripng_event (RIPNG_READ
, sock
);
1349 /* Read RIPng packet. */
1350 len
= ripng_recv_packet (sock
, STREAM_DATA (ripng
->ibuf
),
1351 STREAM_SIZE (ripng
->ibuf
), &from
, &ifindex
,
1355 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno
));
1359 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1360 (4)) must be multiple size of one RTE size (20). */
1361 if (((len
- 4) % 20) != 0)
1363 zlog_warn ("RIPng invalid packet size %d from %s", len
,
1364 inet6_ntoa (from
.sin6_addr
));
1365 ripng_peer_bad_packet (&from
);
1369 packet
= (struct ripng_packet
*) STREAM_DATA (ripng
->ibuf
);
1370 ifp
= if_lookup_by_index (ifindex
);
1372 /* RIPng packet received. */
1373 if (IS_RIPNG_DEBUG_EVENT
)
1374 zlog_debug ("RIPng packet received from %s port %d on %s",
1375 inet6_ntoa (from
.sin6_addr
), ntohs (from
.sin6_port
),
1376 ifp
? ifp
->name
: "unknown");
1378 /* Logging before packet checking. */
1379 if (IS_RIPNG_DEBUG_RECV
)
1380 ripng_packet_dump (packet
, len
, "RECV");
1382 /* Packet comes from unknown interface. */
1385 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex
);
1389 /* Packet version mismatch checking. */
1390 if (packet
->version
!= ripng
->version
)
1392 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1393 packet
->version
, ripng
->version
);
1394 ripng_peer_bad_packet (&from
);
1398 /* Process RIPng packet. */
1399 switch (packet
->command
)
1402 ripng_request_process (packet
, len
, &from
, ifp
);
1404 case RIPNG_RESPONSE
:
1405 ripng_response_process (packet
, len
, &from
, ifp
, hoplimit
);
1408 zlog_warn ("Invalid RIPng command %d", packet
->command
);
1409 ripng_peer_bad_packet (&from
);
1415 /* Walk down the RIPng routing table then clear changed flag. */
1417 ripng_clear_changed_flag (void)
1419 struct route_node
*rp
;
1420 struct ripng_info
*rinfo
;
1422 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1423 if ((rinfo
= rp
->info
) != NULL
)
1424 if (rinfo
->flags
& RIPNG_RTF_CHANGED
)
1425 rinfo
->flags
&= ~RIPNG_RTF_CHANGED
;
1428 /* Regular update of RIPng route. Send all routing formation to RIPng
1429 enabled interface. */
1431 ripng_update (struct thread
*t
)
1433 struct listnode
*node
;
1434 struct interface
*ifp
;
1435 struct ripng_interface
*ri
;
1437 /* Clear update timer thread. */
1438 ripng
->t_update
= NULL
;
1440 /* Logging update event. */
1441 if (IS_RIPNG_DEBUG_EVENT
)
1442 zlog_debug ("RIPng update timer expired!");
1444 /* Supply routes to each interface. */
1445 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
1449 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1455 /* When passive interface is specified, suppress announce to the
1461 if (ri
->ri_send
== RIPNG_SEND_OFF
)
1463 if (IS_RIPNG_DEBUG_EVENT
)
1464 zlog (NULL
, LOG_DEBUG
,
1465 "[Event] RIPng send to if %d is suppressed by config",
1469 #endif /* RIPNG_ADVANCED */
1471 ripng_output_process (ifp
, NULL
, ripng_all_route
);
1474 /* Triggered updates may be suppressed if a regular update is due by
1475 the time the triggered update would be sent. */
1476 if (ripng
->t_triggered_interval
)
1478 thread_cancel (ripng
->t_triggered_interval
);
1479 ripng
->t_triggered_interval
= NULL
;
1483 /* Reset flush event. */
1484 ripng_event (RIPNG_UPDATE_EVENT
, 0);
1489 /* Triggered update interval timer. */
1491 ripng_triggered_interval (struct thread
*t
)
1493 ripng
->t_triggered_interval
= NULL
;
1498 ripng_triggered_update (t
);
1503 /* Execute triggered update. */
1505 ripng_triggered_update (struct thread
*t
)
1507 struct listnode
*node
;
1508 struct interface
*ifp
;
1509 struct ripng_interface
*ri
;
1512 ripng
->t_triggered_update
= NULL
;
1514 /* Cancel interval timer. */
1515 if (ripng
->t_triggered_interval
)
1517 thread_cancel (ripng
->t_triggered_interval
);
1518 ripng
->t_triggered_interval
= NULL
;
1522 /* Logging triggered update. */
1523 if (IS_RIPNG_DEBUG_EVENT
)
1524 zlog_debug ("RIPng triggered update!");
1526 /* Split Horizon processing is done when generating triggered
1527 updates as well as normal updates (see section 2.6). */
1528 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
1532 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1538 /* When passive interface is specified, suppress announce to the
1543 ripng_output_process (ifp
, NULL
, ripng_changed_route
);
1546 /* Once all of the triggered updates have been generated, the route
1547 change flags should be cleared. */
1548 ripng_clear_changed_flag ();
1550 /* After a triggered update is sent, a timer should be set for a
1551 random interval between 1 and 5 seconds. If other changes that
1552 would trigger updates occur before the timer expires, a single
1553 update is triggered when the timer expires. */
1554 interval
= (random () % 5) + 1;
1556 ripng
->t_triggered_interval
=
1557 thread_add_timer (master
, ripng_triggered_interval
, NULL
, interval
);
1562 /* Write routing table entry to the stream and return next index of
1563 the routing table entry in the stream. */
1565 ripng_write_rte (int num
, struct stream
*s
, struct prefix_ipv6
*p
,
1566 struct in6_addr
*nexthop
, u_int16_t tag
, u_char metric
)
1568 /* RIPng packet header. */
1571 stream_putc (s
, RIPNG_RESPONSE
);
1572 stream_putc (s
, RIPNG_V1
);
1576 /* Write routing table entry. */
1578 stream_write (s
, (u_char
*) &p
->prefix
, sizeof (struct in6_addr
));
1580 stream_write (s
, (u_char
*) nexthop
, sizeof (struct in6_addr
));
1581 stream_putw (s
, tag
);
1583 stream_putc (s
, p
->prefixlen
);
1586 stream_putc (s
, metric
);
1591 /* Send RESPONSE message to specified destination. */
1593 ripng_output_process (struct interface
*ifp
, struct sockaddr_in6
*to
,
1597 struct route_node
*rp
;
1598 struct ripng_info
*rinfo
;
1599 struct ripng_interface
*ri
;
1600 struct ripng_aggregate
*aggregate
;
1601 struct prefix_ipv6
*p
;
1602 struct list
* ripng_rte_list
;
1604 if (IS_RIPNG_DEBUG_EVENT
) {
1606 zlog_debug ("RIPng update routes to neighbor %s",
1607 inet6_ntoa(to
->sin6_addr
));
1609 zlog_debug ("RIPng update routes on interface %s", ifp
->name
);
1612 /* Get RIPng interface. */
1615 ripng_rte_list
= ripng_rte_new();
1617 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1619 if ((rinfo
= rp
->info
) != NULL
&& rinfo
->suppress
== 0)
1621 /* If no route-map are applied, the RTE will be these following
1624 p
= (struct prefix_ipv6
*) &rp
->p
;
1625 rinfo
->metric_out
= rinfo
->metric
;
1626 rinfo
->tag_out
= rinfo
->tag
;
1627 memset(&rinfo
->nexthop_out
, 0, sizeof(rinfo
->nexthop_out
));
1628 /* In order to avoid some local loops,
1629 * if the RIPng route has a nexthop via this interface, keep the nexthop,
1630 * otherwise set it to 0. The nexthop should not be propagated
1631 * beyond the local broadcast/multicast area in order
1632 * to avoid an IGP multi-level recursive look-up.
1634 if (rinfo
->ifindex
== ifp
->ifindex
)
1635 rinfo
->nexthop_out
= rinfo
->nexthop
;
1637 /* Apply output filters. */
1638 ret
= ripng_outgoing_filter (p
, ri
);
1642 /* Changed route only output. */
1643 if (route_type
== ripng_changed_route
&&
1644 (! (rinfo
->flags
& RIPNG_RTF_CHANGED
)))
1647 /* Split horizon. */
1648 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON
)
1650 /* We perform split horizon for RIPng routes. */
1651 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1652 rinfo
->ifindex
== ifp
->ifindex
)
1656 /* Preparation for route-map. */
1657 rinfo
->metric_set
= 0;
1660 * and tag_out are already initialized.
1663 /* Interface route-map */
1664 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1668 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1669 (struct prefix
*) p
, RMAP_RIPNG
,
1672 if (ret
== RMAP_DENYMATCH
)
1674 if (IS_RIPNG_DEBUG_PACKET
)
1675 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1676 inet6_ntoa (p
->prefix
), p
->prefixlen
);
1682 /* Redistribute route-map. */
1683 if (ripng
->route_map
[rinfo
->type
].name
)
1687 ret
= route_map_apply (ripng
->route_map
[rinfo
->type
].map
,
1688 (struct prefix
*) p
, RMAP_RIPNG
,
1691 if (ret
== RMAP_DENYMATCH
)
1693 if (IS_RIPNG_DEBUG_PACKET
)
1694 zlog_debug ("RIPng %s/%d is filtered by route-map",
1695 inet6_ntoa (p
->prefix
), p
->prefixlen
);
1700 /* When the route-map does not set metric. */
1701 if (! rinfo
->metric_set
)
1703 /* If the redistribute metric is set. */
1704 if (ripng
->route_map
[rinfo
->type
].metric_config
1705 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1707 rinfo
->metric_out
= ripng
->route_map
[rinfo
->type
].metric
;
1711 /* If the route is not connected or localy generated
1712 one, use default-metric value */
1713 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
1714 && rinfo
->type
!= ZEBRA_ROUTE_CONNECT
1715 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1716 rinfo
->metric_out
= ripng
->default_metric
;
1720 /* Apply offset-list */
1721 if (rinfo
->metric_out
!= RIPNG_METRIC_INFINITY
)
1722 ripng_offset_list_apply_out (p
, ifp
, &rinfo
->metric_out
);
1724 if (rinfo
->metric_out
> RIPNG_METRIC_INFINITY
)
1725 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1727 /* Perform split-horizon with poisoned reverse
1730 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON_POISONED_REVERSE
) {
1731 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1732 rinfo
->ifindex
== ifp
->ifindex
)
1733 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1736 /* Add RTE to the list */
1737 ripng_rte_add(ripng_rte_list
, p
, rinfo
, NULL
);
1740 /* Process the aggregated RTE entry */
1741 if ((aggregate
= rp
->aggregate
) != NULL
&&
1742 aggregate
->count
> 0 &&
1743 aggregate
->suppress
== 0)
1745 /* If no route-map are applied, the RTE will be these following
1748 p
= (struct prefix_ipv6
*) &rp
->p
;
1749 aggregate
->metric_set
= 0;
1750 aggregate
->metric_out
= aggregate
->metric
;
1751 aggregate
->tag_out
= aggregate
->tag
;
1752 memset(&aggregate
->nexthop_out
, 0, sizeof(aggregate
->nexthop_out
));
1754 /* Apply output filters.*/
1755 ret
= ripng_outgoing_filter (p
, ri
);
1759 /* Interface route-map */
1760 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1763 struct ripng_info newinfo
;
1765 /* let's cast the aggregate structure to ripng_info */
1766 memset (&newinfo
, 0, sizeof (struct ripng_info
));
1767 /* the nexthop is :: */
1768 newinfo
.metric
= aggregate
->metric
;
1769 newinfo
.metric_out
= aggregate
->metric_out
;
1770 newinfo
.tag
= aggregate
->tag
;
1771 newinfo
.tag_out
= aggregate
->tag_out
;
1773 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1774 (struct prefix
*) p
, RMAP_RIPNG
,
1777 if (ret
== RMAP_DENYMATCH
)
1779 if (IS_RIPNG_DEBUG_PACKET
)
1780 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1781 inet6_ntoa (p
->prefix
), p
->prefixlen
);
1785 aggregate
->metric_out
= newinfo
.metric_out
;
1786 aggregate
->tag_out
= newinfo
.tag_out
;
1787 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop_out
))
1788 aggregate
->nexthop_out
= newinfo
.nexthop_out
;
1791 /* There is no redistribute routemap for the aggregated RTE */
1793 /* Changed route only output. */
1794 /* XXX, vincent, in order to increase time convergence,
1795 * it should be announced if a child has changed.
1797 if (route_type
== ripng_changed_route
)
1800 /* Apply offset-list */
1801 if (aggregate
->metric_out
!= RIPNG_METRIC_INFINITY
)
1802 ripng_offset_list_apply_out (p
, ifp
, &aggregate
->metric_out
);
1804 if (aggregate
->metric_out
> RIPNG_METRIC_INFINITY
)
1805 aggregate
->metric_out
= RIPNG_METRIC_INFINITY
;
1807 /* Add RTE to the list */
1808 ripng_rte_add(ripng_rte_list
, p
, NULL
, aggregate
);
1813 /* Flush the list */
1814 ripng_rte_send(ripng_rte_list
, ifp
, to
);
1815 ripng_rte_free(ripng_rte_list
);
1818 /* Create new RIPng instance and set it to global variable. */
1822 /* ripng should be NULL. */
1823 assert (ripng
== NULL
);
1825 /* Allocaste RIPng instance. */
1826 ripng
= XCALLOC (MTYPE_RIPNG
, sizeof (struct ripng
));
1828 /* Default version and timer values. */
1829 ripng
->version
= RIPNG_V1
;
1830 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
1831 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
1832 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
1833 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
1836 ripng
->ibuf
= stream_new (RIPNG_MAX_PACKET_SIZE
* 5);
1837 ripng
->obuf
= stream_new (RIPNG_MAX_PACKET_SIZE
);
1839 /* Initialize RIPng routig table. */
1840 ripng
->table
= route_table_init ();
1841 ripng
->route
= route_table_init ();
1842 ripng
->aggregate
= route_table_init ();
1845 ripng
->sock
= ripng_make_socket ();
1846 if (ripng
->sock
< 0)
1850 ripng_event (RIPNG_READ
, ripng
->sock
);
1851 ripng_event (RIPNG_UPDATE_EVENT
, 1);
1856 /* Send RIPng request to the interface. */
1858 ripng_request (struct interface
*ifp
)
1861 struct ripng_packet ripng_packet
;
1863 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
1864 if (if_is_loopback(ifp
))
1867 /* If interface is down, don't send RIP packet. */
1868 if (! if_is_up (ifp
))
1871 if (IS_RIPNG_DEBUG_EVENT
)
1872 zlog_debug ("RIPng send request to %s", ifp
->name
);
1874 memset (&ripng_packet
, 0, sizeof (ripng_packet
));
1875 ripng_packet
.command
= RIPNG_REQUEST
;
1876 ripng_packet
.version
= RIPNG_V1
;
1877 rte
= ripng_packet
.rte
;
1878 rte
->metric
= RIPNG_METRIC_INFINITY
;
1880 return ripng_send_packet ((caddr_t
) &ripng_packet
, sizeof (ripng_packet
),
1886 ripng_update_jitter (int time
)
1888 return ((rand () % (time
+ 1)) - (time
/ 2));
1892 ripng_event (enum ripng_event event
, int sock
)
1900 ripng
->t_read
= thread_add_read (master
, ripng_read
, NULL
, sock
);
1902 case RIPNG_UPDATE_EVENT
:
1903 if (ripng
->t_update
)
1905 thread_cancel (ripng
->t_update
);
1906 ripng
->t_update
= NULL
;
1908 /* Update timer jitter. */
1909 jitter
= ripng_update_jitter (ripng
->update_time
);
1912 thread_add_timer (master
, ripng_update
, NULL
,
1913 sock
? 2 : ripng
->update_time
+ jitter
);
1915 case RIPNG_TRIGGERED_UPDATE
:
1916 if (ripng
->t_triggered_interval
)
1918 else if (! ripng
->t_triggered_update
)
1919 ripng
->t_triggered_update
=
1920 thread_add_event (master
, ripng_triggered_update
, NULL
, 0);
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
;
2004 /* Header of display. */
2005 vty_out (vty
, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2007 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2008 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2009 " Network Next Hop Via Metric Tag Time%s",
2010 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2011 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
2013 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2015 if ((aggregate
= rp
->aggregate
) != NULL
)
2017 p
= (struct prefix_ipv6
*) &rp
->p
;
2020 len
= vty_out (vty
, "R(a) %d/%d %s/%d ",
2021 aggregate
->count
, aggregate
->suppress
,
2022 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2024 len
= vty_out (vty
, "R(a) %s/%d ",
2025 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2027 vty_out (vty
, "%s", VTY_NEWLINE
);
2028 vty_out (vty
, "%*s", 18, " ");
2030 vty_out (vty
, "%*s", 28, " ");
2031 vty_out (vty
, "self %2d %3d%s", aggregate
->metric
,
2036 if ((rinfo
= rp
->info
) != NULL
)
2038 p
= (struct prefix_ipv6
*) &rp
->p
;
2041 len
= vty_out (vty
, "%c(%s) 0/%d %s/%d ",
2042 zebra_route_char(rinfo
->type
),
2043 ripng_route_subtype_print(rinfo
),
2045 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2047 len
= vty_out (vty
, "%c(%s) %s/%d ",
2048 zebra_route_char(rinfo
->type
),
2049 ripng_route_subtype_print(rinfo
),
2050 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2052 vty_out (vty
, "%s", VTY_NEWLINE
);
2053 vty_out (vty
, "%*s", 18, " ");
2054 len
= vty_out (vty
, "%s", inet6_ntoa (rinfo
->nexthop
));
2058 len
= vty_out (vty
, "%*s", len
, " ");
2061 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2062 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2064 len
= vty_out (vty
, "%s", ifindex2ifname(rinfo
->ifindex
));
2065 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2067 len
= vty_out (vty
, "kill");
2069 len
= vty_out (vty
, "self");
2073 vty_out (vty
, "%*s", len
, " ");
2075 vty_out (vty
, " %2d %3d ",
2076 rinfo
->metric
, rinfo
->tag
);
2079 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2080 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2082 /* RTE from remote RIP routers */
2083 ripng_vty_out_uptime (vty
, rinfo
);
2084 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2086 /* poisonous reversed routes (gc) */
2087 ripng_vty_out_uptime (vty
, rinfo
);
2090 vty_out (vty
, "%s", VTY_NEWLINE
);
2097 DEFUN (show_ipv6_ripng_status
,
2098 show_ipv6_ripng_status_cmd
,
2099 "show ipv6 ripng status",
2102 "Show RIPng routes\n"
2103 "IPv6 routing protocol process parameters and statistics\n")
2105 struct listnode
*node
;
2106 struct interface
*ifp
;
2111 vty_out (vty
, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE
);
2112 vty_out (vty
, " Sending updates every %ld seconds with +/-50%%,",
2113 ripng
->update_time
);
2114 vty_out (vty
, " next due in %lu seconds%s",
2115 thread_timer_remain_second (ripng
->t_update
),
2117 vty_out (vty
, " Timeout after %ld seconds,", ripng
->timeout_time
);
2118 vty_out (vty
, " garbage collect after %ld seconds%s", ripng
->garbage_time
,
2121 /* Filtering status show. */
2122 config_show_distribute (vty
);
2124 /* Default metric information. */
2125 vty_out (vty
, " Default redistribution metric is %d%s",
2126 ripng
->default_metric
, VTY_NEWLINE
);
2128 /* Redistribute information. */
2129 vty_out (vty
, " Redistributing:");
2130 ripng_redistribute_write (vty
, 0);
2131 vty_out (vty
, "%s", VTY_NEWLINE
);
2133 vty_out (vty
, " Default version control: send version %d,", ripng
->version
);
2134 vty_out (vty
, " receive version %d %s", ripng
->version
,
2137 vty_out (vty
, " Interface Send Recv%s", VTY_NEWLINE
);
2139 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
2141 struct ripng_interface
*ri
;
2145 if (ri
->enable_network
|| ri
->enable_interface
)
2148 vty_out (vty
, " %-17s%-3d %-3d%s", ifp
->name
,
2155 vty_out (vty
, " Routing for Networks:%s", VTY_NEWLINE
);
2156 ripng_network_write (vty
, 0);
2158 vty_out (vty
, " Routing Information Sources:%s", VTY_NEWLINE
);
2159 vty_out (vty
, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE
);
2160 ripng_peer_display (vty
);
2165 DEFUN (router_ripng
,
2168 "Enable a routing process\n"
2169 "Make RIPng instance command\n")
2173 vty
->node
= RIPNG_NODE
;
2177 ret
= ripng_create ();
2179 /* Notice to user we couldn't create RIPng. */
2182 zlog_warn ("can't create RIPng");
2190 DEFUN (no_router_ripng
,
2191 no_router_ripng_cmd
,
2194 "Enable a routing process\n"
2195 "Make RIPng instance command\n")
2205 "Static route setup\n"
2206 "Set static RIPng route announcement\n")
2209 struct prefix_ipv6 p
;
2210 struct route_node
*rp
;
2212 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2215 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2218 apply_mask_ipv6 (&p
);
2220 rp
= route_node_get (ripng
->route
, (struct prefix
*) &p
);
2223 vty_out (vty
, "There is already same static route.%s", VTY_NEWLINE
);
2224 route_unlock_node (rp
);
2227 rp
->info
= (void *)1;
2229 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0, NULL
);
2234 DEFUN (no_ripng_route
,
2236 "no route IPV6ADDR",
2238 "Static route setup\n"
2239 "Delete static RIPng route announcement\n")
2242 struct prefix_ipv6 p
;
2243 struct route_node
*rp
;
2245 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2248 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2251 apply_mask_ipv6 (&p
);
2253 rp
= route_node_lookup (ripng
->route
, (struct prefix
*) &p
);
2256 vty_out (vty
, "Can't find static route.%s", VTY_NEWLINE
);
2260 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0);
2261 route_unlock_node (rp
);
2264 route_unlock_node (rp
);
2269 DEFUN (ripng_aggregate_address
,
2270 ripng_aggregate_address_cmd
,
2271 "aggregate-address X:X::X:X/M",
2272 "Set aggregate RIPng route announcement\n"
2273 "Aggregate network\n")
2277 struct route_node
*node
;
2279 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2282 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2286 /* Check aggregate alredy exist or not. */
2287 node
= route_node_get (ripng
->aggregate
, &p
);
2290 vty_out (vty
, "There is already same aggregate route.%s", VTY_NEWLINE
);
2291 route_unlock_node (node
);
2294 node
->info
= (void *)1;
2296 ripng_aggregate_add (&p
);
2301 DEFUN (no_ripng_aggregate_address
,
2302 no_ripng_aggregate_address_cmd
,
2303 "no aggregate-address X:X::X:X/M",
2305 "Delete aggregate RIPng route announcement\n"
2306 "Aggregate network")
2310 struct route_node
*rn
;
2312 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &p
);
2315 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2319 rn
= route_node_lookup (ripng
->aggregate
, &p
);
2322 vty_out (vty
, "Can't find aggregate route.%s", VTY_NEWLINE
);
2325 route_unlock_node (rn
);
2327 route_unlock_node (rn
);
2329 ripng_aggregate_delete (&p
);
2334 DEFUN (ripng_default_metric
,
2335 ripng_default_metric_cmd
,
2336 "default-metric <1-16>",
2337 "Set a metric of redistribute routes\n"
2342 ripng
->default_metric
= atoi (argv
[0]);
2347 DEFUN (no_ripng_default_metric
,
2348 no_ripng_default_metric_cmd
,
2349 "no default-metric",
2351 "Set a metric of redistribute routes\n"
2356 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
2361 ALIAS (no_ripng_default_metric
,
2362 no_ripng_default_metric_val_cmd
,
2363 "no default-metric <1-16>",
2365 "Set a metric of redistribute routes\n"
2369 /* RIPng update timer setup. */
2370 DEFUN (ripng_update_timer
,
2371 ripng_update_timer_cmd
,
2372 "update-timer SECOND",
2373 "Set RIPng update timer in seconds\n"
2376 unsigned long update
;
2377 char *endptr
= NULL
;
2379 update
= strtoul (argv
[0], &endptr
, 10);
2380 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2382 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2386 ripng
->update_time
= update
;
2388 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2392 DEFUN (no_ripng_update_timer
,
2393 no_ripng_update_timer_cmd
,
2394 "no update-timer SECOND",
2396 "Unset RIPng update timer in seconds\n"
2399 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2400 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2404 /* RIPng timeout timer setup. */
2405 DEFUN (ripng_timeout_timer
,
2406 ripng_timeout_timer_cmd
,
2407 "timeout-timer SECOND",
2408 "Set RIPng timeout timer in seconds\n"
2411 unsigned long timeout
;
2412 char *endptr
= NULL
;
2414 timeout
= strtoul (argv
[0], &endptr
, 10);
2415 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2417 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2421 ripng
->timeout_time
= timeout
;
2426 DEFUN (no_ripng_timeout_timer
,
2427 no_ripng_timeout_timer_cmd
,
2428 "no timeout-timer SECOND",
2430 "Unset RIPng timeout timer in seconds\n"
2433 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2437 /* RIPng garbage timer setup. */
2438 DEFUN (ripng_garbage_timer
,
2439 ripng_garbage_timer_cmd
,
2440 "garbage-timer SECOND",
2441 "Set RIPng garbage timer in seconds\n"
2444 unsigned long garbage
;
2445 char *endptr
= NULL
;
2447 garbage
= strtoul (argv
[0], &endptr
, 10);
2448 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2450 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2454 ripng
->garbage_time
= garbage
;
2459 DEFUN (no_ripng_garbage_timer
,
2460 no_ripng_garbage_timer_cmd
,
2461 "no garbage-timer SECOND",
2463 "Unset RIPng garbage timer in seconds\n"
2466 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2471 DEFUN (ripng_timers
,
2473 "timers basic <0-65535> <0-65535> <0-65535>",
2474 "RIPng timers setup\n"
2476 "Routing table update timer value in second. Default is 30.\n"
2477 "Routing information timeout timer. Default is 180.\n"
2478 "Garbage collection timer. Default is 120.\n")
2480 unsigned long update
;
2481 unsigned long timeout
;
2482 unsigned long garbage
;
2483 char *endptr
= NULL
;
2485 update
= strtoul (argv
[0], &endptr
, 10);
2486 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2488 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2492 timeout
= strtoul (argv
[1], &endptr
, 10);
2493 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2495 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2499 garbage
= strtoul (argv
[2], &endptr
, 10);
2500 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2502 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2506 /* Set each timer value. */
2507 ripng
->update_time
= update
;
2508 ripng
->timeout_time
= timeout
;
2509 ripng
->garbage_time
= garbage
;
2511 /* Reset update timer thread. */
2512 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2517 DEFUN (no_ripng_timers
,
2518 no_ripng_timers_cmd
,
2521 "RIPng timers setup\n"
2524 /* Set each timer value to the default. */
2525 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2526 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2527 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2529 /* Reset update timer thread. */
2530 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2535 ALIAS (no_ripng_timers
,
2536 no_ripng_timers_val_cmd
,
2537 "no timers basic <0-65535> <0-65535> <0-65535>",
2539 "RIPng timers setup\n"
2541 "Routing table update timer value in second. Default is 30.\n"
2542 "Routing information timeout timer. Default is 180.\n"
2543 "Garbage collection timer. Default is 120.\n")
2545 DEFUN (show_ipv6_protocols
, show_ipv6_protocols_cmd
,
2546 "show ipv6 protocols",
2549 "Routing protocol information")
2554 vty_out (vty
, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE
);
2556 vty_out (vty
, "Sending updates every %ld seconds, next due in %d seconds%s",
2557 ripng
->update_time
, 0,
2560 vty_out (vty
, "Timerout after %ld seconds, garbage correct %ld%s",
2561 ripng
->timeout_time
,
2562 ripng
->garbage_time
,
2565 vty_out (vty
, "Outgoing update filter list for all interfaces is not set");
2566 vty_out (vty
, "Incoming update filter list for all interfaces is not set");
2571 /* Please be carefull to use this command. */
2572 DEFUN (ripng_default_information_originate
,
2573 ripng_default_information_originate_cmd
,
2574 "default-information originate",
2575 "Default route information\n"
2576 "Distribute default route\n")
2578 struct prefix_ipv6 p
;
2580 if (! ripng
->default_information
) {
2581 ripng
->default_information
= 1;
2583 str2prefix_ipv6 ("::/0", &p
);
2584 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0, NULL
);
2590 DEFUN (no_ripng_default_information_originate
,
2591 no_ripng_default_information_originate_cmd
,
2592 "no default-information originate",
2594 "Default route information\n"
2595 "Distribute default route\n")
2597 struct prefix_ipv6 p
;
2599 if (ripng
->default_information
) {
2600 ripng
->default_information
= 0;
2602 str2prefix_ipv6 ("::/0", &p
);
2603 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0);
2609 /* RIPng configuration write function. */
2611 ripng_config_write (struct vty
*vty
)
2613 int ripng_network_write (struct vty
*, int);
2614 void ripng_redistribute_write (struct vty
*, int);
2616 struct route_node
*rp
;
2622 vty_out (vty
, "router ripng%s", VTY_NEWLINE
);
2624 if (ripng
->default_information
)
2625 vty_out (vty
, " default-information originate%s", VTY_NEWLINE
);
2627 ripng_network_write (vty
, 1);
2629 /* RIPng default metric configuration */
2630 if (ripng
->default_metric
!= RIPNG_DEFAULT_METRIC_DEFAULT
)
2631 vty_out (vty
, " default-metric %d%s",
2632 ripng
->default_metric
, VTY_NEWLINE
);
2634 ripng_redistribute_write (vty
, 1);
2636 /* RIP offset-list configuration. */
2637 config_write_ripng_offset_list (vty
);
2639 /* RIPng aggregate routes. */
2640 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2641 if (rp
->info
!= NULL
)
2642 vty_out (vty
, " aggregate-address %s/%d%s",
2643 inet6_ntoa (rp
->p
.u
.prefix6
),
2648 /* RIPng static routes. */
2649 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2650 if (rp
->info
!= NULL
)
2651 vty_out (vty
, " route %s/%d%s", inet6_ntoa (rp
->p
.u
.prefix6
),
2655 /* RIPng timers configuration. */
2656 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
||
2657 ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
||
2658 ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2660 vty_out (vty
, " timers basic %ld %ld %ld%s",
2662 ripng
->timeout_time
,
2663 ripng
->garbage_time
,
2667 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
)
2668 vty_out (vty
, " update-timer %d%s", ripng
->update_time
,
2670 if (ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
)
2671 vty_out (vty
, " timeout-timer %d%s", ripng
->timeout_time
,
2673 if (ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2674 vty_out (vty
, " garbage-timer %d%s", ripng
->garbage_time
,
2678 write
+= config_write_distribute (vty
);
2680 write
+= config_write_if_rmap (vty
);
2687 /* RIPng node structure. */
2688 static struct cmd_node cmd_ripng_node
=
2691 "%s(config-router)# ",
2696 ripng_distribute_update (struct distribute
*dist
)
2698 struct interface
*ifp
;
2699 struct ripng_interface
*ri
;
2700 struct access_list
*alist
;
2701 struct prefix_list
*plist
;
2706 ifp
= if_lookup_by_name (dist
->ifname
);
2712 if (dist
->list
[DISTRIBUTE_IN
])
2714 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
2716 ri
->list
[RIPNG_FILTER_IN
] = alist
;
2718 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2721 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2723 if (dist
->list
[DISTRIBUTE_OUT
])
2725 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
2727 ri
->list
[RIPNG_FILTER_OUT
] = alist
;
2729 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2732 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2734 if (dist
->prefix
[DISTRIBUTE_IN
])
2736 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
2738 ri
->prefix
[RIPNG_FILTER_IN
] = plist
;
2740 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2743 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2745 if (dist
->prefix
[DISTRIBUTE_OUT
])
2747 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
2749 ri
->prefix
[RIPNG_FILTER_OUT
] = plist
;
2751 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2754 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2758 ripng_distribute_update_interface (struct interface
*ifp
)
2760 struct distribute
*dist
;
2762 dist
= distribute_lookup (ifp
->name
);
2764 ripng_distribute_update (dist
);
2767 /* Update all interface's distribute list. */
2769 ripng_distribute_update_all (struct prefix_list
*notused
)
2771 struct interface
*ifp
;
2772 struct listnode
*node
;
2774 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
2775 ripng_distribute_update_interface (ifp
);
2779 ripng_distribute_update_all_wrapper (struct access_list
*notused
)
2781 ripng_distribute_update_all(NULL
);
2784 /* delete all the added ripng routes. */
2789 struct route_node
*rp
;
2790 struct ripng_info
*rinfo
;
2793 /* Clear RIPng routes */
2794 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
)) {
2795 if ((rinfo
= rp
->info
) != NULL
) {
2796 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2797 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2798 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
,
2799 &rinfo
->nexthop
, rinfo
->metric
);
2801 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
2802 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
2805 route_unlock_node (rp
);
2807 ripng_info_free(rinfo
);
2811 /* Cancel the RIPng timers */
2812 RIPNG_TIMER_OFF (ripng
->t_update
);
2813 RIPNG_TIMER_OFF (ripng
->t_triggered_update
);
2814 RIPNG_TIMER_OFF (ripng
->t_triggered_interval
);
2816 /* Cancel the read thread */
2817 if (ripng
->t_read
) {
2818 thread_cancel (ripng
->t_read
);
2819 ripng
->t_read
= NULL
;
2822 /* Close the RIPng socket */
2823 if (ripng
->sock
>= 0) {
2828 /* Static RIPng route configuration. */
2829 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2832 route_unlock_node (rp
);
2835 /* RIPng aggregated prefixes */
2836 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2839 route_unlock_node (rp
);
2842 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2843 if (ripng
->route_map
[i
].name
)
2844 free (ripng
->route_map
[i
].name
);
2846 XFREE (MTYPE_ROUTE_TABLE
, ripng
->table
);
2847 XFREE (MTYPE_ROUTE_TABLE
, ripng
->route
);
2848 XFREE (MTYPE_ROUTE_TABLE
, ripng
->aggregate
);
2850 XFREE (MTYPE_RIPNG
, ripng
);
2854 ripng_clean_network();
2855 ripng_passive_interface_clean ();
2856 ripng_offset_clean ();
2857 ripng_interface_clean ();
2858 ripng_redistribute_clean ();
2861 /* Reset all values to the default settings. */
2865 /* Call ripd related reset functions. */
2866 ripng_debug_reset ();
2867 ripng_route_map_reset ();
2869 /* Call library reset functions. */
2871 access_list_reset ();
2872 prefix_list_reset ();
2874 distribute_list_reset ();
2876 ripng_interface_reset ();
2878 ripng_zclient_reset ();
2882 ripng_if_rmap_update (struct if_rmap
*if_rmap
)
2884 struct interface
*ifp
;
2885 struct ripng_interface
*ri
;
2886 struct route_map
*rmap
;
2888 ifp
= if_lookup_by_name (if_rmap
->ifname
);
2894 if (if_rmap
->routemap
[IF_RMAP_IN
])
2896 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_IN
]);
2898 ri
->routemap
[IF_RMAP_IN
] = rmap
;
2900 ri
->routemap
[IF_RMAP_IN
] = NULL
;
2903 ri
->routemap
[RIPNG_FILTER_IN
] = NULL
;
2905 if (if_rmap
->routemap
[IF_RMAP_OUT
])
2907 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_OUT
]);
2909 ri
->routemap
[IF_RMAP_OUT
] = rmap
;
2911 ri
->routemap
[IF_RMAP_OUT
] = NULL
;
2914 ri
->routemap
[RIPNG_FILTER_OUT
] = NULL
;
2918 ripng_if_rmap_update_interface (struct interface
*ifp
)
2920 struct if_rmap
*if_rmap
;
2922 if_rmap
= if_rmap_lookup (ifp
->name
);
2924 ripng_if_rmap_update (if_rmap
);
2928 ripng_routemap_update_redistribute (void)
2934 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2936 if (ripng
->route_map
[i
].name
)
2937 ripng
->route_map
[i
].map
=
2938 route_map_lookup_by_name (ripng
->route_map
[i
].name
);
2944 ripng_routemap_update (const char *unused
)
2946 struct interface
*ifp
;
2947 struct listnode
*node
;
2949 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
2950 ripng_if_rmap_update_interface (ifp
);
2952 ripng_routemap_update_redistribute ();
2955 /* Initialize ripng structure and set commands. */
2960 srand (time (NULL
));
2962 /* Install RIPNG_NODE. */
2963 install_node (&cmd_ripng_node
, ripng_config_write
);
2965 /* Install ripng commands. */
2966 install_element (VIEW_NODE
, &show_ipv6_ripng_cmd
);
2967 install_element (VIEW_NODE
, &show_ipv6_ripng_status_cmd
);
2969 install_element (ENABLE_NODE
, &show_ipv6_ripng_cmd
);
2970 install_element (ENABLE_NODE
, &show_ipv6_ripng_status_cmd
);
2972 install_element (CONFIG_NODE
, &router_ripng_cmd
);
2973 install_element (CONFIG_NODE
, &no_router_ripng_cmd
);
2975 install_default (RIPNG_NODE
);
2976 install_element (RIPNG_NODE
, &ripng_route_cmd
);
2977 install_element (RIPNG_NODE
, &no_ripng_route_cmd
);
2978 install_element (RIPNG_NODE
, &ripng_aggregate_address_cmd
);
2979 install_element (RIPNG_NODE
, &no_ripng_aggregate_address_cmd
);
2981 install_element (RIPNG_NODE
, &ripng_default_metric_cmd
);
2982 install_element (RIPNG_NODE
, &no_ripng_default_metric_cmd
);
2983 install_element (RIPNG_NODE
, &no_ripng_default_metric_val_cmd
);
2985 install_element (RIPNG_NODE
, &ripng_timers_cmd
);
2986 install_element (RIPNG_NODE
, &no_ripng_timers_cmd
);
2987 install_element (RIPNG_NODE
, &no_ripng_timers_val_cmd
);
2989 install_element (RIPNG_NODE
, &ripng_update_timer_cmd
);
2990 install_element (RIPNG_NODE
, &no_ripng_update_timer_cmd
);
2991 install_element (RIPNG_NODE
, &ripng_timeout_timer_cmd
);
2992 install_element (RIPNG_NODE
, &no_ripng_timeout_timer_cmd
);
2993 install_element (RIPNG_NODE
, &ripng_garbage_timer_cmd
);
2994 install_element (RIPNG_NODE
, &no_ripng_garbage_timer_cmd
);
2997 install_element (RIPNG_NODE
, &ripng_default_information_originate_cmd
);
2998 install_element (RIPNG_NODE
, &no_ripng_default_information_originate_cmd
);
3001 ripng_debug_init ();
3003 /* Access list install. */
3004 access_list_init ();
3005 access_list_add_hook (ripng_distribute_update_all_wrapper
);
3006 access_list_delete_hook (ripng_distribute_update_all_wrapper
);
3008 /* Prefix list initialize.*/
3009 prefix_list_init ();
3010 prefix_list_add_hook (ripng_distribute_update_all
);
3011 prefix_list_delete_hook (ripng_distribute_update_all
);
3013 /* Distribute list install. */
3014 distribute_list_init (RIPNG_NODE
);
3015 distribute_list_add_hook (ripng_distribute_update
);
3016 distribute_list_delete_hook (ripng_distribute_update
);
3018 /* Route-map for interface. */
3019 ripng_route_map_init ();
3020 ripng_offset_init ();
3022 route_map_add_hook (ripng_routemap_update
);
3023 route_map_delete_hook (ripng_routemap_update
);
3025 if_rmap_init (RIPNG_NODE
);
3026 if_rmap_hook_add (ripng_if_rmap_update
);
3027 if_rmap_hook_delete (ripng_if_rmap_update
);