2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
34 #include "distribute.h"
40 #include "ripngd/ripngd.h"
41 #include "ripngd/ripng_route.h"
42 #include "ripngd/ripng_debug.h"
43 #include "ripngd/ripng_nexthop.h"
45 /* RIPng structure which includes many parameters related to RIPng
46 protocol. If ripng couldn't active or ripng doesn't configured,
47 ripng->fd must be negative value. */
48 struct ripng
*ripng
= NULL
;
56 extern struct zebra_privs_t ripngd_privs
;
60 ripng_output_process (struct interface
*, struct sockaddr_in6
*, int);
63 ripng_triggered_update (struct thread
*);
65 /* RIPng next hop specification. */
68 enum ripng_nexthop_type
73 struct in6_addr address
;
77 ripng_route_rte (struct ripng_info
*rinfo
)
79 return (rinfo
->type
== ZEBRA_ROUTE_RIPNG
&& rinfo
->sub_type
== RIPNG_ROUTE_RTE
);
82 /* Allocate new ripng information. */
86 struct ripng_info
*new;
88 new = XCALLOC (MTYPE_RIPNG_ROUTE
, sizeof (struct ripng_info
));
92 /* Free ripng information. */
94 ripng_info_free (struct ripng_info
*rinfo
)
96 XFREE (MTYPE_RIPNG_ROUTE
, rinfo
);
99 /* Create ripng socket. */
101 ripng_make_socket (void)
105 struct sockaddr_in6 ripaddr
;
107 sock
= socket (AF_INET6
, SOCK_DGRAM
, 0);
110 zlog (NULL
, LOG_ERR
, "Can't make ripng socket");
114 ret
= setsockopt_so_recvbuf (sock
, 8096);
117 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
120 #ifdef IPTOS_PREC_INTERNETCONTROL
121 ret
= setsockopt_ipv6_tclass (sock
, IPTOS_PREC_INTERNETCONTROL
);
125 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
128 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
131 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
135 memset (&ripaddr
, 0, sizeof (ripaddr
));
136 ripaddr
.sin6_family
= AF_INET6
;
138 ripaddr
.sin6_len
= sizeof (struct sockaddr_in6
);
139 #endif /* SIN6_LEN */
140 ripaddr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
142 if (ripngd_privs
.change (ZPRIVS_RAISE
))
143 zlog_err ("ripng_make_socket: could not raise privs");
145 ret
= bind (sock
, (struct sockaddr
*) &ripaddr
, sizeof (ripaddr
));
148 zlog (NULL
, LOG_ERR
, "Can't bind ripng socket: %s.", safe_strerror (errno
));
149 if (ripngd_privs
.change (ZPRIVS_LOWER
))
150 zlog_err ("ripng_make_socket: could not lower privs");
153 if (ripngd_privs
.change (ZPRIVS_LOWER
))
154 zlog_err ("ripng_make_socket: could not lower privs");
158 /* Send RIPng packet. */
160 ripng_send_packet (caddr_t buf
, int bufsize
, struct sockaddr_in6
*to
,
161 struct interface
*ifp
)
166 struct cmsghdr
*cmsgptr
;
168 struct in6_pktinfo
*pkt
;
169 struct sockaddr_in6 addr
;
171 if (IS_RIPNG_DEBUG_SEND
) {
173 zlog_debug ("send to %s", inet6_ntoa (to
->sin6_addr
));
174 zlog_debug (" send interface %s", ifp
->name
);
175 zlog_debug (" send packet size %d", bufsize
);
178 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
179 addr
.sin6_family
= AF_INET6
;
181 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
182 #endif /* SIN6_LEN */
183 addr
.sin6_flowinfo
= htonl (RIPNG_PRIORITY_DEFAULT
);
185 /* When destination is specified. */
188 addr
.sin6_addr
= to
->sin6_addr
;
189 addr
.sin6_port
= to
->sin6_port
;
193 inet_pton(AF_INET6
, RIPNG_GROUP
, &addr
.sin6_addr
);
194 addr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
197 msg
.msg_name
= (void *) &addr
;
198 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
201 msg
.msg_control
= (void *) adata
;
202 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
205 iov
.iov_len
= bufsize
;
207 cmsgptr
= (struct cmsghdr
*)adata
;
208 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof (struct in6_pktinfo
));
209 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
210 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
212 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
213 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
214 pkt
->ipi6_ifindex
= ifp
->ifindex
;
216 ret
= sendmsg (ripng
->sock
, &msg
, 0);
220 zlog_err ("RIPng send fail on %s to %s: %s", ifp
->name
,
221 inet6_ntoa (to
->sin6_addr
), safe_strerror (errno
));
223 zlog_err ("RIPng send fail on %s: %s", ifp
->name
, safe_strerror (errno
));
229 /* Receive UDP RIPng packet from socket. */
231 ripng_recv_packet (int sock
, u_char
*buf
, int bufsize
,
232 struct sockaddr_in6
*from
, unsigned int *ifindex
,
238 struct cmsghdr
*cmsgptr
;
241 /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this
242 point I can't determine size of cmsghdr */
245 /* Fill in message and iovec. */
246 msg
.msg_name
= (void *) from
;
247 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
250 msg
.msg_control
= (void *) adata
;
251 msg
.msg_controllen
= sizeof adata
;
253 iov
.iov_len
= bufsize
;
255 /* If recvmsg fail return minus value. */
256 ret
= recvmsg (sock
, &msg
, 0);
260 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
261 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
263 /* I want interface index which this packet comes from. */
264 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
265 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
267 struct in6_pktinfo
*ptr
;
269 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
270 *ifindex
= ptr
->ipi6_ifindex
;
271 dst
= ptr
->ipi6_addr
;
274 zlog_warn ("Interface index returned by IPV6_PKTINFO is zero");
277 /* Incoming packet's multicast hop limit. */
278 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
279 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
281 int *phoplimit
= (int *) CMSG_DATA (cmsgptr
);
282 *hoplimit
= *phoplimit
;
286 /* Hoplimit check shold be done when destination address is
287 multicast address. */
288 if (! IN6_IS_ADDR_MULTICAST (&dst
))
294 /* Dump rip packet */
296 ripng_packet_dump (struct ripng_packet
*packet
, int size
, const char *sndrcv
)
300 const char *command_str
;
302 /* Set command string. */
303 if (packet
->command
== RIPNG_REQUEST
)
304 command_str
= "request";
305 else if (packet
->command
== RIPNG_RESPONSE
)
306 command_str
= "response";
308 command_str
= "unknown";
310 /* Dump packet header. */
311 zlog_debug ("%s %s version %d packet size %d",
312 sndrcv
, command_str
, packet
->version
, size
);
314 /* Dump each routing table entry. */
317 for (lim
= (caddr_t
) packet
+ size
; (caddr_t
) rte
< lim
; rte
++)
319 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
320 zlog_debug (" nexthop %s/%d", inet6_ntoa (rte
->addr
), rte
->prefixlen
);
322 zlog_debug (" %s/%d metric %d tag %d",
323 inet6_ntoa (rte
->addr
), rte
->prefixlen
,
324 rte
->metric
, ntohs (rte
->tag
));
328 /* RIPng next hop address RTE (Route Table Entry). */
330 ripng_nexthop_rte (struct rte
*rte
,
331 struct sockaddr_in6
*from
,
332 struct ripng_nexthop
*nexthop
)
334 char buf
[INET6_BUFSIZ
];
336 /* Logging before checking RTE. */
337 if (IS_RIPNG_DEBUG_RECV
)
338 zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d",
339 inet6_ntoa (rte
->addr
), ntohs (rte
->tag
), rte
->prefixlen
);
341 /* RFC2080 2.1.1 Next Hop:
342 The route tag and prefix length in the next hop RTE must be
343 set to zero on sending and ignored on receiption. */
344 if (ntohs (rte
->tag
) != 0)
345 zlog_warn ("RIPng nexthop RTE with non zero tag value %d from %s",
346 ntohs (rte
->tag
), inet6_ntoa (from
->sin6_addr
));
348 if (rte
->prefixlen
!= 0)
349 zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
350 rte
->prefixlen
, inet6_ntoa (from
->sin6_addr
));
352 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
353 next hop RTE indicates that the next hop address should be the
354 originator of the RIPng advertisement. An address specified as a
355 next hop must be a link-local address. */
356 if (IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
))
358 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
359 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
363 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
365 nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
366 IPV6_ADDR_COPY (&nexthop
->address
, &rte
->addr
);
370 /* The purpose of the next hop RTE is to eliminate packets being
371 routed through extra hops in the system. It is particularly useful
372 when RIPng is not being run on all of the routers on a network.
373 Note that next hop RTE is "advisory". That is, if the provided
374 information is ignored, a possibly sub-optimal, but absolutely
375 valid, route may be taken. If the received next hop address is not
376 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
377 zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s",
378 inet6_ntoa (rte
->addr
),
379 inet_ntop (AF_INET6
, &from
->sin6_addr
, buf
, INET6_BUFSIZ
));
381 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
382 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
387 /* If ifp has same link-local address then return 1. */
389 ripng_lladdr_check (struct interface
*ifp
, struct in6_addr
*addr
)
391 struct listnode
*node
;
392 struct connected
*connected
;
395 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, connected
))
397 p
= connected
->address
;
399 if (p
->family
== AF_INET6
&&
400 IN6_IS_ADDR_LINKLOCAL (&p
->u
.prefix6
) &&
401 IN6_ARE_ADDR_EQUAL (&p
->u
.prefix6
, addr
))
407 /* RIPng route garbage collect timer. */
409 ripng_garbage_collect (struct thread
*t
)
411 struct ripng_info
*rinfo
;
412 struct route_node
*rp
;
414 rinfo
= THREAD_ARG (t
);
415 rinfo
->t_garbage_collect
= NULL
;
417 /* Off timeout timer. */
418 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
420 /* Get route_node pointer. */
423 /* Unlock route_node. */
425 route_unlock_node (rp
);
427 /* Free RIPng routing information. */
428 ripng_info_free (rinfo
);
433 /* Timeout RIPng routes. */
435 ripng_timeout (struct thread
*t
)
437 struct ripng_info
*rinfo
;
438 struct route_node
*rp
;
440 rinfo
= THREAD_ARG (t
);
441 rinfo
->t_timeout
= NULL
;
443 /* Get route_node pointer. */
446 /* - The garbage-collection timer is set for 120 seconds. */
447 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
, ripng_garbage_collect
,
448 ripng
->garbage_time
);
450 /* Delete this route from the kernel. */
451 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
453 /* - The metric for the route is set to 16 (infinity). This causes
454 the route to be removed from service. */
455 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
456 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
458 /* Aggregate count decrement. */
459 ripng_aggregate_decrement (rp
, rinfo
);
461 /* - The route change flag is to indicate that this entry has been
463 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
465 /* - The output process is signalled to trigger a response. */
466 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
472 ripng_timeout_update (struct ripng_info
*rinfo
)
474 if (rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
476 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
477 RIPNG_TIMER_ON (rinfo
->t_timeout
, ripng_timeout
, ripng
->timeout_time
);
482 ripng_incoming_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
484 struct distribute
*dist
;
485 struct access_list
*alist
;
486 struct prefix_list
*plist
;
488 /* Input distribute-list filtering. */
489 if (ri
->list
[RIPNG_FILTER_IN
])
491 if (access_list_apply (ri
->list
[RIPNG_FILTER_IN
],
492 (struct prefix
*) p
) == FILTER_DENY
)
494 if (IS_RIPNG_DEBUG_PACKET
)
495 zlog_debug ("%s/%d filtered by distribute in",
496 inet6_ntoa (p
->prefix
), p
->prefixlen
);
500 if (ri
->prefix
[RIPNG_FILTER_IN
])
502 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_IN
],
503 (struct prefix
*) p
) == PREFIX_DENY
)
505 if (IS_RIPNG_DEBUG_PACKET
)
506 zlog_debug ("%s/%d filtered by prefix-list in",
507 inet6_ntoa (p
->prefix
), p
->prefixlen
);
512 /* All interface filter check. */
513 dist
= distribute_lookup (NULL
);
516 if (dist
->list
[DISTRIBUTE_IN
])
518 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
522 if (access_list_apply (alist
,
523 (struct prefix
*) p
) == FILTER_DENY
)
525 if (IS_RIPNG_DEBUG_PACKET
)
526 zlog_debug ("%s/%d filtered by distribute in",
527 inet6_ntoa (p
->prefix
), p
->prefixlen
);
532 if (dist
->prefix
[DISTRIBUTE_IN
])
534 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
538 if (prefix_list_apply (plist
,
539 (struct prefix
*) p
) == PREFIX_DENY
)
541 if (IS_RIPNG_DEBUG_PACKET
)
542 zlog_debug ("%s/%d filtered by prefix-list in",
543 inet6_ntoa (p
->prefix
), p
->prefixlen
);
553 ripng_outgoing_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
555 struct distribute
*dist
;
556 struct access_list
*alist
;
557 struct prefix_list
*plist
;
559 if (ri
->list
[RIPNG_FILTER_OUT
])
561 if (access_list_apply (ri
->list
[RIPNG_FILTER_OUT
],
562 (struct prefix
*) p
) == FILTER_DENY
)
564 if (IS_RIPNG_DEBUG_PACKET
)
565 zlog_debug ("%s/%d is filtered by distribute out",
566 inet6_ntoa (p
->prefix
), p
->prefixlen
);
570 if (ri
->prefix
[RIPNG_FILTER_OUT
])
572 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_OUT
],
573 (struct prefix
*) p
) == PREFIX_DENY
)
575 if (IS_RIPNG_DEBUG_PACKET
)
576 zlog_debug ("%s/%d is filtered by prefix-list out",
577 inet6_ntoa (p
->prefix
), p
->prefixlen
);
582 /* All interface filter check. */
583 dist
= distribute_lookup (NULL
);
586 if (dist
->list
[DISTRIBUTE_OUT
])
588 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
592 if (access_list_apply (alist
,
593 (struct prefix
*) p
) == FILTER_DENY
)
595 if (IS_RIPNG_DEBUG_PACKET
)
596 zlog_debug ("%s/%d filtered by distribute out",
597 inet6_ntoa (p
->prefix
), p
->prefixlen
);
602 if (dist
->prefix
[DISTRIBUTE_OUT
])
604 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
608 if (prefix_list_apply (plist
,
609 (struct prefix
*) p
) == PREFIX_DENY
)
611 if (IS_RIPNG_DEBUG_PACKET
)
612 zlog_debug ("%s/%d filtered by prefix-list out",
613 inet6_ntoa (p
->prefix
), p
->prefixlen
);
622 /* Process RIPng route according to RFC2080. */
624 ripng_route_process (struct rte
*rte
, struct sockaddr_in6
*from
,
625 struct ripng_nexthop
*ripng_nexthop
,
626 struct interface
*ifp
)
629 struct prefix_ipv6 p
;
630 struct route_node
*rp
;
631 struct ripng_info
*rinfo
;
632 struct ripng_interface
*ri
;
633 struct in6_addr
*nexthop
;
637 /* Make prefix structure. */
638 memset (&p
, 0, sizeof (struct prefix_ipv6
));
640 /* p.prefix = rte->addr; */
641 IPV6_ADDR_COPY (&p
.prefix
, &rte
->addr
);
642 p
.prefixlen
= rte
->prefixlen
;
644 /* Make sure mask is applied. */
645 /* XXX We have to check the prefix is valid or not before call
647 apply_mask_ipv6 (&p
);
649 /* Apply input filters. */
652 ret
= ripng_incoming_filter (&p
, ri
);
657 if (ri
->routemap
[RIPNG_FILTER_IN
])
660 struct ripng_info newinfo
;
662 memset (&newinfo
, 0, sizeof (struct ripng_info
));
663 newinfo
.type
= ZEBRA_ROUTE_RIPNG
;
664 newinfo
.sub_type
= RIPNG_ROUTE_RTE
;
665 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
666 newinfo
.nexthop
= ripng_nexthop
->address
;
668 newinfo
.nexthop
= from
->sin6_addr
;
669 newinfo
.from
= from
->sin6_addr
;
670 newinfo
.ifindex
= ifp
->ifindex
;
671 newinfo
.metric
= rte
->metric
;
672 newinfo
.metric_out
= rte
->metric
; /* XXX */
673 newinfo
.tag
= ntohs(rte
->tag
); /* XXX */
675 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_IN
],
676 (struct prefix
*)&p
, RMAP_RIPNG
, &newinfo
);
678 if (ret
== RMAP_DENYMATCH
)
680 if (IS_RIPNG_DEBUG_PACKET
)
681 zlog_debug ("RIPng %s/%d is filtered by route-map in",
682 inet6_ntoa (p
.prefix
), p
.prefixlen
);
686 /* Get back the object */
687 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
) {
688 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &ripng_nexthop
->address
) ) {
689 /* the nexthop get changed by the routemap */
690 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
))
691 ripng_nexthop
->address
= newinfo
.nexthop
;
693 ripng_nexthop
->address
= in6addr_any
;
696 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &from
->sin6_addr
) ) {
697 /* the nexthop get changed by the routemap */
698 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
)) {
699 ripng_nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
700 ripng_nexthop
->address
= newinfo
.nexthop
;
704 rte
->tag
= htons(newinfo
.tag_out
); /* XXX */
705 rte
->metric
= newinfo
.metric_out
; /* XXX: the routemap uses the metric_out field */
708 /* Once the entry has been validated, update the metric by
709 * adding the cost of the network on wich the message
710 * arrived. If the result is greater than infinity, use infinity
711 * (RFC2453 Sec. 3.9.2)
714 /* Zebra ripngd can handle offset-list in. */
715 ret
= ripng_offset_list_apply_in (&p
, ifp
, &rte
->metric
);
717 /* If offset-list does not modify the metric use interface's
720 rte
->metric
+= ifp
->metric
? ifp
->metric
: 1;
722 if (rte
->metric
> RIPNG_METRIC_INFINITY
)
723 rte
->metric
= RIPNG_METRIC_INFINITY
;
725 /* Set nexthop pointer. */
726 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
727 nexthop
= &ripng_nexthop
->address
;
729 nexthop
= &from
->sin6_addr
;
731 /* Lookup RIPng routing table. */
732 rp
= route_node_get (ripng
->table
, (struct prefix
*) &p
);
738 /* Redistributed route check. */
739 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
740 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
743 /* Local static route. */
744 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
745 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
746 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
))
747 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
751 if (rp
->info
== NULL
)
753 /* Now, check to see whether there is already an explicit route
754 for the destination prefix. If there is no such route, add
755 this route to the routing table, unless the metric is
756 infinity (there is no point in adding a route which
758 if (rte
->metric
!= RIPNG_METRIC_INFINITY
)
760 rinfo
= ripng_info_new ();
762 /* - Setting the destination prefix and length to those in
767 /* - Setting the metric to the newly calculated metric (as
769 rinfo
->metric
= rte
->metric
;
770 rinfo
->tag
= ntohs (rte
->tag
);
772 /* - Set the next hop address to be the address of the router
773 from which the datagram came or the next hop address
774 specified by a next hop RTE. */
775 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
776 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
777 rinfo
->ifindex
= ifp
->ifindex
;
779 /* - Initialize the timeout for the route. If the
780 garbage-collection timer is running for this route, stop it. */
781 ripng_timeout_update (rinfo
);
783 /* - Set the route change flag. */
784 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
786 /* - Signal the output process to trigger an update (see section
788 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
790 /* Finally, route goes into the kernel. */
791 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
792 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
794 ripng_zebra_ipv6_add (&p
, &rinfo
->nexthop
, rinfo
->ifindex
,
796 rinfo
->flags
|= RIPNG_RTF_FIB
;
798 /* Aggregate check. */
799 ripng_aggregate_increment (rp
, rinfo
);
806 /* If there is an existing route, compare the next hop address
807 to the address of the router from which the datagram came.
808 If this datagram is from the same router as the existing
809 route, reinitialize the timeout. */
810 same
= (IN6_ARE_ADDR_EQUAL (&rinfo
->from
, &from
->sin6_addr
)
811 && (rinfo
->ifindex
== ifp
->ifindex
));
814 ripng_timeout_update (rinfo
);
816 /* Next, compare the metrics. If the datagram is from the same
817 router as the existing route, and the new metric is different
818 than the old one; or, if the new metric is lower than the old
819 one; do the following actions: */
820 if ((same
&& rinfo
->metric
!= rte
->metric
) ||
821 rte
->metric
< rinfo
->metric
)
823 /* - Adopt the route from the datagram. That is, put the
824 new metric in, and adjust the next hop address (if
826 oldmetric
= rinfo
->metric
;
827 rinfo
->metric
= rte
->metric
;
828 rinfo
->tag
= ntohs (rte
->tag
);
829 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
830 rinfo
->ifindex
= ifp
->ifindex
;
832 /* Should a new route to this network be established
833 while the garbage-collection timer is running, the
834 new route will replace the one that is about to be
835 deleted. In this case the garbage-collection timer
838 if (oldmetric
== RIPNG_METRIC_INFINITY
&&
839 rinfo
->metric
< RIPNG_METRIC_INFINITY
)
841 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
842 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
844 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
846 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
847 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
849 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
, rinfo
->metric
);
850 rinfo
->flags
|= RIPNG_RTF_FIB
;
852 /* The aggregation counter needs to be updated because
853 the prefixes, which are into the gc, have been
854 removed from the aggregator (see ripng_timout). */
855 ripng_aggregate_increment (rp
, rinfo
);
858 /* Update nexthop and/or metric value. */
859 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
861 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
862 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
, rinfo
->metric
);
863 rinfo
->flags
|= RIPNG_RTF_FIB
;
865 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
866 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
869 /* - Set the route change flag and signal the output process
870 to trigger an update. */
871 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
872 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
874 /* - If the new metric is infinity, start the deletion
875 process (described above); */
876 if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
878 /* If the new metric is infinity, the deletion process
879 begins for the route, which is no longer used for
880 routing packets. Note that the deletion process is
881 started only when the metric is first set to
882 infinity. If the metric was already infinity, then a
883 new deletion process is not started. */
884 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
886 /* - The garbage-collection timer is set for 120 seconds. */
887 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
888 ripng_garbage_collect
, ripng
->garbage_time
);
889 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
891 /* - The metric for the route is set to 16
892 (infinity). This causes the route to be removed
894 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
895 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
897 /* Aggregate count decrement. */
898 ripng_aggregate_decrement (rp
, rinfo
);
900 /* - The route change flag is to indicate that this
901 entry has been changed. */
902 /* - The output process is signalled to trigger a
904 ; /* Above processes are already done previously. */
909 /* otherwise, re-initialize the timeout. */
910 ripng_timeout_update (rinfo
);
913 /* Unlock tempolary lock of the route. */
914 route_unlock_node (rp
);
918 /* Add redistributed route to RIPng table. */
920 ripng_redistribute_add (int type
, int sub_type
, struct prefix_ipv6
*p
,
921 unsigned int ifindex
, struct in6_addr
*nexthop
)
923 struct route_node
*rp
;
924 struct ripng_info
*rinfo
;
926 /* Redistribute route */
927 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
929 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
931 #if defined (MUSICA) || defined (LINUX)
932 /* XXX As long as the RIPng redistribution is applied to all the connected
933 * routes, one needs to filter the ::/96 prefixes.
934 * However it could be a wanted case, it will be removed soon.
936 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
937 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
939 #endif /* MUSICA or LINUX */
941 rp
= route_node_get (ripng
->table
, (struct prefix
*) p
);
946 if (rinfo
->type
== ZEBRA_ROUTE_CONNECT
947 && rinfo
->sub_type
== RIPNG_ROUTE_INTERFACE
948 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
) {
949 route_unlock_node (rp
);
953 /* Manually configured RIPng route check.
954 * They have the precedence on all the other entries.
956 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
957 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
958 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
)) ) {
959 if (type
!= ZEBRA_ROUTE_RIPNG
|| ((sub_type
!= RIPNG_ROUTE_STATIC
) &&
960 (sub_type
!= RIPNG_ROUTE_DEFAULT
))) {
961 route_unlock_node (rp
);
966 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
967 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
969 /* Tells the other daemons about the deletion of
972 if (ripng_route_rte (rinfo
))
973 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
977 ripng_info_free (rinfo
);
979 route_unlock_node (rp
);
983 rinfo
= ripng_info_new ();
986 rinfo
->sub_type
= sub_type
;
987 rinfo
->ifindex
= ifindex
;
991 if (nexthop
&& IN6_IS_ADDR_LINKLOCAL(nexthop
))
992 rinfo
->nexthop
= *nexthop
;
994 rinfo
->flags
|= RIPNG_RTF_FIB
;
997 /* Aggregate check. */
998 ripng_aggregate_increment (rp
, rinfo
);
1000 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1002 if (IS_RIPNG_DEBUG_EVENT
) {
1004 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
1005 inet6_ntoa(p
->prefix
), p
->prefixlen
,
1006 ifindex2ifname(ifindex
));
1008 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1009 inet6_ntoa(p
->prefix
), p
->prefixlen
, inet6_ntoa(*nexthop
),
1010 ifindex2ifname(ifindex
));
1013 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1016 /* Delete redistributed route to RIPng table. */
1018 ripng_redistribute_delete (int type
, int sub_type
, struct prefix_ipv6
*p
,
1019 unsigned int ifindex
)
1021 struct route_node
*rp
;
1022 struct ripng_info
*rinfo
;
1024 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
1026 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
1028 #if defined (MUSICA) || defined (LINUX)
1029 /* XXX As long as the RIPng redistribution is applied to all the connected
1030 * routes, one needs to filter the ::/96 prefixes.
1031 * However it could be a wanted case, it will be removed soon.
1033 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
1034 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
1036 #endif /* MUSICA or LINUX */
1038 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) p
);
1045 && rinfo
->type
== type
1046 && rinfo
->sub_type
== sub_type
1047 && rinfo
->ifindex
== ifindex
)
1049 /* Perform poisoned reverse. */
1050 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1051 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1052 ripng_garbage_collect
, ripng
->garbage_time
);
1053 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1055 /* Aggregate count decrement. */
1056 ripng_aggregate_decrement (rp
, rinfo
);
1058 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1060 if (IS_RIPNG_DEBUG_EVENT
)
1061 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1062 inet6_ntoa(p
->prefix
), p
->prefixlen
,
1063 ifindex2ifname(ifindex
));
1065 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1070 /* Withdraw redistributed route. */
1072 ripng_redistribute_withdraw (int type
)
1074 struct route_node
*rp
;
1075 struct ripng_info
*rinfo
;
1080 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1081 if ((rinfo
= rp
->info
) != NULL
)
1083 if ((rinfo
->type
== type
)
1084 && (rinfo
->sub_type
!= RIPNG_ROUTE_INTERFACE
))
1086 /* Perform poisoned reverse. */
1087 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1088 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1089 ripng_garbage_collect
, ripng
->garbage_time
);
1090 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1092 /* Aggregate count decrement. */
1093 ripng_aggregate_decrement (rp
, rinfo
);
1095 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1097 if (IS_RIPNG_DEBUG_EVENT
) {
1098 struct prefix_ipv6
*p
= (struct prefix_ipv6
*) &rp
->p
;
1100 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
1101 inet6_ntoa(p
->prefix
), p
->prefixlen
,
1102 ifindex2ifname(rinfo
->ifindex
));
1105 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1110 /* RIP routing information. */
1112 ripng_response_process (struct ripng_packet
*packet
, int size
,
1113 struct sockaddr_in6
*from
, struct interface
*ifp
,
1118 struct ripng_nexthop nexthop
;
1120 /* RFC2080 2.4.2 Response Messages:
1121 The Response must be ignored if it is not from the RIPng port. */
1122 if (ntohs (from
->sin6_port
) != RIPNG_PORT_DEFAULT
)
1124 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
1125 ntohs (from
->sin6_port
), inet6_ntoa (from
->sin6_addr
));
1126 ripng_peer_bad_packet (from
);
1130 /* The datagram's IPv6 source address should be checked to see
1131 whether the datagram is from a valid neighbor; the source of the
1132 datagram must be a link-local address. */
1133 if (! IN6_IS_ADDR_LINKLOCAL(&from
->sin6_addr
))
1135 zlog_warn ("RIPng packet comes from non link local address %s",
1136 inet6_ntoa (from
->sin6_addr
));
1137 ripng_peer_bad_packet (from
);
1141 /* It is also worth checking to see whether the response is from one
1142 of the router's own addresses. Interfaces on broadcast networks
1143 may receive copies of their own multicasts immediately. If a
1144 router processes its own output as new input, confusion is likely,
1145 and such datagrams must be ignored. */
1146 if (ripng_lladdr_check (ifp
, &from
->sin6_addr
))
1148 zlog_warn ("RIPng packet comes from my own link local address %s",
1149 inet6_ntoa (from
->sin6_addr
));
1150 ripng_peer_bad_packet (from
);
1154 /* As an additional check, periodic advertisements must have their
1155 hop counts set to 255, and inbound, multicast packets sent from the
1156 RIPng port (i.e. periodic advertisement or triggered update
1157 packets) must be examined to ensure that the hop count is 255. */
1158 if (hoplimit
>= 0 && hoplimit
!= 255)
1160 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
1161 hoplimit
, inet6_ntoa (from
->sin6_addr
));
1162 ripng_peer_bad_packet (from
);
1166 /* Update RIPng peer. */
1167 ripng_peer_update (from
, packet
->version
);
1169 /* Reset nexthop. */
1170 memset (&nexthop
, 0, sizeof (struct ripng_nexthop
));
1171 nexthop
.flag
= RIPNG_NEXTHOP_UNSPEC
;
1173 /* Set RTE pointer. */
1176 for (lim
= ((caddr_t
) packet
) + size
; (caddr_t
) rte
< lim
; rte
++)
1178 /* First of all, we have to check this RTE is next hop RTE or
1179 not. Next hop RTE is completely different with normal RTE so
1180 we need special treatment. */
1181 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
1183 ripng_nexthop_rte (rte
, from
, &nexthop
);
1187 /* RTE information validation. */
1189 /* - is the destination prefix valid (e.g., not a multicast
1190 prefix and not a link-local address) A link-local address
1191 should never be present in an RTE. */
1192 if (IN6_IS_ADDR_MULTICAST (&rte
->addr
))
1194 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
1195 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1196 ripng_peer_bad_route (from
);
1199 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
1201 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
1202 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1203 ripng_peer_bad_route (from
);
1206 if (IN6_IS_ADDR_LOOPBACK (&rte
->addr
))
1208 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
1209 inet6_ntoa (rte
->addr
), rte
->prefixlen
, rte
->metric
);
1210 ripng_peer_bad_route (from
);
1214 /* - is the prefix length valid (i.e., between 0 and 128,
1216 if (rte
->prefixlen
> 128)
1218 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
1219 inet6_ntoa (rte
->addr
), rte
->prefixlen
,
1220 inet6_ntoa (from
->sin6_addr
), ifp
->name
);
1221 ripng_peer_bad_route (from
);
1225 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1226 if (! (rte
->metric
>= 1 && rte
->metric
<= 16))
1228 zlog_warn ("Invalid metric %d from %s%%%s", rte
->metric
,
1229 inet6_ntoa (from
->sin6_addr
), ifp
->name
);
1230 ripng_peer_bad_route (from
);
1234 /* Vincent: XXX Should we compute the direclty reachable nexthop
1235 * for our RIPng network ?
1238 /* Routing table updates. */
1239 ripng_route_process (rte
, from
, &nexthop
, ifp
);
1243 /* Response to request message. */
1245 ripng_request_process (struct ripng_packet
*packet
,int size
,
1246 struct sockaddr_in6
*from
, struct interface
*ifp
)
1250 struct prefix_ipv6 p
;
1251 struct route_node
*rp
;
1252 struct ripng_info
*rinfo
;
1253 struct ripng_interface
*ri
;
1255 /* Does not reponse to the requests on the loopback interfaces */
1256 if (if_is_loopback (ifp
))
1259 /* Check RIPng process is enabled on this interface. */
1264 /* When passive interface is specified, suppress responses */
1268 /* RIPng peer update. */
1269 ripng_peer_update (from
, packet
->version
);
1271 lim
= ((caddr_t
) packet
) + size
;
1274 /* The Request is processed entry by entry. If there are no
1275 entries, no response is given. */
1276 if (lim
== (caddr_t
) rte
)
1279 /* There is one special case. If there is exactly one entry in the
1280 request, and it has a destination prefix of zero, a prefix length
1281 of zero, and a metric of infinity (i.e., 16), then this is a
1282 request to send the entire routing table. In that case, a call
1283 is made to the output process to send the routing table to the
1284 requesting address/port. */
1285 if (lim
== ((caddr_t
) (rte
+ 1)) &&
1286 IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
) &&
1287 rte
->prefixlen
== 0 &&
1288 rte
->metric
== RIPNG_METRIC_INFINITY
)
1290 /* All route with split horizon */
1291 ripng_output_process (ifp
, from
, ripng_all_route
);
1295 /* Except for this special case, processing is quite simple.
1296 Examine the list of RTEs in the Request one by one. For each
1297 entry, look up the destination in the router's routing
1298 database and, if there is a route, put that route's metric in
1299 the metric field of the RTE. If there is no explicit route
1300 to the specified destination, put infinity in the metric
1301 field. Once all the entries have been filled in, change the
1302 command from Request to Response and send the datagram back
1303 to the requestor. */
1304 memset (&p
, 0, sizeof (struct prefix_ipv6
));
1305 p
.family
= AF_INET6
;
1307 for (; ((caddr_t
) rte
) < lim
; rte
++)
1309 p
.prefix
= rte
->addr
;
1310 p
.prefixlen
= rte
->prefixlen
;
1311 apply_mask_ipv6 (&p
);
1313 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) &p
);
1318 rte
->metric
= rinfo
->metric
;
1319 route_unlock_node (rp
);
1322 rte
->metric
= RIPNG_METRIC_INFINITY
;
1324 packet
->command
= RIPNG_RESPONSE
;
1326 ripng_send_packet ((caddr_t
) packet
, size
, from
, ifp
);
1330 /* First entry point of reading RIPng packet. */
1332 ripng_read (struct thread
*thread
)
1336 struct sockaddr_in6 from
;
1337 struct ripng_packet
*packet
;
1338 unsigned int ifindex
;
1339 struct interface
*ifp
;
1342 /* Check ripng is active and alive. */
1343 assert (ripng
!= NULL
);
1344 assert (ripng
->sock
>= 0);
1346 /* Fetch thread data and set read pointer to empty for event
1347 managing. `sock' sould be same as ripng->sock. */
1348 sock
= THREAD_FD (thread
);
1349 ripng
->t_read
= NULL
;
1351 /* Add myself to the next event. */
1352 ripng_event (RIPNG_READ
, sock
);
1354 /* Read RIPng packet. */
1355 len
= ripng_recv_packet (sock
, STREAM_DATA (ripng
->ibuf
),
1356 STREAM_SIZE (ripng
->ibuf
), &from
, &ifindex
,
1360 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno
));
1364 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1365 (4)) must be multiple size of one RTE size (20). */
1366 if (((len
- 4) % 20) != 0)
1368 zlog_warn ("RIPng invalid packet size %d from %s", len
,
1369 inet6_ntoa (from
.sin6_addr
));
1370 ripng_peer_bad_packet (&from
);
1374 packet
= (struct ripng_packet
*) STREAM_DATA (ripng
->ibuf
);
1375 ifp
= if_lookup_by_index (ifindex
);
1377 /* RIPng packet received. */
1378 if (IS_RIPNG_DEBUG_EVENT
)
1379 zlog_debug ("RIPng packet received from %s port %d on %s",
1380 inet6_ntoa (from
.sin6_addr
), ntohs (from
.sin6_port
),
1381 ifp
? ifp
->name
: "unknown");
1383 /* Logging before packet checking. */
1384 if (IS_RIPNG_DEBUG_RECV
)
1385 ripng_packet_dump (packet
, len
, "RECV");
1387 /* Packet comes from unknown interface. */
1390 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex
);
1394 /* Packet version mismatch checking. */
1395 if (packet
->version
!= ripng
->version
)
1397 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1398 packet
->version
, ripng
->version
);
1399 ripng_peer_bad_packet (&from
);
1403 /* Process RIPng packet. */
1404 switch (packet
->command
)
1407 ripng_request_process (packet
, len
, &from
, ifp
);
1409 case RIPNG_RESPONSE
:
1410 ripng_response_process (packet
, len
, &from
, ifp
, hoplimit
);
1413 zlog_warn ("Invalid RIPng command %d", packet
->command
);
1414 ripng_peer_bad_packet (&from
);
1420 /* Walk down the RIPng routing table then clear changed flag. */
1422 ripng_clear_changed_flag (void)
1424 struct route_node
*rp
;
1425 struct ripng_info
*rinfo
;
1427 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1428 if ((rinfo
= rp
->info
) != NULL
)
1429 if (rinfo
->flags
& RIPNG_RTF_CHANGED
)
1430 rinfo
->flags
&= ~RIPNG_RTF_CHANGED
;
1433 /* Regular update of RIPng route. Send all routing formation to RIPng
1434 enabled interface. */
1436 ripng_update (struct thread
*t
)
1438 struct listnode
*node
;
1439 struct interface
*ifp
;
1440 struct ripng_interface
*ri
;
1442 /* Clear update timer thread. */
1443 ripng
->t_update
= NULL
;
1445 /* Logging update event. */
1446 if (IS_RIPNG_DEBUG_EVENT
)
1447 zlog_debug ("RIPng update timer expired!");
1449 /* Supply routes to each interface. */
1450 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
1454 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1460 /* When passive interface is specified, suppress announce to the
1466 if (ri
->ri_send
== RIPNG_SEND_OFF
)
1468 if (IS_RIPNG_DEBUG_EVENT
)
1469 zlog (NULL
, LOG_DEBUG
,
1470 "[Event] RIPng send to if %d is suppressed by config",
1474 #endif /* RIPNG_ADVANCED */
1476 ripng_output_process (ifp
, NULL
, ripng_all_route
);
1479 /* Triggered updates may be suppressed if a regular update is due by
1480 the time the triggered update would be sent. */
1481 if (ripng
->t_triggered_interval
)
1483 thread_cancel (ripng
->t_triggered_interval
);
1484 ripng
->t_triggered_interval
= NULL
;
1488 /* Reset flush event. */
1489 ripng_event (RIPNG_UPDATE_EVENT
, 0);
1494 /* Triggered update interval timer. */
1496 ripng_triggered_interval (struct thread
*t
)
1498 ripng
->t_triggered_interval
= NULL
;
1503 ripng_triggered_update (t
);
1508 /* Execute triggered update. */
1510 ripng_triggered_update (struct thread
*t
)
1512 struct listnode
*node
;
1513 struct interface
*ifp
;
1514 struct ripng_interface
*ri
;
1517 ripng
->t_triggered_update
= NULL
;
1519 /* Cancel interval timer. */
1520 if (ripng
->t_triggered_interval
)
1522 thread_cancel (ripng
->t_triggered_interval
);
1523 ripng
->t_triggered_interval
= NULL
;
1527 /* Logging triggered update. */
1528 if (IS_RIPNG_DEBUG_EVENT
)
1529 zlog_debug ("RIPng triggered update!");
1531 /* Split Horizon processing is done when generating triggered
1532 updates as well as normal updates (see section 2.6). */
1533 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
1537 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1543 /* When passive interface is specified, suppress announce to the
1548 ripng_output_process (ifp
, NULL
, ripng_changed_route
);
1551 /* Once all of the triggered updates have been generated, the route
1552 change flags should be cleared. */
1553 ripng_clear_changed_flag ();
1555 /* After a triggered update is sent, a timer should be set for a
1556 random interval between 1 and 5 seconds. If other changes that
1557 would trigger updates occur before the timer expires, a single
1558 update is triggered when the timer expires. */
1559 interval
= (random () % 5) + 1;
1561 ripng
->t_triggered_interval
=
1562 thread_add_timer (master
, ripng_triggered_interval
, NULL
, interval
);
1567 /* Write routing table entry to the stream and return next index of
1568 the routing table entry in the stream. */
1570 ripng_write_rte (int num
, struct stream
*s
, struct prefix_ipv6
*p
,
1571 struct in6_addr
*nexthop
, u_int16_t tag
, u_char metric
)
1573 /* RIPng packet header. */
1576 stream_putc (s
, RIPNG_RESPONSE
);
1577 stream_putc (s
, RIPNG_V1
);
1581 /* Write routing table entry. */
1583 stream_write (s
, (u_char
*) &p
->prefix
, sizeof (struct in6_addr
));
1585 stream_write (s
, (u_char
*) nexthop
, sizeof (struct in6_addr
));
1586 stream_putw (s
, tag
);
1588 stream_putc (s
, p
->prefixlen
);
1591 stream_putc (s
, metric
);
1596 /* Send RESPONSE message to specified destination. */
1598 ripng_output_process (struct interface
*ifp
, struct sockaddr_in6
*to
,
1602 struct route_node
*rp
;
1603 struct ripng_info
*rinfo
;
1604 struct ripng_interface
*ri
;
1605 struct ripng_aggregate
*aggregate
;
1606 struct prefix_ipv6
*p
;
1607 struct list
* ripng_rte_list
;
1609 if (IS_RIPNG_DEBUG_EVENT
) {
1611 zlog_debug ("RIPng update routes to neighbor %s",
1612 inet6_ntoa(to
->sin6_addr
));
1614 zlog_debug ("RIPng update routes on interface %s", ifp
->name
);
1617 /* Get RIPng interface. */
1620 ripng_rte_list
= ripng_rte_new();
1622 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1624 if ((rinfo
= rp
->info
) != NULL
&& rinfo
->suppress
== 0)
1626 /* If no route-map are applied, the RTE will be these following
1629 p
= (struct prefix_ipv6
*) &rp
->p
;
1630 rinfo
->metric_out
= rinfo
->metric
;
1631 rinfo
->tag_out
= rinfo
->tag
;
1632 memset(&rinfo
->nexthop_out
, 0, sizeof(rinfo
->nexthop_out
));
1633 /* In order to avoid some local loops,
1634 * if the RIPng route has a nexthop via this interface, keep the nexthop,
1635 * otherwise set it to 0. The nexthop should not be propagated
1636 * beyond the local broadcast/multicast area in order
1637 * to avoid an IGP multi-level recursive look-up.
1639 if (rinfo
->ifindex
== ifp
->ifindex
)
1640 rinfo
->nexthop_out
= rinfo
->nexthop
;
1642 /* Apply output filters. */
1643 ret
= ripng_outgoing_filter (p
, ri
);
1647 /* Changed route only output. */
1648 if (route_type
== ripng_changed_route
&&
1649 (! (rinfo
->flags
& RIPNG_RTF_CHANGED
)))
1652 /* Split horizon. */
1653 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON
)
1655 /* We perform split horizon for RIPng routes. */
1656 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1657 rinfo
->ifindex
== ifp
->ifindex
)
1661 /* Preparation for route-map. */
1662 rinfo
->metric_set
= 0;
1665 * and tag_out are already initialized.
1668 /* Interface route-map */
1669 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1673 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1674 (struct prefix
*) p
, RMAP_RIPNG
,
1677 if (ret
== RMAP_DENYMATCH
)
1679 if (IS_RIPNG_DEBUG_PACKET
)
1680 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1681 inet6_ntoa (p
->prefix
), p
->prefixlen
);
1687 /* Redistribute route-map. */
1688 if (ripng
->route_map
[rinfo
->type
].name
)
1692 ret
= route_map_apply (ripng
->route_map
[rinfo
->type
].map
,
1693 (struct prefix
*) p
, RMAP_RIPNG
,
1696 if (ret
== RMAP_DENYMATCH
)
1698 if (IS_RIPNG_DEBUG_PACKET
)
1699 zlog_debug ("RIPng %s/%d is filtered by route-map",
1700 inet6_ntoa (p
->prefix
), p
->prefixlen
);
1705 /* When the route-map does not set metric. */
1706 if (! rinfo
->metric_set
)
1708 /* If the redistribute metric is set. */
1709 if (ripng
->route_map
[rinfo
->type
].metric_config
1710 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1712 rinfo
->metric_out
= ripng
->route_map
[rinfo
->type
].metric
;
1716 /* If the route is not connected or localy generated
1717 one, use default-metric value */
1718 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
1719 && rinfo
->type
!= ZEBRA_ROUTE_CONNECT
1720 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1721 rinfo
->metric_out
= ripng
->default_metric
;
1725 /* Apply offset-list */
1726 if (rinfo
->metric_out
!= RIPNG_METRIC_INFINITY
)
1727 ripng_offset_list_apply_out (p
, ifp
, &rinfo
->metric_out
);
1729 if (rinfo
->metric_out
> RIPNG_METRIC_INFINITY
)
1730 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1732 /* Perform split-horizon with poisoned reverse
1735 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON_POISONED_REVERSE
) {
1736 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1737 rinfo
->ifindex
== ifp
->ifindex
)
1738 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1741 /* Add RTE to the list */
1742 ripng_rte_add(ripng_rte_list
, p
, rinfo
, NULL
);
1745 /* Process the aggregated RTE entry */
1746 if ((aggregate
= rp
->aggregate
) != NULL
&&
1747 aggregate
->count
> 0 &&
1748 aggregate
->suppress
== 0)
1750 /* If no route-map are applied, the RTE will be these following
1753 p
= (struct prefix_ipv6
*) &rp
->p
;
1754 aggregate
->metric_set
= 0;
1755 aggregate
->metric_out
= aggregate
->metric
;
1756 aggregate
->tag_out
= aggregate
->tag
;
1757 memset(&aggregate
->nexthop_out
, 0, sizeof(aggregate
->nexthop_out
));
1759 /* Apply output filters.*/
1760 ret
= ripng_outgoing_filter (p
, ri
);
1764 /* Interface route-map */
1765 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1768 struct ripng_info newinfo
;
1770 /* let's cast the aggregate structure to ripng_info */
1771 memset (&newinfo
, 0, sizeof (struct ripng_info
));
1772 /* the nexthop is :: */
1773 newinfo
.metric
= aggregate
->metric
;
1774 newinfo
.metric_out
= aggregate
->metric_out
;
1775 newinfo
.tag
= aggregate
->tag
;
1776 newinfo
.tag_out
= aggregate
->tag_out
;
1778 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1779 (struct prefix
*) p
, RMAP_RIPNG
,
1782 if (ret
== RMAP_DENYMATCH
)
1784 if (IS_RIPNG_DEBUG_PACKET
)
1785 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1786 inet6_ntoa (p
->prefix
), p
->prefixlen
);
1790 aggregate
->metric_out
= newinfo
.metric_out
;
1791 aggregate
->tag_out
= newinfo
.tag_out
;
1792 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop_out
))
1793 aggregate
->nexthop_out
= newinfo
.nexthop_out
;
1796 /* There is no redistribute routemap for the aggregated RTE */
1798 /* Changed route only output. */
1799 /* XXX, vincent, in order to increase time convergence,
1800 * it should be announced if a child has changed.
1802 if (route_type
== ripng_changed_route
)
1805 /* Apply offset-list */
1806 if (aggregate
->metric_out
!= RIPNG_METRIC_INFINITY
)
1807 ripng_offset_list_apply_out (p
, ifp
, &aggregate
->metric_out
);
1809 if (aggregate
->metric_out
> RIPNG_METRIC_INFINITY
)
1810 aggregate
->metric_out
= RIPNG_METRIC_INFINITY
;
1812 /* Add RTE to the list */
1813 ripng_rte_add(ripng_rte_list
, p
, NULL
, aggregate
);
1818 /* Flush the list */
1819 ripng_rte_send(ripng_rte_list
, ifp
, to
);
1820 ripng_rte_free(ripng_rte_list
);
1823 /* Create new RIPng instance and set it to global variable. */
1827 /* ripng should be NULL. */
1828 assert (ripng
== NULL
);
1830 /* Allocaste RIPng instance. */
1831 ripng
= XCALLOC (MTYPE_RIPNG
, sizeof (struct ripng
));
1833 /* Default version and timer values. */
1834 ripng
->version
= RIPNG_V1
;
1835 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
1836 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
1837 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
1838 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
1841 ripng
->ibuf
= stream_new (RIPNG_MAX_PACKET_SIZE
* 5);
1842 ripng
->obuf
= stream_new (RIPNG_MAX_PACKET_SIZE
);
1844 /* Initialize RIPng routig table. */
1845 ripng
->table
= route_table_init ();
1846 ripng
->route
= route_table_init ();
1847 ripng
->aggregate
= route_table_init ();
1850 ripng
->sock
= ripng_make_socket ();
1851 if (ripng
->sock
< 0)
1855 ripng_event (RIPNG_READ
, ripng
->sock
);
1856 ripng_event (RIPNG_UPDATE_EVENT
, 1);
1861 /* Send RIPng request to the interface. */
1863 ripng_request (struct interface
*ifp
)
1866 struct ripng_packet ripng_packet
;
1868 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
1869 if (if_is_loopback(ifp
))
1872 /* If interface is down, don't send RIP packet. */
1873 if (! if_is_up (ifp
))
1876 if (IS_RIPNG_DEBUG_EVENT
)
1877 zlog_debug ("RIPng send request to %s", ifp
->name
);
1879 memset (&ripng_packet
, 0, sizeof (ripng_packet
));
1880 ripng_packet
.command
= RIPNG_REQUEST
;
1881 ripng_packet
.version
= RIPNG_V1
;
1882 rte
= ripng_packet
.rte
;
1883 rte
->metric
= RIPNG_METRIC_INFINITY
;
1885 return ripng_send_packet ((caddr_t
) &ripng_packet
, sizeof (ripng_packet
),
1891 ripng_update_jitter (int time
)
1893 return ((rand () % (time
+ 1)) - (time
/ 2));
1897 ripng_event (enum ripng_event event
, int sock
)
1905 ripng
->t_read
= thread_add_read (master
, ripng_read
, NULL
, sock
);
1907 case RIPNG_UPDATE_EVENT
:
1908 if (ripng
->t_update
)
1910 thread_cancel (ripng
->t_update
);
1911 ripng
->t_update
= NULL
;
1913 /* Update timer jitter. */
1914 jitter
= ripng_update_jitter (ripng
->update_time
);
1917 thread_add_timer (master
, ripng_update
, NULL
,
1918 sock
? 2 : ripng
->update_time
+ jitter
);
1920 case RIPNG_TRIGGERED_UPDATE
:
1921 if (ripng
->t_triggered_interval
)
1923 else if (! ripng
->t_triggered_update
)
1924 ripng
->t_triggered_update
=
1925 thread_add_event (master
, ripng_triggered_update
, NULL
, 0);
1933 /* Print out routes update time. */
1935 ripng_vty_out_uptime (struct vty
*vty
, struct ripng_info
*rinfo
)
1940 char timebuf
[TIME_BUF
];
1941 struct thread
*thread
;
1943 if ((thread
= rinfo
->t_timeout
) != NULL
)
1945 clock
= thread_timer_remain_second (thread
);
1946 tm
= gmtime (&clock
);
1947 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1948 vty_out (vty
, "%5s", timebuf
);
1950 else if ((thread
= rinfo
->t_garbage_collect
) != NULL
)
1952 clock
= thread_timer_remain_second (thread
);
1953 tm
= gmtime (&clock
);
1954 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1955 vty_out (vty
, "%5s", timebuf
);
1960 ripng_route_subtype_print (struct ripng_info
*rinfo
)
1965 if (rinfo
->suppress
)
1968 switch (rinfo
->sub_type
)
1970 case RIPNG_ROUTE_RTE
:
1973 case RIPNG_ROUTE_STATIC
:
1976 case RIPNG_ROUTE_DEFAULT
:
1979 case RIPNG_ROUTE_REDISTRIBUTE
:
1982 case RIPNG_ROUTE_INTERFACE
:
1993 DEFUN (show_ipv6_ripng
,
1994 show_ipv6_ripng_cmd
,
1998 "Show RIPng routes\n")
2000 struct route_node
*rp
;
2001 struct ripng_info
*rinfo
;
2002 struct ripng_aggregate
*aggregate
;
2003 struct prefix_ipv6
*p
;
2009 /* Header of display. */
2010 vty_out (vty
, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2012 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2013 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2014 " Network Next Hop Via Metric Tag Time%s",
2015 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2016 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
2018 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2020 if ((aggregate
= rp
->aggregate
) != NULL
)
2022 p
= (struct prefix_ipv6
*) &rp
->p
;
2025 len
= vty_out (vty
, "R(a) %d/%d %s/%d ",
2026 aggregate
->count
, aggregate
->suppress
,
2027 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2029 len
= vty_out (vty
, "R(a) %s/%d ",
2030 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2032 vty_out (vty
, "%s", VTY_NEWLINE
);
2033 vty_out (vty
, "%*s", 18, " ");
2035 vty_out (vty
, "%*s", 28, " ");
2036 vty_out (vty
, "self %2d %3d%s", aggregate
->metric
,
2041 if ((rinfo
= rp
->info
) != NULL
)
2043 p
= (struct prefix_ipv6
*) &rp
->p
;
2046 len
= vty_out (vty
, "%c(%s) 0/%d %s/%d ",
2047 zebra_route_char(rinfo
->type
),
2048 ripng_route_subtype_print(rinfo
),
2050 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2052 len
= vty_out (vty
, "%c(%s) %s/%d ",
2053 zebra_route_char(rinfo
->type
),
2054 ripng_route_subtype_print(rinfo
),
2055 inet6_ntoa (p
->prefix
), p
->prefixlen
);
2057 vty_out (vty
, "%s", VTY_NEWLINE
);
2058 vty_out (vty
, "%*s", 18, " ");
2059 len
= vty_out (vty
, "%s", inet6_ntoa (rinfo
->nexthop
));
2063 len
= vty_out (vty
, "%*s", len
, " ");
2066 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2067 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2069 len
= vty_out (vty
, "%s", ifindex2ifname(rinfo
->ifindex
));
2070 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2072 len
= vty_out (vty
, "kill");
2074 len
= vty_out (vty
, "self");
2078 vty_out (vty
, "%*s", len
, " ");
2080 vty_out (vty
, " %2d %3d ",
2081 rinfo
->metric
, rinfo
->tag
);
2084 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2085 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2087 /* RTE from remote RIP routers */
2088 ripng_vty_out_uptime (vty
, rinfo
);
2089 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2091 /* poisonous reversed routes (gc) */
2092 ripng_vty_out_uptime (vty
, rinfo
);
2095 vty_out (vty
, "%s", VTY_NEWLINE
);
2102 DEFUN (show_ipv6_ripng_status
,
2103 show_ipv6_ripng_status_cmd
,
2104 "show ipv6 ripng status",
2107 "Show RIPng routes\n"
2108 "IPv6 routing protocol process parameters and statistics\n")
2110 struct listnode
*node
;
2111 struct interface
*ifp
;
2116 vty_out (vty
, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE
);
2117 vty_out (vty
, " Sending updates every %ld seconds with +/-50%%,",
2118 ripng
->update_time
);
2119 vty_out (vty
, " next due in %lu seconds%s",
2120 thread_timer_remain_second (ripng
->t_update
),
2122 vty_out (vty
, " Timeout after %ld seconds,", ripng
->timeout_time
);
2123 vty_out (vty
, " garbage collect after %ld seconds%s", ripng
->garbage_time
,
2126 /* Filtering status show. */
2127 config_show_distribute (vty
);
2129 /* Default metric information. */
2130 vty_out (vty
, " Default redistribution metric is %d%s",
2131 ripng
->default_metric
, VTY_NEWLINE
);
2133 /* Redistribute information. */
2134 vty_out (vty
, " Redistributing:");
2135 ripng_redistribute_write (vty
, 0);
2136 vty_out (vty
, "%s", VTY_NEWLINE
);
2138 vty_out (vty
, " Default version control: send version %d,", ripng
->version
);
2139 vty_out (vty
, " receive version %d %s", ripng
->version
,
2142 vty_out (vty
, " Interface Send Recv%s", VTY_NEWLINE
);
2144 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
2146 struct ripng_interface
*ri
;
2150 if (ri
->enable_network
|| ri
->enable_interface
)
2153 vty_out (vty
, " %-17s%-3d %-3d%s", ifp
->name
,
2160 vty_out (vty
, " Routing for Networks:%s", VTY_NEWLINE
);
2161 ripng_network_write (vty
, 0);
2163 vty_out (vty
, " Routing Information Sources:%s", VTY_NEWLINE
);
2164 vty_out (vty
, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE
);
2165 ripng_peer_display (vty
);
2170 DEFUN (router_ripng
,
2173 "Enable a routing process\n"
2174 "Make RIPng instance command\n")
2178 vty
->node
= RIPNG_NODE
;
2182 ret
= ripng_create ();
2184 /* Notice to user we couldn't create RIPng. */
2187 zlog_warn ("can't create RIPng");
2195 DEFUN (no_router_ripng
,
2196 no_router_ripng_cmd
,
2199 "Enable a routing process\n"
2200 "Make RIPng instance command\n")
2210 "Static route setup\n"
2211 "Set static RIPng route announcement\n")
2214 struct prefix_ipv6 p
;
2215 struct route_node
*rp
;
2217 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2220 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2223 apply_mask_ipv6 (&p
);
2225 rp
= route_node_get (ripng
->route
, (struct prefix
*) &p
);
2228 vty_out (vty
, "There is already same static route.%s", VTY_NEWLINE
);
2229 route_unlock_node (rp
);
2232 rp
->info
= (void *)1;
2234 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0, NULL
);
2239 DEFUN (no_ripng_route
,
2241 "no route IPV6ADDR",
2243 "Static route setup\n"
2244 "Delete static RIPng route announcement\n")
2247 struct prefix_ipv6 p
;
2248 struct route_node
*rp
;
2250 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2253 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2256 apply_mask_ipv6 (&p
);
2258 rp
= route_node_lookup (ripng
->route
, (struct prefix
*) &p
);
2261 vty_out (vty
, "Can't find static route.%s", VTY_NEWLINE
);
2265 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0);
2266 route_unlock_node (rp
);
2269 route_unlock_node (rp
);
2274 DEFUN (ripng_aggregate_address
,
2275 ripng_aggregate_address_cmd
,
2276 "aggregate-address X:X::X:X/M",
2277 "Set aggregate RIPng route announcement\n"
2278 "Aggregate network\n")
2282 struct route_node
*node
;
2284 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2287 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2291 /* Check aggregate alredy exist or not. */
2292 node
= route_node_get (ripng
->aggregate
, &p
);
2295 vty_out (vty
, "There is already same aggregate route.%s", VTY_NEWLINE
);
2296 route_unlock_node (node
);
2299 node
->info
= (void *)1;
2301 ripng_aggregate_add (&p
);
2306 DEFUN (no_ripng_aggregate_address
,
2307 no_ripng_aggregate_address_cmd
,
2308 "no aggregate-address X:X::X:X/M",
2310 "Delete aggregate RIPng route announcement\n"
2311 "Aggregate network")
2315 struct route_node
*rn
;
2317 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &p
);
2320 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2324 rn
= route_node_lookup (ripng
->aggregate
, &p
);
2327 vty_out (vty
, "Can't find aggregate route.%s", VTY_NEWLINE
);
2330 route_unlock_node (rn
);
2332 route_unlock_node (rn
);
2334 ripng_aggregate_delete (&p
);
2339 DEFUN (ripng_default_metric
,
2340 ripng_default_metric_cmd
,
2341 "default-metric <1-16>",
2342 "Set a metric of redistribute routes\n"
2347 ripng
->default_metric
= atoi (argv
[0]);
2352 DEFUN (no_ripng_default_metric
,
2353 no_ripng_default_metric_cmd
,
2354 "no default-metric",
2356 "Set a metric of redistribute routes\n"
2361 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
2366 ALIAS (no_ripng_default_metric
,
2367 no_ripng_default_metric_val_cmd
,
2368 "no default-metric <1-16>",
2370 "Set a metric of redistribute routes\n"
2374 /* RIPng update timer setup. */
2375 DEFUN (ripng_update_timer
,
2376 ripng_update_timer_cmd
,
2377 "update-timer SECOND",
2378 "Set RIPng update timer in seconds\n"
2381 unsigned long update
;
2382 char *endptr
= NULL
;
2384 update
= strtoul (argv
[0], &endptr
, 10);
2385 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2387 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2391 ripng
->update_time
= update
;
2393 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2397 DEFUN (no_ripng_update_timer
,
2398 no_ripng_update_timer_cmd
,
2399 "no update-timer SECOND",
2401 "Unset RIPng update timer in seconds\n"
2404 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2405 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2409 /* RIPng timeout timer setup. */
2410 DEFUN (ripng_timeout_timer
,
2411 ripng_timeout_timer_cmd
,
2412 "timeout-timer SECOND",
2413 "Set RIPng timeout timer in seconds\n"
2416 unsigned long timeout
;
2417 char *endptr
= NULL
;
2419 timeout
= strtoul (argv
[0], &endptr
, 10);
2420 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2422 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2426 ripng
->timeout_time
= timeout
;
2431 DEFUN (no_ripng_timeout_timer
,
2432 no_ripng_timeout_timer_cmd
,
2433 "no timeout-timer SECOND",
2435 "Unset RIPng timeout timer in seconds\n"
2438 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2442 /* RIPng garbage timer setup. */
2443 DEFUN (ripng_garbage_timer
,
2444 ripng_garbage_timer_cmd
,
2445 "garbage-timer SECOND",
2446 "Set RIPng garbage timer in seconds\n"
2449 unsigned long garbage
;
2450 char *endptr
= NULL
;
2452 garbage
= strtoul (argv
[0], &endptr
, 10);
2453 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2455 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2459 ripng
->garbage_time
= garbage
;
2464 DEFUN (no_ripng_garbage_timer
,
2465 no_ripng_garbage_timer_cmd
,
2466 "no garbage-timer SECOND",
2468 "Unset RIPng garbage timer in seconds\n"
2471 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2476 DEFUN (ripng_timers
,
2478 "timers basic <0-65535> <0-65535> <0-65535>",
2479 "RIPng timers setup\n"
2481 "Routing table update timer value in second. Default is 30.\n"
2482 "Routing information timeout timer. Default is 180.\n"
2483 "Garbage collection timer. Default is 120.\n")
2485 unsigned long update
;
2486 unsigned long timeout
;
2487 unsigned long garbage
;
2489 VTY_GET_INTEGER_RANGE("update timer", update
, argv
[0], 0, 65535);
2490 VTY_GET_INTEGER_RANGE("timeout timer", timeout
, argv
[1], 0, 65535);
2491 VTY_GET_INTEGER_RANGE("garbage timer", garbage
, argv
[2], 0, 65535);
2493 /* Set each timer value. */
2494 ripng
->update_time
= update
;
2495 ripng
->timeout_time
= timeout
;
2496 ripng
->garbage_time
= garbage
;
2498 /* Reset update timer thread. */
2499 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2504 DEFUN (no_ripng_timers
,
2505 no_ripng_timers_cmd
,
2508 "RIPng timers setup\n"
2511 /* Set each timer value to the default. */
2512 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2513 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2514 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2516 /* Reset update timer thread. */
2517 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2522 ALIAS (no_ripng_timers
,
2523 no_ripng_timers_val_cmd
,
2524 "no timers basic <0-65535> <0-65535> <0-65535>",
2526 "RIPng timers setup\n"
2528 "Routing table update timer value in second. Default is 30.\n"
2529 "Routing information timeout timer. Default is 180.\n"
2530 "Garbage collection timer. Default is 120.\n")
2532 DEFUN (show_ipv6_protocols
, show_ipv6_protocols_cmd
,
2533 "show ipv6 protocols",
2536 "Routing protocol information")
2541 vty_out (vty
, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE
);
2543 vty_out (vty
, "Sending updates every %ld seconds, next due in %d seconds%s",
2544 ripng
->update_time
, 0,
2547 vty_out (vty
, "Timerout after %ld seconds, garbage correct %ld%s",
2548 ripng
->timeout_time
,
2549 ripng
->garbage_time
,
2552 vty_out (vty
, "Outgoing update filter list for all interfaces is not set");
2553 vty_out (vty
, "Incoming update filter list for all interfaces is not set");
2558 /* Please be carefull to use this command. */
2559 DEFUN (ripng_default_information_originate
,
2560 ripng_default_information_originate_cmd
,
2561 "default-information originate",
2562 "Default route information\n"
2563 "Distribute default route\n")
2565 struct prefix_ipv6 p
;
2567 if (! ripng
->default_information
) {
2568 ripng
->default_information
= 1;
2570 str2prefix_ipv6 ("::/0", &p
);
2571 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0, NULL
);
2577 DEFUN (no_ripng_default_information_originate
,
2578 no_ripng_default_information_originate_cmd
,
2579 "no default-information originate",
2581 "Default route information\n"
2582 "Distribute default route\n")
2584 struct prefix_ipv6 p
;
2586 if (ripng
->default_information
) {
2587 ripng
->default_information
= 0;
2589 str2prefix_ipv6 ("::/0", &p
);
2590 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0);
2596 /* RIPng configuration write function. */
2598 ripng_config_write (struct vty
*vty
)
2600 int ripng_network_write (struct vty
*, int);
2601 void ripng_redistribute_write (struct vty
*, int);
2603 struct route_node
*rp
;
2609 vty_out (vty
, "router ripng%s", VTY_NEWLINE
);
2611 if (ripng
->default_information
)
2612 vty_out (vty
, " default-information originate%s", VTY_NEWLINE
);
2614 ripng_network_write (vty
, 1);
2616 /* RIPng default metric configuration */
2617 if (ripng
->default_metric
!= RIPNG_DEFAULT_METRIC_DEFAULT
)
2618 vty_out (vty
, " default-metric %d%s",
2619 ripng
->default_metric
, VTY_NEWLINE
);
2621 ripng_redistribute_write (vty
, 1);
2623 /* RIP offset-list configuration. */
2624 config_write_ripng_offset_list (vty
);
2626 /* RIPng aggregate routes. */
2627 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2628 if (rp
->info
!= NULL
)
2629 vty_out (vty
, " aggregate-address %s/%d%s",
2630 inet6_ntoa (rp
->p
.u
.prefix6
),
2635 /* RIPng static routes. */
2636 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2637 if (rp
->info
!= NULL
)
2638 vty_out (vty
, " route %s/%d%s", inet6_ntoa (rp
->p
.u
.prefix6
),
2642 /* RIPng timers configuration. */
2643 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
||
2644 ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
||
2645 ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2647 vty_out (vty
, " timers basic %ld %ld %ld%s",
2649 ripng
->timeout_time
,
2650 ripng
->garbage_time
,
2654 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
)
2655 vty_out (vty
, " update-timer %d%s", ripng
->update_time
,
2657 if (ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
)
2658 vty_out (vty
, " timeout-timer %d%s", ripng
->timeout_time
,
2660 if (ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2661 vty_out (vty
, " garbage-timer %d%s", ripng
->garbage_time
,
2665 write
+= config_write_distribute (vty
);
2667 write
+= config_write_if_rmap (vty
);
2674 /* RIPng node structure. */
2675 static struct cmd_node cmd_ripng_node
=
2678 "%s(config-router)# ",
2683 ripng_distribute_update (struct distribute
*dist
)
2685 struct interface
*ifp
;
2686 struct ripng_interface
*ri
;
2687 struct access_list
*alist
;
2688 struct prefix_list
*plist
;
2693 ifp
= if_lookup_by_name (dist
->ifname
);
2699 if (dist
->list
[DISTRIBUTE_IN
])
2701 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
2703 ri
->list
[RIPNG_FILTER_IN
] = alist
;
2705 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2708 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2710 if (dist
->list
[DISTRIBUTE_OUT
])
2712 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
2714 ri
->list
[RIPNG_FILTER_OUT
] = alist
;
2716 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2719 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2721 if (dist
->prefix
[DISTRIBUTE_IN
])
2723 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
2725 ri
->prefix
[RIPNG_FILTER_IN
] = plist
;
2727 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2730 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2732 if (dist
->prefix
[DISTRIBUTE_OUT
])
2734 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
2736 ri
->prefix
[RIPNG_FILTER_OUT
] = plist
;
2738 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2741 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2745 ripng_distribute_update_interface (struct interface
*ifp
)
2747 struct distribute
*dist
;
2749 dist
= distribute_lookup (ifp
->name
);
2751 ripng_distribute_update (dist
);
2754 /* Update all interface's distribute list. */
2756 ripng_distribute_update_all (struct prefix_list
*notused
)
2758 struct interface
*ifp
;
2759 struct listnode
*node
;
2761 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
2762 ripng_distribute_update_interface (ifp
);
2766 ripng_distribute_update_all_wrapper (struct access_list
*notused
)
2768 ripng_distribute_update_all(NULL
);
2771 /* delete all the added ripng routes. */
2776 struct route_node
*rp
;
2777 struct ripng_info
*rinfo
;
2780 /* Clear RIPng routes */
2781 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
)) {
2782 if ((rinfo
= rp
->info
) != NULL
) {
2783 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2784 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2785 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
,
2786 &rinfo
->nexthop
, rinfo
->metric
);
2788 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
2789 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
2792 route_unlock_node (rp
);
2794 ripng_info_free(rinfo
);
2798 /* Cancel the RIPng timers */
2799 RIPNG_TIMER_OFF (ripng
->t_update
);
2800 RIPNG_TIMER_OFF (ripng
->t_triggered_update
);
2801 RIPNG_TIMER_OFF (ripng
->t_triggered_interval
);
2803 /* Cancel the read thread */
2804 if (ripng
->t_read
) {
2805 thread_cancel (ripng
->t_read
);
2806 ripng
->t_read
= NULL
;
2809 /* Close the RIPng socket */
2810 if (ripng
->sock
>= 0) {
2815 /* Static RIPng route configuration. */
2816 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2819 route_unlock_node (rp
);
2822 /* RIPng aggregated prefixes */
2823 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2826 route_unlock_node (rp
);
2829 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2830 if (ripng
->route_map
[i
].name
)
2831 free (ripng
->route_map
[i
].name
);
2833 XFREE (MTYPE_ROUTE_TABLE
, ripng
->table
);
2834 XFREE (MTYPE_ROUTE_TABLE
, ripng
->route
);
2835 XFREE (MTYPE_ROUTE_TABLE
, ripng
->aggregate
);
2837 XFREE (MTYPE_RIPNG
, ripng
);
2841 ripng_clean_network();
2842 ripng_passive_interface_clean ();
2843 ripng_offset_clean ();
2844 ripng_interface_clean ();
2845 ripng_redistribute_clean ();
2848 /* Reset all values to the default settings. */
2852 /* Call ripd related reset functions. */
2853 ripng_debug_reset ();
2854 ripng_route_map_reset ();
2856 /* Call library reset functions. */
2858 access_list_reset ();
2859 prefix_list_reset ();
2861 distribute_list_reset ();
2863 ripng_interface_reset ();
2865 ripng_zclient_reset ();
2869 ripng_if_rmap_update (struct if_rmap
*if_rmap
)
2871 struct interface
*ifp
;
2872 struct ripng_interface
*ri
;
2873 struct route_map
*rmap
;
2875 ifp
= if_lookup_by_name (if_rmap
->ifname
);
2881 if (if_rmap
->routemap
[IF_RMAP_IN
])
2883 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_IN
]);
2885 ri
->routemap
[IF_RMAP_IN
] = rmap
;
2887 ri
->routemap
[IF_RMAP_IN
] = NULL
;
2890 ri
->routemap
[RIPNG_FILTER_IN
] = NULL
;
2892 if (if_rmap
->routemap
[IF_RMAP_OUT
])
2894 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_OUT
]);
2896 ri
->routemap
[IF_RMAP_OUT
] = rmap
;
2898 ri
->routemap
[IF_RMAP_OUT
] = NULL
;
2901 ri
->routemap
[RIPNG_FILTER_OUT
] = NULL
;
2905 ripng_if_rmap_update_interface (struct interface
*ifp
)
2907 struct if_rmap
*if_rmap
;
2909 if_rmap
= if_rmap_lookup (ifp
->name
);
2911 ripng_if_rmap_update (if_rmap
);
2915 ripng_routemap_update_redistribute (void)
2921 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2923 if (ripng
->route_map
[i
].name
)
2924 ripng
->route_map
[i
].map
=
2925 route_map_lookup_by_name (ripng
->route_map
[i
].name
);
2931 ripng_routemap_update (const char *unused
)
2933 struct interface
*ifp
;
2934 struct listnode
*node
;
2936 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
2937 ripng_if_rmap_update_interface (ifp
);
2939 ripng_routemap_update_redistribute ();
2942 /* Initialize ripng structure and set commands. */
2947 srand (time (NULL
));
2949 /* Install RIPNG_NODE. */
2950 install_node (&cmd_ripng_node
, ripng_config_write
);
2952 /* Install ripng commands. */
2953 install_element (VIEW_NODE
, &show_ipv6_ripng_cmd
);
2954 install_element (VIEW_NODE
, &show_ipv6_ripng_status_cmd
);
2956 install_element (ENABLE_NODE
, &show_ipv6_ripng_cmd
);
2957 install_element (ENABLE_NODE
, &show_ipv6_ripng_status_cmd
);
2959 install_element (CONFIG_NODE
, &router_ripng_cmd
);
2960 install_element (CONFIG_NODE
, &no_router_ripng_cmd
);
2962 install_default (RIPNG_NODE
);
2963 install_element (RIPNG_NODE
, &ripng_route_cmd
);
2964 install_element (RIPNG_NODE
, &no_ripng_route_cmd
);
2965 install_element (RIPNG_NODE
, &ripng_aggregate_address_cmd
);
2966 install_element (RIPNG_NODE
, &no_ripng_aggregate_address_cmd
);
2968 install_element (RIPNG_NODE
, &ripng_default_metric_cmd
);
2969 install_element (RIPNG_NODE
, &no_ripng_default_metric_cmd
);
2970 install_element (RIPNG_NODE
, &no_ripng_default_metric_val_cmd
);
2972 install_element (RIPNG_NODE
, &ripng_timers_cmd
);
2973 install_element (RIPNG_NODE
, &no_ripng_timers_cmd
);
2974 install_element (RIPNG_NODE
, &no_ripng_timers_val_cmd
);
2976 install_element (RIPNG_NODE
, &ripng_update_timer_cmd
);
2977 install_element (RIPNG_NODE
, &no_ripng_update_timer_cmd
);
2978 install_element (RIPNG_NODE
, &ripng_timeout_timer_cmd
);
2979 install_element (RIPNG_NODE
, &no_ripng_timeout_timer_cmd
);
2980 install_element (RIPNG_NODE
, &ripng_garbage_timer_cmd
);
2981 install_element (RIPNG_NODE
, &no_ripng_garbage_timer_cmd
);
2984 install_element (RIPNG_NODE
, &ripng_default_information_originate_cmd
);
2985 install_element (RIPNG_NODE
, &no_ripng_default_information_originate_cmd
);
2988 ripng_debug_init ();
2990 /* Access list install. */
2991 access_list_init ();
2992 access_list_add_hook (ripng_distribute_update_all_wrapper
);
2993 access_list_delete_hook (ripng_distribute_update_all_wrapper
);
2995 /* Prefix list initialize.*/
2996 prefix_list_init ();
2997 prefix_list_add_hook (ripng_distribute_update_all
);
2998 prefix_list_delete_hook (ripng_distribute_update_all
);
3000 /* Distribute list install. */
3001 distribute_list_init (RIPNG_NODE
);
3002 distribute_list_add_hook (ripng_distribute_update
);
3003 distribute_list_delete_hook (ripng_distribute_update
);
3005 /* Route-map for interface. */
3006 ripng_route_map_init ();
3007 ripng_offset_init ();
3009 route_map_add_hook (ripng_routemap_update
);
3010 route_map_delete_hook (ripng_routemap_update
);
3012 if_rmap_init (RIPNG_NODE
);
3013 if_rmap_hook_add (ripng_if_rmap_update
);
3014 if_rmap_hook_delete (ripng_if_rmap_update
);