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
)
275 *hoplimit
= *((int *) CMSG_DATA (cmsgptr
));
278 /* Hoplimit check shold be done when destination address is
279 multicast address. */
280 if (! IN6_IS_ADDR_MULTICAST (&dst
))
286 /* Dump rip packet */
288 ripng_packet_dump (struct ripng_packet
*packet
, int size
, const char *sndrcv
)
292 const char *command_str
;
294 /* Set command string. */
295 if (packet
->command
== RIPNG_REQUEST
)
296 command_str
= "request";
297 else if (packet
->command
== RIPNG_RESPONSE
)
298 command_str
= "response";
300 command_str
= "unknown";
302 /* Dump packet header. */
303 zlog_debug ("%s %s version %d packet size %d",
304 sndrcv
, command_str
, packet
->version
, size
);
306 /* Dump each routing table entry. */
309 for (lim
= (caddr_t
) packet
+ size
; (caddr_t
) rte
< lim
; rte
++)
311 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
312 zlog_debug (" nexthop %s/%d", inet6_ntoa (&rte
->addr
), rte
->prefixlen
);
314 zlog_debug (" %s/%d metric %d tag %d",
315 inet6_ntoa (&rte
->addr
), rte
->prefixlen
,
316 rte
->metric
, ntohs (rte
->tag
));
320 /* RIPng next hop address RTE (Route Table Entry). */
322 ripng_nexthop_rte (struct rte
*rte
,
323 struct sockaddr_in6
*from
,
324 struct ripng_nexthop
*nexthop
)
326 char buf
[INET6_BUFSIZ
];
328 /* Logging before checking RTE. */
329 if (IS_RIPNG_DEBUG_RECV
)
330 zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d",
331 inet6_ntoa (&rte
->addr
), ntohs (rte
->tag
), rte
->prefixlen
);
333 /* RFC2080 2.1.1 Next Hop:
334 The route tag and prefix length in the next hop RTE must be
335 set to zero on sending and ignored on receiption. */
336 if (ntohs (rte
->tag
) != 0)
337 zlog_warn ("RIPng nexthop RTE with non zero tag value %d from %s",
338 ntohs (rte
->tag
), inet6_ntoa (&from
->sin6_addr
));
340 if (rte
->prefixlen
!= 0)
341 zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
342 rte
->prefixlen
, inet6_ntoa (&from
->sin6_addr
));
344 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
345 next hop RTE indicates that the next hop address should be the
346 originator of the RIPng advertisement. An address specified as a
347 next hop must be a link-local address. */
348 if (IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
))
350 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
351 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
355 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
357 nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
358 IPV6_ADDR_COPY (&nexthop
->address
, &rte
->addr
);
362 /* The purpose of the next hop RTE is to eliminate packets being
363 routed through extra hops in the system. It is particularly useful
364 when RIPng is not being run on all of the routers on a network.
365 Note that next hop RTE is "advisory". That is, if the provided
366 information is ignored, a possibly sub-optimal, but absolutely
367 valid, route may be taken. If the received next hop address is not
368 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
369 zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s",
370 inet6_ntoa (&rte
->addr
),
371 inet_ntop (AF_INET6
, &from
->sin6_addr
, buf
, INET6_BUFSIZ
));
373 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
374 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
379 /* If ifp has same link-local address then return 1. */
381 ripng_lladdr_check (struct interface
*ifp
, struct in6_addr
*addr
)
383 struct listnode
*listnode
;
384 struct connected
*connected
;
387 for (listnode
= listhead (ifp
->connected
); listnode
; nextnode (listnode
))
388 if ((connected
= getdata (listnode
)) != NULL
)
390 p
= connected
->address
;
392 if (p
->family
== AF_INET6
&&
393 IN6_IS_ADDR_LINKLOCAL (&p
->u
.prefix6
) &&
394 IN6_ARE_ADDR_EQUAL (&p
->u
.prefix6
, addr
))
400 /* RIPng route garbage collect timer. */
402 ripng_garbage_collect (struct thread
*t
)
404 struct ripng_info
*rinfo
;
405 struct route_node
*rp
;
407 rinfo
= THREAD_ARG (t
);
408 rinfo
->t_garbage_collect
= NULL
;
410 /* Off timeout timer. */
411 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
413 /* Get route_node pointer. */
416 /* Unlock route_node. */
418 route_unlock_node (rp
);
420 /* Free RIPng routing information. */
421 ripng_info_free (rinfo
);
426 /* Timeout RIPng routes. */
428 ripng_timeout (struct thread
*t
)
430 struct ripng_info
*rinfo
;
431 struct route_node
*rp
;
433 rinfo
= THREAD_ARG (t
);
434 rinfo
->t_timeout
= NULL
;
436 /* Get route_node pointer. */
439 /* - The garbage-collection timer is set for 120 seconds. */
440 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
, ripng_garbage_collect
,
441 ripng
->garbage_time
);
443 /* Delete this route from the kernel. */
444 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
446 /* - The metric for the route is set to 16 (infinity). This causes
447 the route to be removed from service. */
448 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
449 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
451 /* Aggregate count decrement. */
452 ripng_aggregate_decrement (rp
, rinfo
);
454 /* - The route change flag is to indicate that this entry has been
456 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
458 /* - The output process is signalled to trigger a response. */
459 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
465 ripng_timeout_update (struct ripng_info
*rinfo
)
467 if (rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
469 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
470 RIPNG_TIMER_ON (rinfo
->t_timeout
, ripng_timeout
, ripng
->timeout_time
);
475 ripng_incoming_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
477 struct distribute
*dist
;
478 struct access_list
*alist
;
479 struct prefix_list
*plist
;
481 /* Input distribute-list filtering. */
482 if (ri
->list
[RIPNG_FILTER_IN
])
484 if (access_list_apply (ri
->list
[RIPNG_FILTER_IN
],
485 (struct prefix
*) p
) == FILTER_DENY
)
487 if (IS_RIPNG_DEBUG_PACKET
)
488 zlog_debug ("%s/%d filtered by distribute in",
489 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
493 if (ri
->prefix
[RIPNG_FILTER_IN
])
495 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_IN
],
496 (struct prefix
*) p
) == PREFIX_DENY
)
498 if (IS_RIPNG_DEBUG_PACKET
)
499 zlog_debug ("%s/%d filtered by prefix-list in",
500 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
505 /* All interface filter check. */
506 dist
= distribute_lookup (NULL
);
509 if (dist
->list
[DISTRIBUTE_IN
])
511 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
515 if (access_list_apply (alist
,
516 (struct prefix
*) p
) == FILTER_DENY
)
518 if (IS_RIPNG_DEBUG_PACKET
)
519 zlog_debug ("%s/%d filtered by distribute in",
520 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
525 if (dist
->prefix
[DISTRIBUTE_IN
])
527 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
531 if (prefix_list_apply (plist
,
532 (struct prefix
*) p
) == PREFIX_DENY
)
534 if (IS_RIPNG_DEBUG_PACKET
)
535 zlog_debug ("%s/%d filtered by prefix-list in",
536 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
546 ripng_outgoing_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
548 struct distribute
*dist
;
549 struct access_list
*alist
;
550 struct prefix_list
*plist
;
552 if (ri
->list
[RIPNG_FILTER_OUT
])
554 if (access_list_apply (ri
->list
[RIPNG_FILTER_OUT
],
555 (struct prefix
*) p
) == FILTER_DENY
)
557 if (IS_RIPNG_DEBUG_PACKET
)
558 zlog_debug ("%s/%d is filtered by distribute out",
559 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
563 if (ri
->prefix
[RIPNG_FILTER_OUT
])
565 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_OUT
],
566 (struct prefix
*) p
) == PREFIX_DENY
)
568 if (IS_RIPNG_DEBUG_PACKET
)
569 zlog_debug ("%s/%d is filtered by prefix-list out",
570 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
575 /* All interface filter check. */
576 dist
= distribute_lookup (NULL
);
579 if (dist
->list
[DISTRIBUTE_OUT
])
581 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
585 if (access_list_apply (alist
,
586 (struct prefix
*) p
) == FILTER_DENY
)
588 if (IS_RIPNG_DEBUG_PACKET
)
589 zlog_debug ("%s/%d filtered by distribute out",
590 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
595 if (dist
->prefix
[DISTRIBUTE_OUT
])
597 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
601 if (prefix_list_apply (plist
,
602 (struct prefix
*) p
) == PREFIX_DENY
)
604 if (IS_RIPNG_DEBUG_PACKET
)
605 zlog_debug ("%s/%d filtered by prefix-list out",
606 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
615 /* Process RIPng route according to RFC2080. */
617 ripng_route_process (struct rte
*rte
, struct sockaddr_in6
*from
,
618 struct ripng_nexthop
*ripng_nexthop
,
619 struct interface
*ifp
)
622 struct prefix_ipv6 p
;
623 struct route_node
*rp
;
624 struct ripng_info
*rinfo
;
625 struct ripng_interface
*ri
;
626 struct in6_addr
*nexthop
;
630 /* Make prefix structure. */
631 memset (&p
, 0, sizeof (struct prefix_ipv6
));
633 /* p.prefix = rte->addr; */
634 IPV6_ADDR_COPY (&p
.prefix
, &rte
->addr
);
635 p
.prefixlen
= rte
->prefixlen
;
637 /* Make sure mask is applied. */
638 /* XXX We have to check the prefix is valid or not before call
640 apply_mask_ipv6 (&p
);
642 /* Apply input filters. */
645 ret
= ripng_incoming_filter (&p
, ri
);
650 if (ri
->routemap
[RIPNG_FILTER_IN
])
653 struct ripng_info newinfo
;
655 memset (&newinfo
, 0, sizeof (struct ripng_info
));
656 newinfo
.type
= ZEBRA_ROUTE_RIPNG
;
657 newinfo
.sub_type
= RIPNG_ROUTE_RTE
;
658 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
659 newinfo
.nexthop
= ripng_nexthop
->address
;
661 newinfo
.nexthop
= from
->sin6_addr
;
662 newinfo
.from
= from
->sin6_addr
;
663 newinfo
.ifindex
= ifp
->ifindex
;
664 newinfo
.metric
= rte
->metric
;
665 newinfo
.metric_out
= rte
->metric
; /* XXX */
666 newinfo
.tag
= ntohs(rte
->tag
); /* XXX */
668 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_IN
],
669 (struct prefix
*)&p
, RMAP_RIPNG
, &newinfo
);
671 if (ret
== RMAP_DENYMATCH
)
673 if (IS_RIPNG_DEBUG_PACKET
)
674 zlog_debug ("RIPng %s/%d is filtered by route-map in",
675 inet6_ntoa (&p
.prefix
), p
.prefixlen
);
679 /* Get back the object */
680 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
) {
681 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &ripng_nexthop
->address
) ) {
682 /* the nexthop get changed by the routemap */
683 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
))
684 ripng_nexthop
->address
= newinfo
.nexthop
;
686 ripng_nexthop
->address
= in6addr_any
;
689 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &from
->sin6_addr
) ) {
690 /* the nexthop get changed by the routemap */
691 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
)) {
692 ripng_nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
693 ripng_nexthop
->address
= newinfo
.nexthop
;
697 rte
->tag
= htons(newinfo
.tag_out
); /* XXX */
698 rte
->metric
= newinfo
.metric_out
; /* XXX: the routemap uses the metric_out field */
701 /* Once the entry has been validated, update the metric by
702 * adding the cost of the network on wich the message
703 * arrived. If the result is greater than infinity, use infinity
704 * (RFC2453 Sec. 3.9.2)
707 /* Zebra ripngd can handle offset-list in. */
708 ret
= ripng_offset_list_apply_in (&p
, ifp
, &rte
->metric
);
710 /* If offset-list does not modify the metric use interface's
713 rte
->metric
+= ifp
->metric
;
715 if (rte
->metric
> RIPNG_METRIC_INFINITY
)
716 rte
->metric
= RIPNG_METRIC_INFINITY
;
718 /* Set nexthop pointer. */
719 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
720 nexthop
= &ripng_nexthop
->address
;
722 nexthop
= &from
->sin6_addr
;
724 /* Lookup RIPng routing table. */
725 rp
= route_node_get (ripng
->table
, (struct prefix
*) &p
);
731 /* Redistributed route check. */
732 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
733 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
736 /* Local static route. */
737 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
738 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
739 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
))
740 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
744 if (rp
->info
== NULL
)
746 /* Now, check to see whether there is already an explicit route
747 for the destination prefix. If there is no such route, add
748 this route to the routing table, unless the metric is
749 infinity (there is no point in adding a route which
751 if (rte
->metric
!= RIPNG_METRIC_INFINITY
)
753 rinfo
= ripng_info_new ();
755 /* - Setting the destination prefix and length to those in
760 /* - Setting the metric to the newly calculated metric (as
762 rinfo
->metric
= rte
->metric
;
763 rinfo
->tag
= ntohs (rte
->tag
);
765 /* - Set the next hop address to be the address of the router
766 from which the datagram came or the next hop address
767 specified by a next hop RTE. */
768 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
769 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
770 rinfo
->ifindex
= ifp
->ifindex
;
772 /* - Initialize the timeout for the route. If the
773 garbage-collection timer is running for this route, stop it. */
774 ripng_timeout_update (rinfo
);
776 /* - Set the route change flag. */
777 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
779 /* - Signal the output process to trigger an update (see section
781 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
783 /* Finally, route goes into the kernel. */
784 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
785 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
787 ripng_zebra_ipv6_add (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
788 rinfo
->flags
|= RIPNG_RTF_FIB
;
790 /* Aggregate check. */
791 ripng_aggregate_increment (rp
, rinfo
);
798 /* If there is an existing route, compare the next hop address
799 to the address of the router from which the datagram came.
800 If this datagram is from the same router as the existing
801 route, reinitialize the timeout. */
802 same
= (IN6_ARE_ADDR_EQUAL (&rinfo
->from
, &from
->sin6_addr
)
803 && (rinfo
->ifindex
== ifp
->ifindex
));
806 ripng_timeout_update (rinfo
);
808 /* Next, compare the metrics. If the datagram is from the same
809 router as the existing route, and the new metric is different
810 than the old one; or, if the new metric is lower than the old
811 one; do the following actions: */
812 if ((same
&& rinfo
->metric
!= rte
->metric
) ||
813 rte
->metric
< rinfo
->metric
)
815 /* - Adopt the route from the datagram. That is, put the
816 new metric in, and adjust the next hop address (if
818 oldmetric
= rinfo
->metric
;
819 rinfo
->metric
= rte
->metric
;
820 rinfo
->tag
= ntohs (rte
->tag
);
821 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
822 rinfo
->ifindex
= ifp
->ifindex
;
824 /* Should a new route to this network be established
825 while the garbage-collection timer is running, the
826 new route will replace the one that is about to be
827 deleted. In this case the garbage-collection timer
830 if (oldmetric
== RIPNG_METRIC_INFINITY
&&
831 rinfo
->metric
< RIPNG_METRIC_INFINITY
)
833 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
834 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
836 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
838 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
839 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
841 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
);
842 rinfo
->flags
|= RIPNG_RTF_FIB
;
844 /* The aggregation counter needs to be updated because
845 the prefixes, which are into the gc, have been
846 removed from the aggregator (see ripng_timout). */
847 ripng_aggregate_increment (rp
, rinfo
);
850 /* Update nexthop and/or metric value. */
851 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
853 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
854 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
);
855 rinfo
->flags
|= RIPNG_RTF_FIB
;
857 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
858 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
861 /* - Set the route change flag and signal the output process
862 to trigger an update. */
863 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
864 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
866 /* - If the new metric is infinity, start the deletion
867 process (described above); */
868 if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
870 /* If the new metric is infinity, the deletion process
871 begins for the route, which is no longer used for
872 routing packets. Note that the deletion process is
873 started only when the metric is first set to
874 infinity. If the metric was already infinity, then a
875 new deletion process is not started. */
876 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
878 /* - The garbage-collection timer is set for 120 seconds. */
879 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
880 ripng_garbage_collect
, ripng
->garbage_time
);
881 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
883 /* - The metric for the route is set to 16
884 (infinity). This causes the route to be removed
886 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
887 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
889 /* Aggregate count decrement. */
890 ripng_aggregate_decrement (rp
, rinfo
);
892 /* - The route change flag is to indicate that this
893 entry has been changed. */
894 /* - The output process is signalled to trigger a
896 ; /* Above processes are already done previously. */
901 /* otherwise, re-initialize the timeout. */
902 ripng_timeout_update (rinfo
);
905 /* Unlock tempolary lock of the route. */
906 route_unlock_node (rp
);
910 /* Add redistributed route to RIPng table. */
912 ripng_redistribute_add (int type
, int sub_type
, struct prefix_ipv6
*p
,
913 unsigned int ifindex
, struct in6_addr
*nexthop
)
915 struct route_node
*rp
;
916 struct ripng_info
*rinfo
;
918 /* Redistribute route */
919 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
921 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
923 #if defined (MUSICA) || defined (LINUX)
924 /* XXX As long as the RIPng redistribution is applied to all the connected
925 * routes, one needs to filter the ::/96 prefixes.
926 * However it could be a wanted case, it will be removed soon.
928 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
929 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
931 #endif /* MUSICA or LINUX */
933 rp
= route_node_get (ripng
->table
, (struct prefix
*) p
);
938 if (rinfo
->type
== ZEBRA_ROUTE_CONNECT
939 && rinfo
->sub_type
== RIPNG_ROUTE_INTERFACE
940 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
) {
941 route_unlock_node (rp
);
945 /* Manually configured RIPng route check.
946 * They have the precedence on all the other entries.
948 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
949 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
950 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
)) ) {
951 if (type
!= ZEBRA_ROUTE_RIPNG
|| ((sub_type
!= RIPNG_ROUTE_STATIC
) &&
952 (sub_type
!= RIPNG_ROUTE_DEFAULT
))) {
953 route_unlock_node (rp
);
958 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
959 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
961 /* Tells the other daemons about the deletion of
964 if (ripng_route_rte (rinfo
))
965 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
969 ripng_info_free (rinfo
);
971 route_unlock_node (rp
);
975 rinfo
= ripng_info_new ();
978 rinfo
->sub_type
= sub_type
;
979 rinfo
->ifindex
= ifindex
;
983 if (nexthop
&& IN6_IS_ADDR_LINKLOCAL(nexthop
))
984 rinfo
->nexthop
= *nexthop
;
986 rinfo
->flags
|= RIPNG_RTF_FIB
;
989 /* Aggregate check. */
990 ripng_aggregate_increment (rp
, rinfo
);
992 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
994 if (IS_RIPNG_DEBUG_EVENT
) {
996 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
997 inet6_ntoa(&p
->prefix
), p
->prefixlen
,
998 ifindex2ifname(ifindex
));
1000 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1001 inet6_ntoa(&p
->prefix
), p
->prefixlen
, inet6_ntoa(nexthop
),
1002 ifindex2ifname(ifindex
));
1005 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1008 /* Delete redistributed route to RIPng table. */
1010 ripng_redistribute_delete (int type
, int sub_type
, struct prefix_ipv6
*p
,
1011 unsigned int ifindex
)
1013 struct route_node
*rp
;
1014 struct ripng_info
*rinfo
;
1016 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
1018 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
1020 #if defined (MUSICA) || defined (LINUX)
1021 /* XXX As long as the RIPng redistribution is applied to all the connected
1022 * routes, one needs to filter the ::/96 prefixes.
1023 * However it could be a wanted case, it will be removed soon.
1025 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
1026 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
1028 #endif /* MUSICA or LINUX */
1030 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) p
);
1037 && rinfo
->type
== type
1038 && rinfo
->sub_type
== sub_type
1039 && rinfo
->ifindex
== ifindex
)
1041 /* Perform poisoned reverse. */
1042 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1043 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1044 ripng_garbage_collect
, ripng
->garbage_time
);
1045 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1047 /* Aggregate count decrement. */
1048 ripng_aggregate_decrement (rp
, rinfo
);
1050 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1052 if (IS_RIPNG_DEBUG_EVENT
)
1053 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1054 inet6_ntoa(&p
->prefix
), p
->prefixlen
,
1055 ifindex2ifname(ifindex
));
1057 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1062 /* Withdraw redistributed route. */
1064 ripng_redistribute_withdraw (int type
)
1066 struct route_node
*rp
;
1067 struct ripng_info
*rinfo
;
1072 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1073 if ((rinfo
= rp
->info
) != NULL
)
1075 if ((rinfo
->type
== type
)
1076 && (rinfo
->sub_type
!= RIPNG_ROUTE_INTERFACE
))
1078 /* Perform poisoned reverse. */
1079 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1080 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1081 ripng_garbage_collect
, ripng
->garbage_time
);
1082 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1084 /* Aggregate count decrement. */
1085 ripng_aggregate_decrement (rp
, rinfo
);
1087 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1089 if (IS_RIPNG_DEBUG_EVENT
) {
1090 struct prefix_ipv6
*p
= (struct prefix_ipv6
*) &rp
->p
;
1092 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
1093 inet6_ntoa(&p
->prefix
), p
->prefixlen
,
1094 ifindex2ifname(rinfo
->ifindex
));
1097 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1102 /* RIP routing information. */
1104 ripng_response_process (struct ripng_packet
*packet
, int size
,
1105 struct sockaddr_in6
*from
, struct interface
*ifp
,
1110 struct ripng_nexthop nexthop
;
1112 /* RFC2080 2.4.2 Response Messages:
1113 The Response must be ignored if it is not from the RIPng port. */
1114 if (ntohs (from
->sin6_port
) != RIPNG_PORT_DEFAULT
)
1116 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
1117 ntohs (from
->sin6_port
), inet6_ntoa (&from
->sin6_addr
));
1118 ripng_peer_bad_packet (from
);
1122 /* The datagram's IPv6 source address should be checked to see
1123 whether the datagram is from a valid neighbor; the source of the
1124 datagram must be a link-local address. */
1125 if (! IN6_IS_ADDR_LINKLOCAL(&from
->sin6_addr
))
1127 zlog_warn ("RIPng packet comes from non link local address %s",
1128 inet6_ntoa (&from
->sin6_addr
));
1129 ripng_peer_bad_packet (from
);
1133 /* It is also worth checking to see whether the response is from one
1134 of the router's own addresses. Interfaces on broadcast networks
1135 may receive copies of their own multicasts immediately. If a
1136 router processes its own output as new input, confusion is likely,
1137 and such datagrams must be ignored. */
1138 if (ripng_lladdr_check (ifp
, &from
->sin6_addr
))
1140 zlog_warn ("RIPng packet comes from my own link local address %s",
1141 inet6_ntoa (&from
->sin6_addr
));
1142 ripng_peer_bad_packet (from
);
1146 /* As an additional check, periodic advertisements must have their
1147 hop counts set to 255, and inbound, multicast packets sent from the
1148 RIPng port (i.e. periodic advertisement or triggered update
1149 packets) must be examined to ensure that the hop count is 255. */
1150 if (hoplimit
>= 0 && hoplimit
!= 255)
1152 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
1153 hoplimit
, inet6_ntoa (&from
->sin6_addr
));
1154 ripng_peer_bad_packet (from
);
1158 /* Update RIPng peer. */
1159 ripng_peer_update (from
, packet
->version
);
1161 /* Reset nexthop. */
1162 memset (&nexthop
, 0, sizeof (struct ripng_nexthop
));
1163 nexthop
.flag
= RIPNG_NEXTHOP_UNSPEC
;
1165 /* Set RTE pointer. */
1168 for (lim
= ((caddr_t
) packet
) + size
; (caddr_t
) rte
< lim
; rte
++)
1170 /* First of all, we have to check this RTE is next hop RTE or
1171 not. Next hop RTE is completely different with normal RTE so
1172 we need special treatment. */
1173 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
1175 ripng_nexthop_rte (rte
, from
, &nexthop
);
1179 /* RTE information validation. */
1181 /* - is the destination prefix valid (e.g., not a multicast
1182 prefix and not a link-local address) A link-local address
1183 should never be present in an RTE. */
1184 if (IN6_IS_ADDR_MULTICAST (&rte
->addr
))
1186 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
1187 inet6_ntoa (&rte
->addr
), rte
->prefixlen
, rte
->metric
);
1188 ripng_peer_bad_route (from
);
1191 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
1193 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
1194 inet6_ntoa (&rte
->addr
), rte
->prefixlen
, rte
->metric
);
1195 ripng_peer_bad_route (from
);
1198 if (IN6_IS_ADDR_LOOPBACK (&rte
->addr
))
1200 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
1201 inet6_ntoa (&rte
->addr
), rte
->prefixlen
, rte
->metric
);
1202 ripng_peer_bad_route (from
);
1206 /* - is the prefix length valid (i.e., between 0 and 128,
1208 if (rte
->prefixlen
> 128)
1210 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
1211 inet6_ntoa (&rte
->addr
), rte
->prefixlen
,
1212 inet6_ntoa (&from
->sin6_addr
), ifp
->name
);
1213 ripng_peer_bad_route (from
);
1217 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1218 if (! (rte
->metric
>= 1 && rte
->metric
<= 16))
1220 zlog_warn ("Invalid metric %d from %s%%%s", rte
->metric
,
1221 inet6_ntoa (&from
->sin6_addr
), ifp
->name
);
1222 ripng_peer_bad_route (from
);
1226 /* Vincent: XXX Should we compute the direclty reachable nexthop
1227 * for our RIPng network ?
1230 /* Routing table updates. */
1231 ripng_route_process (rte
, from
, &nexthop
, ifp
);
1235 /* Response to request message. */
1237 ripng_request_process (struct ripng_packet
*packet
,int size
,
1238 struct sockaddr_in6
*from
, struct interface
*ifp
)
1242 struct prefix_ipv6 p
;
1243 struct route_node
*rp
;
1244 struct ripng_info
*rinfo
;
1245 struct ripng_interface
*ri
;
1247 /* Does not reponse to the requests on the loopback interfaces */
1248 if (if_is_loopback (ifp
))
1251 /* Check RIPng process is enabled on this interface. */
1256 /* When passive interface is specified, suppress responses */
1260 /* RIPng peer update. */
1261 ripng_peer_update (from
, packet
->version
);
1263 lim
= ((caddr_t
) packet
) + size
;
1266 /* The Request is processed entry by entry. If there are no
1267 entries, no response is given. */
1268 if (lim
== (caddr_t
) rte
)
1271 /* There is one special case. If there is exactly one entry in the
1272 request, and it has a destination prefix of zero, a prefix length
1273 of zero, and a metric of infinity (i.e., 16), then this is a
1274 request to send the entire routing table. In that case, a call
1275 is made to the output process to send the routing table to the
1276 requesting address/port. */
1277 if (lim
== ((caddr_t
) (rte
+ 1)) &&
1278 IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
) &&
1279 rte
->prefixlen
== 0 &&
1280 rte
->metric
== RIPNG_METRIC_INFINITY
)
1282 /* All route with split horizon */
1283 ripng_output_process (ifp
, from
, ripng_all_route
);
1287 /* Except for this special case, processing is quite simple.
1288 Examine the list of RTEs in the Request one by one. For each
1289 entry, look up the destination in the router's routing
1290 database and, if there is a route, put that route's metric in
1291 the metric field of the RTE. If there is no explicit route
1292 to the specified destination, put infinity in the metric
1293 field. Once all the entries have been filled in, change the
1294 command from Request to Response and send the datagram back
1295 to the requestor. */
1296 memset (&p
, 0, sizeof (struct prefix_ipv6
));
1297 p
.family
= AF_INET6
;
1299 for (; ((caddr_t
) rte
) < lim
; rte
++)
1301 p
.prefix
= rte
->addr
;
1302 p
.prefixlen
= rte
->prefixlen
;
1303 apply_mask_ipv6 (&p
);
1305 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) &p
);
1310 rte
->metric
= rinfo
->metric
;
1311 route_unlock_node (rp
);
1314 rte
->metric
= RIPNG_METRIC_INFINITY
;
1316 packet
->command
= RIPNG_RESPONSE
;
1318 ripng_send_packet ((caddr_t
) packet
, size
, from
, ifp
);
1322 /* First entry point of reading RIPng packet. */
1324 ripng_read (struct thread
*thread
)
1328 struct sockaddr_in6 from
;
1329 struct ripng_packet
*packet
;
1330 unsigned int ifindex
;
1331 struct interface
*ifp
;
1334 /* Check ripng is active and alive. */
1335 assert (ripng
!= NULL
);
1336 assert (ripng
->sock
>= 0);
1338 /* Fetch thread data and set read pointer to empty for event
1339 managing. `sock' sould be same as ripng->sock. */
1340 sock
= THREAD_FD (thread
);
1341 ripng
->t_read
= NULL
;
1343 /* Add myself to the next event. */
1344 ripng_event (RIPNG_READ
, sock
);
1346 /* Read RIPng packet. */
1347 len
= ripng_recv_packet (sock
, STREAM_DATA (ripng
->ibuf
),
1348 STREAM_SIZE (ripng
->ibuf
), &from
, &ifindex
,
1352 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno
));
1356 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1357 (4)) must be multiple size of one RTE size (20). */
1358 if (((len
- 4) % 20) != 0)
1360 zlog_warn ("RIPng invalid packet size %d from %s", len
,
1361 inet6_ntoa (&from
.sin6_addr
));
1362 ripng_peer_bad_packet (&from
);
1366 packet
= (struct ripng_packet
*) STREAM_DATA (ripng
->ibuf
);
1367 ifp
= if_lookup_by_index (ifindex
);
1369 /* RIPng packet received. */
1370 if (IS_RIPNG_DEBUG_EVENT
)
1371 zlog_debug ("RIPng packet received from %s port %d on %s",
1372 inet6_ntoa (&from
.sin6_addr
), ntohs (from
.sin6_port
),
1373 ifp
? ifp
->name
: "unknown");
1375 /* Logging before packet checking. */
1376 if (IS_RIPNG_DEBUG_RECV
)
1377 ripng_packet_dump (packet
, len
, "RECV");
1379 /* Packet comes from unknown interface. */
1382 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex
);
1386 /* Packet version mismatch checking. */
1387 if (packet
->version
!= ripng
->version
)
1389 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1390 packet
->version
, ripng
->version
);
1391 ripng_peer_bad_packet (&from
);
1395 /* Process RIPng packet. */
1396 switch (packet
->command
)
1399 ripng_request_process (packet
, len
, &from
, ifp
);
1401 case RIPNG_RESPONSE
:
1402 ripng_response_process (packet
, len
, &from
, ifp
, hoplimit
);
1405 zlog_warn ("Invalid RIPng command %d", packet
->command
);
1406 ripng_peer_bad_packet (&from
);
1412 /* Walk down the RIPng routing table then clear changed flag. */
1414 ripng_clear_changed_flag ()
1416 struct route_node
*rp
;
1417 struct ripng_info
*rinfo
;
1419 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1420 if ((rinfo
= rp
->info
) != NULL
)
1421 if (rinfo
->flags
& RIPNG_RTF_CHANGED
)
1422 rinfo
->flags
&= ~RIPNG_RTF_CHANGED
;
1425 /* Regular update of RIPng route. Send all routing formation to RIPng
1426 enabled interface. */
1428 ripng_update (struct thread
*t
)
1430 struct listnode
*node
;
1431 struct interface
*ifp
;
1432 struct ripng_interface
*ri
;
1434 /* Clear update timer thread. */
1435 ripng
->t_update
= NULL
;
1437 /* Logging update event. */
1438 if (IS_RIPNG_DEBUG_EVENT
)
1439 zlog_debug ("RIPng update timer expired!");
1441 /* Supply routes to each interface. */
1442 for (node
= listhead (iflist
); node
; nextnode (node
))
1444 ifp
= getdata (node
);
1447 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1453 /* When passive interface is specified, suppress announce to the
1459 if (ri
->ri_send
== RIPNG_SEND_OFF
)
1461 if (IS_RIPNG_DEBUG_EVENT
)
1462 zlog (NULL
, LOG_DEBUG
,
1463 "[Event] RIPng send to if %d is suppressed by config",
1467 #endif /* RIPNG_ADVANCED */
1469 ripng_output_process (ifp
, NULL
, ripng_all_route
);
1472 /* Triggered updates may be suppressed if a regular update is due by
1473 the time the triggered update would be sent. */
1474 if (ripng
->t_triggered_interval
)
1476 thread_cancel (ripng
->t_triggered_interval
);
1477 ripng
->t_triggered_interval
= NULL
;
1481 /* Reset flush event. */
1482 ripng_event (RIPNG_UPDATE_EVENT
, 0);
1487 /* Triggered update interval timer. */
1489 ripng_triggered_interval (struct thread
*t
)
1491 ripng
->t_triggered_interval
= NULL
;
1496 ripng_triggered_update (t
);
1501 /* Execute triggered update. */
1503 ripng_triggered_update (struct thread
*t
)
1505 struct listnode
*node
;
1506 struct interface
*ifp
;
1507 struct ripng_interface
*ri
;
1510 ripng
->t_triggered_update
= NULL
;
1512 /* Cancel interval timer. */
1513 if (ripng
->t_triggered_interval
)
1515 thread_cancel (ripng
->t_triggered_interval
);
1516 ripng
->t_triggered_interval
= NULL
;
1520 /* Logging triggered update. */
1521 if (IS_RIPNG_DEBUG_EVENT
)
1522 zlog_debug ("RIPng triggered update!");
1524 /* Split Horizon processing is done when generating triggered
1525 updates as well as normal updates (see section 2.6). */
1526 for (node
= listhead (iflist
); node
; nextnode (node
))
1528 ifp
= getdata (node
);
1531 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1537 /* When passive interface is specified, suppress announce to the
1542 ripng_output_process (ifp
, NULL
, ripng_changed_route
);
1545 /* Once all of the triggered updates have been generated, the route
1546 change flags should be cleared. */
1547 ripng_clear_changed_flag ();
1549 /* After a triggered update is sent, a timer should be set for a
1550 random interval between 1 and 5 seconds. If other changes that
1551 would trigger updates occur before the timer expires, a single
1552 update is triggered when the timer expires. */
1553 interval
= (random () % 5) + 1;
1555 ripng
->t_triggered_interval
=
1556 thread_add_timer (master
, ripng_triggered_interval
, NULL
, interval
);
1561 /* Write routing table entry to the stream and return next index of
1562 the routing table entry in the stream. */
1564 ripng_write_rte (int num
, struct stream
*s
, struct prefix_ipv6
*p
,
1565 struct in6_addr
*nexthop
, u_int16_t tag
, u_char metric
)
1567 /* RIPng packet header. */
1570 stream_putc (s
, RIPNG_RESPONSE
);
1571 stream_putc (s
, RIPNG_V1
);
1575 /* Write routing table entry. */
1577 stream_write (s
, (u_char
*) &p
->prefix
, sizeof (struct in6_addr
));
1579 stream_write (s
, (u_char
*) nexthop
, sizeof (struct in6_addr
));
1580 stream_putw (s
, tag
);
1582 stream_putc (s
, p
->prefixlen
);
1585 stream_putc (s
, metric
);
1590 /* Send RESPONSE message to specified destination. */
1592 ripng_output_process (struct interface
*ifp
, struct sockaddr_in6
*to
,
1596 struct route_node
*rp
;
1597 struct ripng_info
*rinfo
;
1598 struct ripng_interface
*ri
;
1599 struct ripng_aggregate
*aggregate
;
1600 struct prefix_ipv6
*p
;
1601 struct list
* ripng_rte_list
;
1603 if (IS_RIPNG_DEBUG_EVENT
) {
1605 zlog_debug ("RIPng update routes to neighbor %s",
1606 inet6_ntoa(&to
->sin6_addr
));
1608 zlog_debug ("RIPng update routes on interface %s", ifp
->name
);
1611 /* Get RIPng interface. */
1614 ripng_rte_list
= ripng_rte_new();
1616 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1618 if ((rinfo
= rp
->info
) != NULL
&& rinfo
->suppress
== 0)
1620 /* If no route-map are applied, the RTE will be these following
1623 p
= (struct prefix_ipv6
*) &rp
->p
;
1624 rinfo
->metric_out
= rinfo
->metric
;
1625 rinfo
->tag_out
= rinfo
->tag
;
1626 memset(&rinfo
->nexthop_out
, 0, sizeof(rinfo
->nexthop_out
));
1627 /* In order to avoid some local loops,
1628 * if the RIPng route has a nexthop via this interface, keep the nexthop,
1629 * otherwise set it to 0. The nexthop should not be propagated
1630 * beyond the local broadcast/multicast area in order
1631 * to avoid an IGP multi-level recursive look-up.
1633 if (rinfo
->ifindex
== ifp
->ifindex
)
1634 rinfo
->nexthop_out
= rinfo
->nexthop
;
1636 /* Apply output filters. */
1637 ret
= ripng_outgoing_filter (p
, ri
);
1641 /* Changed route only output. */
1642 if (route_type
== ripng_changed_route
&&
1643 (! (rinfo
->flags
& RIPNG_RTF_CHANGED
)))
1646 /* Split horizon. */
1647 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON
)
1649 /* We perform split horizon for RIPng routes. */
1650 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1651 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 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1731 rinfo
->ifindex
== ifp
->ifindex
)
1732 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1735 /* Add RTE to the list */
1736 ripng_rte_add(ripng_rte_list
, p
, rinfo
, NULL
);
1739 /* Process the aggregated RTE entry */
1740 if ((aggregate
= rp
->aggregate
) != NULL
&&
1741 aggregate
->count
> 0 &&
1742 aggregate
->suppress
== 0)
1744 /* If no route-map are applied, the RTE will be these following
1747 p
= (struct prefix_ipv6
*) &rp
->p
;
1748 aggregate
->metric_set
= 0;
1749 aggregate
->metric_out
= aggregate
->metric
;
1750 aggregate
->tag_out
= aggregate
->tag
;
1751 memset(&aggregate
->nexthop_out
, 0, sizeof(aggregate
->nexthop_out
));
1753 /* Apply output filters.*/
1754 ret
= ripng_outgoing_filter (p
, ri
);
1758 /* Interface route-map */
1759 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1762 struct ripng_info newinfo
;
1764 /* let's cast the aggregate structure to ripng_info */
1765 memset (&newinfo
, 0, sizeof (struct ripng_info
));
1766 /* the nexthop is :: */
1767 newinfo
.metric
= aggregate
->metric
;
1768 newinfo
.metric_out
= aggregate
->metric_out
;
1769 newinfo
.tag
= aggregate
->tag
;
1770 newinfo
.tag_out
= aggregate
->tag_out
;
1772 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1773 (struct prefix
*) p
, RMAP_RIPNG
,
1776 if (ret
== RMAP_DENYMATCH
)
1778 if (IS_RIPNG_DEBUG_PACKET
)
1779 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1780 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
1784 aggregate
->metric_out
= newinfo
.metric_out
;
1785 aggregate
->tag_out
= newinfo
.tag_out
;
1786 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop_out
))
1787 aggregate
->nexthop_out
= newinfo
.nexthop_out
;
1790 /* There is no redistribute routemap for the aggregated RTE */
1792 /* Changed route only output. */
1793 /* XXX, vincent, in order to increase time convergence,
1794 * it should be announced if a child has changed.
1796 if (route_type
== ripng_changed_route
)
1799 /* Apply offset-list */
1800 if (aggregate
->metric_out
!= RIPNG_METRIC_INFINITY
)
1801 ripng_offset_list_apply_out (p
, ifp
, &aggregate
->metric_out
);
1803 if (aggregate
->metric_out
> RIPNG_METRIC_INFINITY
)
1804 aggregate
->metric_out
= RIPNG_METRIC_INFINITY
;
1806 /* Add RTE to the list */
1807 ripng_rte_add(ripng_rte_list
, p
, NULL
, aggregate
);
1812 /* Flush the list */
1813 ripng_rte_send(ripng_rte_list
, ifp
, to
);
1814 ripng_rte_free(ripng_rte_list
);
1817 /* Create new RIPng instance and set it to global variable. */
1821 /* ripng should be NULL. */
1822 assert (ripng
== NULL
);
1824 /* Allocaste RIPng instance. */
1825 ripng
= XMALLOC (MTYPE_RIPNG
, sizeof (struct ripng
));
1826 memset (ripng
, 0, 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);
1927 /* Each route type's strings and default preference.
1928 * FIXME: ISIS? What are these distance values? */
1933 const char *str_long
;
1937 { ZEBRA_ROUTE_SYSTEM
, "X", "system", 10},
1938 { ZEBRA_ROUTE_KERNEL
, "K", "kernel", 20},
1939 { ZEBRA_ROUTE_CONNECT
, "C", "connected", 30},
1940 { ZEBRA_ROUTE_STATIC
, "S", "static", 40},
1941 { ZEBRA_ROUTE_RIP
, "R", "rip", 50},
1942 { ZEBRA_ROUTE_RIPNG
, "R", "ripng", 50},
1943 { ZEBRA_ROUTE_OSPF
, "O", "ospf", 60},
1944 { ZEBRA_ROUTE_OSPF6
, "O", "ospf6", 60},
1945 { ZEBRA_ROUTE_BGP
, "B", "bgp", 70},
1948 /* Print out routes update time. */
1950 ripng_vty_out_uptime (struct vty
*vty
, struct ripng_info
*rinfo
)
1952 struct timeval timer_now
;
1956 char timebuf
[TIME_BUF
];
1957 struct thread
*thread
;
1959 gettimeofday (&timer_now
, NULL
);
1961 if ((thread
= rinfo
->t_timeout
) != NULL
)
1963 clock
= thread
->u
.sands
.tv_sec
- timer_now
.tv_sec
;
1964 tm
= gmtime (&clock
);
1965 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1966 vty_out (vty
, "%5s", timebuf
);
1968 else if ((thread
= rinfo
->t_garbage_collect
) != NULL
)
1970 clock
= thread
->u
.sands
.tv_sec
- timer_now
.tv_sec
;
1971 tm
= gmtime (&clock
);
1972 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1973 vty_out (vty
, "%5s", timebuf
);
1978 ripng_route_subtype_print (struct ripng_info
*rinfo
)
1983 if (rinfo
->suppress
)
1986 switch (rinfo
->sub_type
)
1988 case RIPNG_ROUTE_RTE
:
1991 case RIPNG_ROUTE_STATIC
:
1994 case RIPNG_ROUTE_DEFAULT
:
1997 case RIPNG_ROUTE_REDISTRIBUTE
:
2000 case RIPNG_ROUTE_INTERFACE
:
2011 DEFUN (show_ipv6_ripng
,
2012 show_ipv6_ripng_cmd
,
2016 "Show RIPng routes\n")
2018 struct route_node
*rp
;
2019 struct ripng_info
*rinfo
;
2020 struct ripng_aggregate
*aggregate
;
2021 struct prefix_ipv6
*p
;
2027 /* Header of display. */
2028 vty_out (vty
, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2030 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2031 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2032 " Network Next Hop Via Metric Tag Time%s",
2033 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2034 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
2036 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2038 if ((aggregate
= rp
->aggregate
) != NULL
)
2040 p
= (struct prefix_ipv6
*) &rp
->p
;
2043 len
= vty_out (vty
, "R(a) %d/%d %s/%d ",
2044 aggregate
->count
, aggregate
->suppress
,
2045 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
2047 len
= vty_out (vty
, "R(a) %s/%d ",
2048 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
2050 vty_out (vty
, "%s", VTY_NEWLINE
);
2051 vty_out (vty
, "%*s", 18, " ");
2053 vty_out (vty
, "%*s", 28, " ");
2054 vty_out (vty
, "self %2d %3d%s", aggregate
->metric
,
2059 if ((rinfo
= rp
->info
) != NULL
)
2061 p
= (struct prefix_ipv6
*) &rp
->p
;
2064 len
= vty_out (vty
, "%s(%s) 0/%d %s/%d ",
2065 route_info
[rinfo
->type
].str
,
2066 ripng_route_subtype_print(rinfo
),
2068 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
2070 len
= vty_out (vty
, "%s(%s) %s/%d ",
2071 route_info
[rinfo
->type
].str
,
2072 ripng_route_subtype_print(rinfo
),
2073 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
2075 vty_out (vty
, "%s", VTY_NEWLINE
);
2076 vty_out (vty
, "%*s", 18, " ");
2077 len
= vty_out (vty
, "%s", inet6_ntoa (&rinfo
->nexthop
));
2081 len
= vty_out (vty
, "%*s", len
, " ");
2084 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2085 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2087 len
= vty_out (vty
, "%s", ifindex2ifname(rinfo
->ifindex
));
2088 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2090 len
= vty_out (vty
, "kill");
2092 len
= vty_out (vty
, "self");
2096 vty_out (vty
, "%*s", len
, " ");
2098 vty_out (vty
, " %2d %3d ",
2099 rinfo
->metric
, rinfo
->tag
);
2102 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2103 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2105 /* RTE from remote RIP routers */
2106 ripng_vty_out_uptime (vty
, rinfo
);
2107 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2109 /* poisonous reversed routes (gc) */
2110 ripng_vty_out_uptime (vty
, rinfo
);
2113 vty_out (vty
, "%s", VTY_NEWLINE
);
2120 /* Return next event time. */
2122 ripng_next_thread_timer (struct thread
*thread
)
2124 struct timeval timer_now
;
2126 gettimeofday (&timer_now
, NULL
);
2128 return thread
->u
.sands
.tv_sec
- timer_now
.tv_sec
;
2131 DEFUN (show_ipv6_ripng_status
,
2132 show_ipv6_ripng_status_cmd
,
2133 "show ipv6 ripng status",
2136 "Show RIPng routes\n"
2137 "IPv6 routing protocol process parameters and statistics\n")
2139 struct listnode
*node
;
2140 int ripng_network_write (struct vty
*, int);
2141 void ripng_redistribute_write (struct vty
*, int);
2146 vty_out (vty
, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE
);
2147 vty_out (vty
, " Sending updates every %ld seconds with +/-50%%,",
2148 ripng
->update_time
);
2149 vty_out (vty
, " next due in %d seconds%s",
2150 ripng_next_thread_timer (ripng
->t_update
),
2152 vty_out (vty
, " Timeout after %ld seconds,", ripng
->timeout_time
);
2153 vty_out (vty
, " garbage collect after %ld seconds%s", ripng
->garbage_time
,
2156 /* Filtering status show. */
2157 config_show_distribute (vty
);
2159 /* Default metric information. */
2160 vty_out (vty
, " Default redistribution metric is %d%s",
2161 ripng
->default_metric
, VTY_NEWLINE
);
2163 /* Redistribute information. */
2164 vty_out (vty
, " Redistributing:");
2165 ripng_redistribute_write (vty
, 0);
2166 vty_out (vty
, "%s", VTY_NEWLINE
);
2168 vty_out (vty
, " Default version control: send version %d,", ripng
->version
);
2169 vty_out (vty
, " receive version %d %s", ripng
->version
,
2172 vty_out (vty
, " Interface Send Recv%s", VTY_NEWLINE
);
2174 for (node
= listhead (iflist
); node
; node
= nextnode (node
))
2176 struct ripng_interface
*ri
;
2177 struct interface
*ifp
;
2179 ifp
= getdata (node
);
2182 if (ri
->enable_network
|| ri
->enable_interface
)
2185 vty_out (vty
, " %-17s%-3d %-3d%s", ifp
->name
,
2192 vty_out (vty
, " Routing for Networks:%s", VTY_NEWLINE
);
2193 ripng_network_write (vty
, 0);
2195 vty_out (vty
, " Routing Information Sources:%s", VTY_NEWLINE
);
2196 vty_out (vty
, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE
);
2197 ripng_peer_display (vty
);
2202 DEFUN (router_ripng
,
2205 "Enable a routing process\n"
2206 "Make RIPng instance command\n")
2210 vty
->node
= RIPNG_NODE
;
2214 ret
= ripng_create ();
2216 /* Notice to user we couldn't create RIPng. */
2219 zlog_warn ("can't create RIPng");
2227 DEFUN (no_router_ripng
,
2228 no_router_ripng_cmd
,
2231 "Enable a routing process\n"
2232 "Make RIPng instance command\n")
2242 "Static route setup\n"
2243 "Set static RIPng route announcement\n")
2246 struct prefix_ipv6 p
;
2247 struct route_node
*rp
;
2249 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2252 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2255 apply_mask_ipv6 (&p
);
2257 rp
= route_node_get (ripng
->route
, (struct prefix
*) &p
);
2260 vty_out (vty
, "There is already same static route.%s", VTY_NEWLINE
);
2261 route_unlock_node (rp
);
2264 rp
->info
= (void *)1;
2266 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0, NULL
);
2271 DEFUN (no_ripng_route
,
2273 "no route IPV6ADDR",
2275 "Static route setup\n"
2276 "Delete static RIPng route announcement\n")
2279 struct prefix_ipv6 p
;
2280 struct route_node
*rp
;
2282 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2285 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2288 apply_mask_ipv6 (&p
);
2290 rp
= route_node_lookup (ripng
->route
, (struct prefix
*) &p
);
2293 vty_out (vty
, "Can't find static route.%s", VTY_NEWLINE
);
2297 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0);
2298 route_unlock_node (rp
);
2301 route_unlock_node (rp
);
2306 DEFUN (ripng_aggregate_address
,
2307 ripng_aggregate_address_cmd
,
2308 "aggregate-address X:X::X:X/M",
2309 "Set aggregate RIPng route announcement\n"
2310 "Aggregate network\n")
2314 struct route_node
*node
;
2316 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2319 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2323 /* Check aggregate alredy exist or not. */
2324 node
= route_node_get (ripng
->aggregate
, &p
);
2327 vty_out (vty
, "There is already same aggregate route.%s", VTY_NEWLINE
);
2328 route_unlock_node (node
);
2331 node
->info
= (void *)1;
2333 ripng_aggregate_add (&p
);
2338 DEFUN (no_ripng_aggregate_address
,
2339 no_ripng_aggregate_address_cmd
,
2340 "no aggregate-address X:X::X:X/M",
2342 "Delete aggregate RIPng route announcement\n"
2343 "Aggregate network")
2347 struct route_node
*rn
;
2349 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &p
);
2352 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2356 rn
= route_node_lookup (ripng
->aggregate
, &p
);
2359 vty_out (vty
, "Can't find aggregate route.%s", VTY_NEWLINE
);
2362 route_unlock_node (rn
);
2364 route_unlock_node (rn
);
2366 ripng_aggregate_delete (&p
);
2371 DEFUN (ripng_default_metric
,
2372 ripng_default_metric_cmd
,
2373 "default-metric <1-16>",
2374 "Set a metric of redistribute routes\n"
2379 ripng
->default_metric
= atoi (argv
[0]);
2384 DEFUN (no_ripng_default_metric
,
2385 no_ripng_default_metric_cmd
,
2386 "no default-metric",
2388 "Set a metric of redistribute routes\n"
2393 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
2398 ALIAS (no_ripng_default_metric
,
2399 no_ripng_default_metric_val_cmd
,
2400 "no default-metric <1-16>",
2402 "Set a metric of redistribute routes\n"
2406 /* RIPng update timer setup. */
2407 DEFUN (ripng_update_timer
,
2408 ripng_update_timer_cmd
,
2409 "update-timer SECOND",
2410 "Set RIPng update timer in seconds\n"
2413 unsigned long update
;
2414 char *endptr
= NULL
;
2416 update
= strtoul (argv
[0], &endptr
, 10);
2417 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2419 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2423 ripng
->update_time
= update
;
2425 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2429 DEFUN (no_ripng_update_timer
,
2430 no_ripng_update_timer_cmd
,
2431 "no update-timer SECOND",
2433 "Unset RIPng update timer in seconds\n"
2436 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2437 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2441 /* RIPng timeout timer setup. */
2442 DEFUN (ripng_timeout_timer
,
2443 ripng_timeout_timer_cmd
,
2444 "timeout-timer SECOND",
2445 "Set RIPng timeout timer in seconds\n"
2448 unsigned long timeout
;
2449 char *endptr
= NULL
;
2451 timeout
= strtoul (argv
[0], &endptr
, 10);
2452 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2454 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2458 ripng
->timeout_time
= timeout
;
2463 DEFUN (no_ripng_timeout_timer
,
2464 no_ripng_timeout_timer_cmd
,
2465 "no timeout-timer SECOND",
2467 "Unset RIPng timeout timer in seconds\n"
2470 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2474 /* RIPng garbage timer setup. */
2475 DEFUN (ripng_garbage_timer
,
2476 ripng_garbage_timer_cmd
,
2477 "garbage-timer SECOND",
2478 "Set RIPng garbage timer in seconds\n"
2481 unsigned long garbage
;
2482 char *endptr
= NULL
;
2484 garbage
= strtoul (argv
[0], &endptr
, 10);
2485 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2487 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2491 ripng
->garbage_time
= garbage
;
2496 DEFUN (no_ripng_garbage_timer
,
2497 no_ripng_garbage_timer_cmd
,
2498 "no garbage-timer SECOND",
2500 "Unset RIPng garbage timer in seconds\n"
2503 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2508 DEFUN (ripng_timers
,
2510 "timers basic <0-65535> <0-65535> <0-65535>",
2511 "RIPng timers setup\n"
2513 "Routing table update timer value in second. Default is 30.\n"
2514 "Routing information timeout timer. Default is 180.\n"
2515 "Garbage collection timer. Default is 120.\n")
2517 unsigned long update
;
2518 unsigned long timeout
;
2519 unsigned long garbage
;
2520 char *endptr
= NULL
;
2522 update
= strtoul (argv
[0], &endptr
, 10);
2523 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2525 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2529 timeout
= strtoul (argv
[1], &endptr
, 10);
2530 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2532 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2536 garbage
= strtoul (argv
[2], &endptr
, 10);
2537 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2539 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2543 /* Set each timer value. */
2544 ripng
->update_time
= update
;
2545 ripng
->timeout_time
= timeout
;
2546 ripng
->garbage_time
= garbage
;
2548 /* Reset update timer thread. */
2549 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2554 DEFUN (no_ripng_timers
,
2555 no_ripng_timers_cmd
,
2558 "RIPng timers setup\n"
2561 /* Set each timer value to the default. */
2562 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2563 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2564 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2566 /* Reset update timer thread. */
2567 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2572 ALIAS (no_ripng_timers
,
2573 no_ripng_timers_val_cmd
,
2574 "no timers basic <0-65535> <0-65535> <0-65535>",
2576 "RIPng timers setup\n"
2578 "Routing table update timer value in second. Default is 30.\n"
2579 "Routing information timeout timer. Default is 180.\n"
2580 "Garbage collection timer. Default is 120.\n")
2582 DEFUN (show_ipv6_protocols
, show_ipv6_protocols_cmd
,
2583 "show ipv6 protocols",
2586 "Routing protocol information")
2591 vty_out (vty
, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE
);
2593 vty_out (vty
, "Sending updates every %ld seconds, next due in %d seconds%s",
2594 ripng
->update_time
, 0,
2597 vty_out (vty
, "Timerout after %ld seconds, garbage correct %ld%s",
2598 ripng
->timeout_time
,
2599 ripng
->garbage_time
,
2602 vty_out (vty
, "Outgoing update filter list for all interfaces is not set");
2603 vty_out (vty
, "Incoming update filter list for all interfaces is not set");
2608 /* Please be carefull to use this command. */
2609 DEFUN (ripng_default_information_originate
,
2610 ripng_default_information_originate_cmd
,
2611 "default-information originate",
2612 "Default route information\n"
2613 "Distribute default route\n")
2615 struct prefix_ipv6 p
;
2617 if (! ripng
->default_information
) {
2618 ripng
->default_information
= 1;
2620 str2prefix_ipv6 ("::/0", &p
);
2621 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0, NULL
);
2627 DEFUN (no_ripng_default_information_originate
,
2628 no_ripng_default_information_originate_cmd
,
2629 "no default-information originate",
2631 "Default route information\n"
2632 "Distribute default route\n")
2634 struct prefix_ipv6 p
;
2636 if (ripng
->default_information
) {
2637 ripng
->default_information
= 0;
2639 str2prefix_ipv6 ("::/0", &p
);
2640 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0);
2646 /* RIPng configuration write function. */
2648 ripng_config_write (struct vty
*vty
)
2650 int ripng_network_write (struct vty
*, int);
2651 void ripng_redistribute_write (struct vty
*, int);
2653 struct route_node
*rp
;
2659 vty_out (vty
, "router ripng%s", VTY_NEWLINE
);
2661 if (ripng
->default_information
)
2662 vty_out (vty
, " default-information originate%s", VTY_NEWLINE
);
2664 ripng_network_write (vty
, 1);
2666 /* RIPng default metric configuration */
2667 if (ripng
->default_metric
!= RIPNG_DEFAULT_METRIC_DEFAULT
)
2668 vty_out (vty
, " default-metric %d%s",
2669 ripng
->default_metric
, VTY_NEWLINE
);
2671 ripng_redistribute_write (vty
, 1);
2673 /* RIP offset-list configuration. */
2674 config_write_ripng_offset_list (vty
);
2676 /* RIPng aggregate routes. */
2677 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2678 if (rp
->info
!= NULL
)
2679 vty_out (vty
, " aggregate-address %s/%d%s",
2680 inet6_ntoa (&rp
->p
.u
.prefix6
),
2685 /* RIPng static routes. */
2686 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2687 if (rp
->info
!= NULL
)
2688 vty_out (vty
, " route %s/%d%s", inet6_ntoa (&rp
->p
.u
.prefix6
),
2692 /* RIPng timers configuration. */
2693 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
||
2694 ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
||
2695 ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2697 vty_out (vty
, " timers basic %ld %ld %ld%s",
2699 ripng
->timeout_time
,
2700 ripng
->garbage_time
,
2704 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
)
2705 vty_out (vty
, " update-timer %d%s", ripng
->update_time
,
2707 if (ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
)
2708 vty_out (vty
, " timeout-timer %d%s", ripng
->timeout_time
,
2710 if (ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2711 vty_out (vty
, " garbage-timer %d%s", ripng
->garbage_time
,
2715 write
+= config_write_distribute (vty
);
2717 write
+= config_write_if_rmap (vty
);
2724 /* RIPng node structure. */
2725 struct cmd_node cmd_ripng_node
=
2728 "%s(config-router)# ",
2733 ripng_distribute_update (struct distribute
*dist
)
2735 struct interface
*ifp
;
2736 struct ripng_interface
*ri
;
2737 struct access_list
*alist
;
2738 struct prefix_list
*plist
;
2743 ifp
= if_lookup_by_name (dist
->ifname
);
2749 if (dist
->list
[DISTRIBUTE_IN
])
2751 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
2753 ri
->list
[RIPNG_FILTER_IN
] = alist
;
2755 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2758 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2760 if (dist
->list
[DISTRIBUTE_OUT
])
2762 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
2764 ri
->list
[RIPNG_FILTER_OUT
] = alist
;
2766 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2769 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2771 if (dist
->prefix
[DISTRIBUTE_IN
])
2773 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
2775 ri
->prefix
[RIPNG_FILTER_IN
] = plist
;
2777 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2780 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2782 if (dist
->prefix
[DISTRIBUTE_OUT
])
2784 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
2786 ri
->prefix
[RIPNG_FILTER_OUT
] = plist
;
2788 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2791 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2795 ripng_distribute_update_interface (struct interface
*ifp
)
2797 struct distribute
*dist
;
2799 dist
= distribute_lookup (ifp
->name
);
2801 ripng_distribute_update (dist
);
2804 /* Update all interface's distribute list. */
2806 ripng_distribute_update_all (struct prefix_list
*notused
)
2808 struct interface
*ifp
;
2809 struct listnode
*node
;
2811 for (node
= listhead (iflist
); node
; nextnode (node
))
2813 ifp
= getdata (node
);
2814 ripng_distribute_update_interface (ifp
);
2819 ripng_distribute_update_all_wrapper (struct access_list
*notused
)
2821 ripng_distribute_update_all(NULL
);
2824 /* delete all the added ripng routes. */
2829 struct route_node
*rp
;
2830 struct ripng_info
*rinfo
;
2833 /* Clear RIPng routes */
2834 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
)) {
2835 if ((rinfo
= rp
->info
) != NULL
) {
2836 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2837 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2838 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
,
2839 &rinfo
->nexthop
, rinfo
->metric
);
2841 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
2842 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
2845 route_unlock_node (rp
);
2847 ripng_info_free(rinfo
);
2851 /* Cancel the RIPng timers */
2852 RIPNG_TIMER_OFF (ripng
->t_update
);
2853 RIPNG_TIMER_OFF (ripng
->t_triggered_update
);
2854 RIPNG_TIMER_OFF (ripng
->t_triggered_interval
);
2856 /* Cancel the read thread */
2857 if (ripng
->t_read
) {
2858 thread_cancel (ripng
->t_read
);
2859 ripng
->t_read
= NULL
;
2862 /* Close the RIPng socket */
2863 if (ripng
->sock
>= 0) {
2868 /* Static RIPng route configuration. */
2869 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2872 route_unlock_node (rp
);
2875 /* RIPng aggregated prefixes */
2876 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2879 route_unlock_node (rp
);
2882 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2883 if (ripng
->route_map
[i
].name
)
2884 free (ripng
->route_map
[i
].name
);
2886 XFREE (MTYPE_ROUTE_TABLE
, ripng
->table
);
2887 XFREE (MTYPE_ROUTE_TABLE
, ripng
->route
);
2888 XFREE (MTYPE_ROUTE_TABLE
, ripng
->aggregate
);
2890 XFREE (MTYPE_RIPNG
, ripng
);
2894 ripng_clean_network();
2895 ripng_passive_interface_clean ();
2896 ripng_offset_clean ();
2897 ripng_interface_clean ();
2898 ripng_redistribute_clean ();
2901 /* Reset all values to the default settings. */
2905 /* Call ripd related reset functions. */
2906 ripng_debug_reset ();
2907 ripng_route_map_reset ();
2909 /* Call library reset functions. */
2911 access_list_reset ();
2912 prefix_list_reset ();
2914 distribute_list_reset ();
2916 ripng_interface_reset ();
2918 ripng_zclient_reset ();
2922 ripng_if_rmap_update (struct if_rmap
*if_rmap
)
2924 struct interface
*ifp
;
2925 struct ripng_interface
*ri
;
2926 struct route_map
*rmap
;
2928 ifp
= if_lookup_by_name (if_rmap
->ifname
);
2934 if (if_rmap
->routemap
[IF_RMAP_IN
])
2936 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_IN
]);
2938 ri
->routemap
[IF_RMAP_IN
] = rmap
;
2940 ri
->routemap
[IF_RMAP_IN
] = NULL
;
2943 ri
->routemap
[RIPNG_FILTER_IN
] = NULL
;
2945 if (if_rmap
->routemap
[IF_RMAP_OUT
])
2947 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_OUT
]);
2949 ri
->routemap
[IF_RMAP_OUT
] = rmap
;
2951 ri
->routemap
[IF_RMAP_OUT
] = NULL
;
2954 ri
->routemap
[RIPNG_FILTER_OUT
] = NULL
;
2958 ripng_if_rmap_update_interface (struct interface
*ifp
)
2960 struct if_rmap
*if_rmap
;
2962 if_rmap
= if_rmap_lookup (ifp
->name
);
2964 ripng_if_rmap_update (if_rmap
);
2968 ripng_routemap_update_redistribute (void)
2974 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2976 if (ripng
->route_map
[i
].name
)
2977 ripng
->route_map
[i
].map
=
2978 route_map_lookup_by_name (ripng
->route_map
[i
].name
);
2984 ripng_routemap_update (const char *unused
)
2986 struct interface
*ifp
;
2987 struct listnode
*node
;
2989 for (node
= listhead (iflist
); node
; nextnode (node
))
2991 ifp
= getdata (node
);
2992 ripng_if_rmap_update_interface (ifp
);
2995 ripng_routemap_update_redistribute ();
2998 /* Initialize ripng structure and set commands. */
3003 srand (time (NULL
));
3005 /* Install RIPNG_NODE. */
3006 install_node (&cmd_ripng_node
, ripng_config_write
);
3008 /* Install ripng commands. */
3009 install_element (VIEW_NODE
, &show_ipv6_ripng_cmd
);
3010 install_element (VIEW_NODE
, &show_ipv6_ripng_status_cmd
);
3012 install_element (ENABLE_NODE
, &show_ipv6_ripng_cmd
);
3013 install_element (ENABLE_NODE
, &show_ipv6_ripng_status_cmd
);
3015 install_element (CONFIG_NODE
, &router_ripng_cmd
);
3016 install_element (CONFIG_NODE
, &no_router_ripng_cmd
);
3018 install_default (RIPNG_NODE
);
3019 install_element (RIPNG_NODE
, &ripng_route_cmd
);
3020 install_element (RIPNG_NODE
, &no_ripng_route_cmd
);
3021 install_element (RIPNG_NODE
, &ripng_aggregate_address_cmd
);
3022 install_element (RIPNG_NODE
, &no_ripng_aggregate_address_cmd
);
3024 install_element (RIPNG_NODE
, &ripng_default_metric_cmd
);
3025 install_element (RIPNG_NODE
, &no_ripng_default_metric_cmd
);
3026 install_element (RIPNG_NODE
, &no_ripng_default_metric_val_cmd
);
3028 install_element (RIPNG_NODE
, &ripng_timers_cmd
);
3029 install_element (RIPNG_NODE
, &no_ripng_timers_cmd
);
3030 install_element (RIPNG_NODE
, &no_ripng_timers_val_cmd
);
3032 install_element (RIPNG_NODE
, &ripng_update_timer_cmd
);
3033 install_element (RIPNG_NODE
, &no_ripng_update_timer_cmd
);
3034 install_element (RIPNG_NODE
, &ripng_timeout_timer_cmd
);
3035 install_element (RIPNG_NODE
, &no_ripng_timeout_timer_cmd
);
3036 install_element (RIPNG_NODE
, &ripng_garbage_timer_cmd
);
3037 install_element (RIPNG_NODE
, &no_ripng_garbage_timer_cmd
);
3040 install_element (RIPNG_NODE
, &ripng_default_information_originate_cmd
);
3041 install_element (RIPNG_NODE
, &no_ripng_default_information_originate_cmd
);
3044 ripng_debug_init ();
3046 /* Access list install. */
3047 access_list_init ();
3048 access_list_add_hook (ripng_distribute_update_all_wrapper
);
3049 access_list_delete_hook (ripng_distribute_update_all_wrapper
);
3051 /* Prefix list initialize.*/
3052 prefix_list_init ();
3053 prefix_list_add_hook (ripng_distribute_update_all
);
3054 prefix_list_delete_hook (ripng_distribute_update_all
);
3056 /* Distribute list install. */
3057 distribute_list_init (RIPNG_NODE
);
3058 distribute_list_add_hook (ripng_distribute_update
);
3059 distribute_list_delete_hook (ripng_distribute_update
);
3061 /* Route-map for interface. */
3062 ripng_route_map_init ();
3063 ripng_offset_init ();
3065 route_map_add_hook (ripng_routemap_update
);
3066 route_map_delete_hook (ripng_routemap_update
);
3068 if_rmap_init (RIPNG_NODE
);
3069 if_rmap_hook_add (ripng_if_rmap_update
);
3070 if_rmap_hook_delete (ripng_if_rmap_update
);