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
;
76 /* Utility function for making IPv6 address string. */
78 inet6_ntop (struct in6_addr
*p
)
80 static char buf
[INET6_ADDRSTRLEN
];
82 inet_ntop (AF_INET6
, p
, buf
, INET6_ADDRSTRLEN
);
88 ripng_route_rte (struct ripng_info
*rinfo
)
90 return (rinfo
->type
== ZEBRA_ROUTE_RIPNG
&& rinfo
->sub_type
== RIPNG_ROUTE_RTE
);
93 /* Allocate new ripng information. */
97 struct ripng_info
*new;
99 new = XCALLOC (MTYPE_RIPNG_ROUTE
, sizeof (struct ripng_info
));
103 /* Free ripng information. */
105 ripng_info_free (struct ripng_info
*rinfo
)
107 XFREE (MTYPE_RIPNG_ROUTE
, rinfo
);
110 /* Create ripng socket. */
112 ripng_make_socket (void)
116 struct sockaddr_in6 ripaddr
;
118 sock
= socket (AF_INET6
, SOCK_DGRAM
, 0);
121 zlog (NULL
, LOG_ERR
, "Can't make ripng socket");
125 ret
= setsockopt_so_recvbuf (sock
, 8096);
128 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
131 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
134 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
137 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
141 memset (&ripaddr
, 0, sizeof (ripaddr
));
142 ripaddr
.sin6_family
= AF_INET6
;
144 ripaddr
.sin6_len
= sizeof (struct sockaddr_in6
);
145 #endif /* SIN6_LEN */
146 ripaddr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
148 if (ripngd_privs
.change (ZPRIVS_RAISE
))
149 zlog_err ("ripng_make_socket: could not raise privs");
151 ret
= bind (sock
, (struct sockaddr
*) &ripaddr
, sizeof (ripaddr
));
154 zlog (NULL
, LOG_ERR
, "Can't bind ripng socket: %s.", safe_strerror (errno
));
155 if (ripngd_privs
.change (ZPRIVS_LOWER
))
156 zlog_err ("ripng_make_socket: could not lower privs");
159 if (ripngd_privs
.change (ZPRIVS_LOWER
))
160 zlog_err ("ripng_make_socket: could not lower privs");
164 /* Send RIPng packet. */
166 ripng_send_packet (caddr_t buf
, int bufsize
, struct sockaddr_in6
*to
,
167 struct interface
*ifp
)
172 struct cmsghdr
*cmsgptr
;
174 struct in6_pktinfo
*pkt
;
175 struct sockaddr_in6 addr
;
177 if (IS_RIPNG_DEBUG_SEND
) {
179 zlog_debug ("send to %s", inet6_ntop (&to
->sin6_addr
));
180 zlog_debug (" send interface %s", ifp
->name
);
181 zlog_debug (" send packet size %d", bufsize
);
184 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
185 addr
.sin6_family
= AF_INET6
;
187 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
188 #endif /* SIN6_LEN */
189 addr
.sin6_flowinfo
= htonl (RIPNG_PRIORITY_DEFAULT
);
191 /* When destination is specified. */
194 addr
.sin6_addr
= to
->sin6_addr
;
195 addr
.sin6_port
= to
->sin6_port
;
199 inet_pton(AF_INET6
, RIPNG_GROUP
, &addr
.sin6_addr
);
200 addr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
203 msg
.msg_name
= (void *) &addr
;
204 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
207 msg
.msg_control
= (void *) adata
;
208 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
211 iov
.iov_len
= bufsize
;
213 cmsgptr
= (struct cmsghdr
*)adata
;
214 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof (struct in6_pktinfo
));
215 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
216 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
218 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
219 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
220 pkt
->ipi6_ifindex
= ifp
->ifindex
;
222 ret
= sendmsg (ripng
->sock
, &msg
, 0);
226 zlog_err ("RIPng send fail on %s to %s: %s", ifp
->name
,
227 inet6_ntop (&to
->sin6_addr
), safe_strerror (errno
));
229 zlog_err ("RIPng send fail on %s: %s", ifp
->name
, safe_strerror (errno
));
235 /* Receive UDP RIPng packet from socket. */
237 ripng_recv_packet (int sock
, u_char
*buf
, int bufsize
,
238 struct sockaddr_in6
*from
, unsigned int *ifindex
,
244 struct cmsghdr
*cmsgptr
;
247 /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this
248 point I can't determine size of cmsghdr */
251 /* Fill in message and iovec. */
252 msg
.msg_name
= (void *) from
;
253 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
256 msg
.msg_control
= (void *) adata
;
257 msg
.msg_controllen
= sizeof adata
;
259 iov
.iov_len
= bufsize
;
261 /* If recvmsg fail return minus value. */
262 ret
= recvmsg (sock
, &msg
, 0);
266 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
267 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
269 /* I want interface index which this packet comes from. */
270 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
271 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
273 struct in6_pktinfo
*ptr
;
275 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
276 *ifindex
= ptr
->ipi6_ifindex
;
277 dst
= ptr
->ipi6_addr
;
280 zlog_warn ("Interface index returned by IPV6_PKTINFO is zero");
283 /* Incoming packet's multicast hop limit. */
284 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
285 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
286 *hoplimit
= *((int *) CMSG_DATA (cmsgptr
));
289 /* Hoplimit check shold be done when destination address is
290 multicast address. */
291 if (! IN6_IS_ADDR_MULTICAST (&dst
))
297 /* Dump rip packet */
299 ripng_packet_dump (struct ripng_packet
*packet
, int size
, const char *sndrcv
)
303 const char *command_str
;
305 /* Set command string. */
306 if (packet
->command
== RIPNG_REQUEST
)
307 command_str
= "request";
308 else if (packet
->command
== RIPNG_RESPONSE
)
309 command_str
= "response";
311 command_str
= "unknown";
313 /* Dump packet header. */
314 zlog_debug ("%s %s version %d packet size %d",
315 sndrcv
, command_str
, packet
->version
, size
);
317 /* Dump each routing table entry. */
320 for (lim
= (caddr_t
) packet
+ size
; (caddr_t
) rte
< lim
; rte
++)
322 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
323 zlog_debug (" nexthop %s/%d", inet6_ntop (&rte
->addr
), rte
->prefixlen
);
325 zlog_debug (" %s/%d metric %d tag %d",
326 inet6_ntop (&rte
->addr
), rte
->prefixlen
,
327 rte
->metric
, ntohs (rte
->tag
));
331 /* RIPng next hop address RTE (Route Table Entry). */
333 ripng_nexthop_rte (struct rte
*rte
,
334 struct sockaddr_in6
*from
,
335 struct ripng_nexthop
*nexthop
)
337 char buf
[INET6_BUFSIZ
];
339 /* Logging before checking RTE. */
340 if (IS_RIPNG_DEBUG_RECV
)
341 zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d",
342 inet6_ntop (&rte
->addr
), ntohs (rte
->tag
), rte
->prefixlen
);
344 /* RFC2080 2.1.1 Next Hop:
345 The route tag and prefix length in the next hop RTE must be
346 set to zero on sending and ignored on receiption. */
347 if (ntohs (rte
->tag
) != 0)
348 zlog_warn ("RIPng nexthop RTE with non zero tag value %d from %s",
349 ntohs (rte
->tag
), inet6_ntop (&from
->sin6_addr
));
351 if (rte
->prefixlen
!= 0)
352 zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
353 rte
->prefixlen
, inet6_ntop (&from
->sin6_addr
));
355 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
356 next hop RTE indicates that the next hop address should be the
357 originator of the RIPng advertisement. An address specified as a
358 next hop must be a link-local address. */
359 if (IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
))
361 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
362 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
366 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
368 nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
369 IPV6_ADDR_COPY (&nexthop
->address
, &rte
->addr
);
373 /* The purpose of the next hop RTE is to eliminate packets being
374 routed through extra hops in the system. It is particularly useful
375 when RIPng is not being run on all of the routers on a network.
376 Note that next hop RTE is "advisory". That is, if the provided
377 information is ignored, a possibly sub-optimal, but absolutely
378 valid, route may be taken. If the received next hop address is not
379 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
380 zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s",
381 inet6_ntop (&rte
->addr
),
382 inet_ntop (AF_INET6
, &from
->sin6_addr
, buf
, INET6_BUFSIZ
));
384 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
385 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
390 /* If ifp has same link-local address then return 1. */
392 ripng_lladdr_check (struct interface
*ifp
, struct in6_addr
*addr
)
394 struct listnode
*listnode
;
395 struct connected
*connected
;
398 for (listnode
= listhead (ifp
->connected
); listnode
; nextnode (listnode
))
399 if ((connected
= getdata (listnode
)) != NULL
)
401 p
= connected
->address
;
403 if (p
->family
== AF_INET6
&&
404 IN6_IS_ADDR_LINKLOCAL (&p
->u
.prefix6
) &&
405 IN6_ARE_ADDR_EQUAL (&p
->u
.prefix6
, addr
))
411 /* RIPng route garbage collect timer. */
413 ripng_garbage_collect (struct thread
*t
)
415 struct ripng_info
*rinfo
;
416 struct route_node
*rp
;
418 rinfo
= THREAD_ARG (t
);
419 rinfo
->t_garbage_collect
= NULL
;
421 /* Off timeout timer. */
422 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
424 /* Get route_node pointer. */
427 /* Unlock route_node. */
429 route_unlock_node (rp
);
431 /* Free RIPng routing information. */
432 ripng_info_free (rinfo
);
437 /* Timeout RIPng routes. */
439 ripng_timeout (struct thread
*t
)
441 struct ripng_info
*rinfo
;
442 struct route_node
*rp
;
444 rinfo
= THREAD_ARG (t
);
445 rinfo
->t_timeout
= NULL
;
447 /* Get route_node pointer. */
450 /* - The garbage-collection timer is set for 120 seconds. */
451 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
, ripng_garbage_collect
,
452 ripng
->garbage_time
);
454 /* Delete this route from the kernel. */
455 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
457 /* - The metric for the route is set to 16 (infinity). This causes
458 the route to be removed from service. */
459 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
460 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
462 /* Aggregate count decrement. */
463 ripng_aggregate_decrement (rp
, rinfo
);
465 /* - The route change flag is to indicate that this entry has been
467 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
469 /* - The output process is signalled to trigger a response. */
470 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
476 ripng_timeout_update (struct ripng_info
*rinfo
)
478 if (rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
480 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
481 RIPNG_TIMER_ON (rinfo
->t_timeout
, ripng_timeout
, ripng
->timeout_time
);
486 ripng_incoming_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
488 struct distribute
*dist
;
489 struct access_list
*alist
;
490 struct prefix_list
*plist
;
492 /* Input distribute-list filtering. */
493 if (ri
->list
[RIPNG_FILTER_IN
])
495 if (access_list_apply (ri
->list
[RIPNG_FILTER_IN
],
496 (struct prefix
*) p
) == FILTER_DENY
)
498 if (IS_RIPNG_DEBUG_PACKET
)
499 zlog_debug ("%s/%d filtered by distribute in",
500 inet6_ntop (&p
->prefix
), p
->prefixlen
);
504 if (ri
->prefix
[RIPNG_FILTER_IN
])
506 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_IN
],
507 (struct prefix
*) p
) == PREFIX_DENY
)
509 if (IS_RIPNG_DEBUG_PACKET
)
510 zlog_debug ("%s/%d filtered by prefix-list in",
511 inet6_ntop (&p
->prefix
), p
->prefixlen
);
516 /* All interface filter check. */
517 dist
= distribute_lookup (NULL
);
520 if (dist
->list
[DISTRIBUTE_IN
])
522 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
526 if (access_list_apply (alist
,
527 (struct prefix
*) p
) == FILTER_DENY
)
529 if (IS_RIPNG_DEBUG_PACKET
)
530 zlog_debug ("%s/%d filtered by distribute in",
531 inet6_ntop (&p
->prefix
), p
->prefixlen
);
536 if (dist
->prefix
[DISTRIBUTE_IN
])
538 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
542 if (prefix_list_apply (plist
,
543 (struct prefix
*) p
) == PREFIX_DENY
)
545 if (IS_RIPNG_DEBUG_PACKET
)
546 zlog_debug ("%s/%d filtered by prefix-list in",
547 inet6_ntop (&p
->prefix
), p
->prefixlen
);
557 ripng_outgoing_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
559 struct distribute
*dist
;
560 struct access_list
*alist
;
561 struct prefix_list
*plist
;
563 if (ri
->list
[RIPNG_FILTER_OUT
])
565 if (access_list_apply (ri
->list
[RIPNG_FILTER_OUT
],
566 (struct prefix
*) p
) == FILTER_DENY
)
568 if (IS_RIPNG_DEBUG_PACKET
)
569 zlog_debug ("%s/%d is filtered by distribute out",
570 inet6_ntop (&p
->prefix
), p
->prefixlen
);
574 if (ri
->prefix
[RIPNG_FILTER_OUT
])
576 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_OUT
],
577 (struct prefix
*) p
) == PREFIX_DENY
)
579 if (IS_RIPNG_DEBUG_PACKET
)
580 zlog_debug ("%s/%d is filtered by prefix-list out",
581 inet6_ntop (&p
->prefix
), p
->prefixlen
);
586 /* All interface filter check. */
587 dist
= distribute_lookup (NULL
);
590 if (dist
->list
[DISTRIBUTE_OUT
])
592 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
596 if (access_list_apply (alist
,
597 (struct prefix
*) p
) == FILTER_DENY
)
599 if (IS_RIPNG_DEBUG_PACKET
)
600 zlog_debug ("%s/%d filtered by distribute out",
601 inet6_ntop (&p
->prefix
), p
->prefixlen
);
606 if (dist
->prefix
[DISTRIBUTE_OUT
])
608 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
612 if (prefix_list_apply (plist
,
613 (struct prefix
*) p
) == PREFIX_DENY
)
615 if (IS_RIPNG_DEBUG_PACKET
)
616 zlog_debug ("%s/%d filtered by prefix-list out",
617 inet6_ntop (&p
->prefix
), p
->prefixlen
);
626 /* Process RIPng route according to RFC2080. */
628 ripng_route_process (struct rte
*rte
, struct sockaddr_in6
*from
,
629 struct ripng_nexthop
*ripng_nexthop
,
630 struct interface
*ifp
)
633 struct prefix_ipv6 p
;
634 struct route_node
*rp
;
635 struct ripng_info
*rinfo
;
636 struct ripng_interface
*ri
;
637 struct in6_addr
*nexthop
;
641 /* Make prefix structure. */
642 memset (&p
, 0, sizeof (struct prefix_ipv6
));
644 /* p.prefix = rte->addr; */
645 IPV6_ADDR_COPY (&p
.prefix
, &rte
->addr
);
646 p
.prefixlen
= rte
->prefixlen
;
648 /* Make sure mask is applied. */
649 /* XXX We have to check the prefix is valid or not before call
651 apply_mask_ipv6 (&p
);
653 /* Apply input filters. */
656 ret
= ripng_incoming_filter (&p
, ri
);
661 if (ri
->routemap
[RIPNG_FILTER_IN
])
664 struct ripng_info newinfo
;
666 memset (&newinfo
, 0, sizeof (struct ripng_info
));
667 newinfo
.type
= ZEBRA_ROUTE_RIPNG
;
668 newinfo
.sub_type
= RIPNG_ROUTE_RTE
;
669 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
670 newinfo
.nexthop
= ripng_nexthop
->address
;
672 newinfo
.nexthop
= from
->sin6_addr
;
673 newinfo
.from
= from
->sin6_addr
;
674 newinfo
.ifindex
= ifp
->ifindex
;
675 newinfo
.metric
= rte
->metric
;
676 newinfo
.metric_out
= rte
->metric
; /* XXX */
677 newinfo
.tag
= ntohs(rte
->tag
); /* XXX */
679 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_IN
],
680 (struct prefix
*)&p
, RMAP_RIPNG
, &newinfo
);
682 if (ret
== RMAP_DENYMATCH
)
684 if (IS_RIPNG_DEBUG_PACKET
)
685 zlog_debug ("RIPng %s/%d is filtered by route-map in",
686 inet6_ntop (&p
.prefix
), p
.prefixlen
);
690 /* Get back the object */
691 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
) {
692 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &ripng_nexthop
->address
) ) {
693 /* the nexthop get changed by the routemap */
694 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
))
695 ripng_nexthop
->address
= newinfo
.nexthop
;
697 ripng_nexthop
->address
= in6addr_any
;
700 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &from
->sin6_addr
) ) {
701 /* the nexthop get changed by the routemap */
702 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
)) {
703 ripng_nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
704 ripng_nexthop
->address
= newinfo
.nexthop
;
708 rte
->tag
= htons(newinfo
.tag_out
); /* XXX */
709 rte
->metric
= newinfo
.metric_out
; /* XXX: the routemap uses the metric_out field */
712 /* Once the entry has been validated, update the metric by
713 * adding the cost of the network on wich the message
714 * arrived. If the result is greater than infinity, use infinity
715 * (RFC2453 Sec. 3.9.2)
718 /* Zebra ripngd can handle offset-list in. */
719 ret
= ripng_offset_list_apply_in (&p
, ifp
, &rte
->metric
);
721 /* If offset-list does not modify the metric use interface's
724 rte
->metric
+= ifp
->metric
;
726 if (rte
->metric
> RIPNG_METRIC_INFINITY
)
727 rte
->metric
= RIPNG_METRIC_INFINITY
;
729 /* Set nexthop pointer. */
730 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
731 nexthop
= &ripng_nexthop
->address
;
733 nexthop
= &from
->sin6_addr
;
735 /* Lookup RIPng routing table. */
736 rp
= route_node_get (ripng
->table
, (struct prefix
*) &p
);
742 /* Redistributed route check. */
743 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
744 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
747 /* Local static route. */
748 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
749 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
750 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
))
751 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
755 if (rp
->info
== NULL
)
757 /* Now, check to see whether there is already an explicit route
758 for the destination prefix. If there is no such route, add
759 this route to the routing table, unless the metric is
760 infinity (there is no point in adding a route which
762 if (rte
->metric
!= RIPNG_METRIC_INFINITY
)
764 rinfo
= ripng_info_new ();
766 /* - Setting the destination prefix and length to those in
771 /* - Setting the metric to the newly calculated metric (as
773 rinfo
->metric
= rte
->metric
;
774 rinfo
->tag
= ntohs (rte
->tag
);
776 /* - Set the next hop address to be the address of the router
777 from which the datagram came or the next hop address
778 specified by a next hop RTE. */
779 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
780 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
781 rinfo
->ifindex
= ifp
->ifindex
;
783 /* - Initialize the timeout for the route. If the
784 garbage-collection timer is running for this route, stop it. */
785 ripng_timeout_update (rinfo
);
787 /* - Set the route change flag. */
788 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
790 /* - Signal the output process to trigger an update (see section
792 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
794 /* Finally, route goes into the kernel. */
795 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
796 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
798 ripng_zebra_ipv6_add (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
799 rinfo
->flags
|= RIPNG_RTF_FIB
;
801 /* Aggregate check. */
802 ripng_aggregate_increment (rp
, rinfo
);
809 /* If there is an existing route, compare the next hop address
810 to the address of the router from which the datagram came.
811 If this datagram is from the same router as the existing
812 route, reinitialize the timeout. */
813 same
= (IN6_ARE_ADDR_EQUAL (&rinfo
->from
, &from
->sin6_addr
)
814 && (rinfo
->ifindex
== ifp
->ifindex
));
817 ripng_timeout_update (rinfo
);
819 /* Next, compare the metrics. If the datagram is from the same
820 router as the existing route, and the new metric is different
821 than the old one; or, if the new metric is lower than the old
822 one; do the following actions: */
823 if ((same
&& rinfo
->metric
!= rte
->metric
) ||
824 rte
->metric
< rinfo
->metric
)
826 /* - Adopt the route from the datagram. That is, put the
827 new metric in, and adjust the next hop address (if
829 oldmetric
= rinfo
->metric
;
830 rinfo
->metric
= rte
->metric
;
831 rinfo
->tag
= ntohs (rte
->tag
);
832 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
833 rinfo
->ifindex
= ifp
->ifindex
;
835 /* Should a new route to this network be established
836 while the garbage-collection timer is running, the
837 new route will replace the one that is about to be
838 deleted. In this case the garbage-collection timer
841 if (oldmetric
== RIPNG_METRIC_INFINITY
&&
842 rinfo
->metric
< RIPNG_METRIC_INFINITY
)
844 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
845 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
847 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
849 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
850 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
852 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
);
853 rinfo
->flags
|= RIPNG_RTF_FIB
;
855 /* The aggregation counter needs to be updated because
856 the prefixes, which are into the gc, have been
857 removed from the aggregator (see ripng_timout). */
858 ripng_aggregate_increment (rp
, rinfo
);
861 /* Update nexthop and/or metric value. */
862 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
864 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
865 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
);
866 rinfo
->flags
|= RIPNG_RTF_FIB
;
868 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
869 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
872 /* - Set the route change flag and signal the output process
873 to trigger an update. */
874 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
875 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
877 /* - If the new metric is infinity, start the deletion
878 process (described above); */
879 if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
881 /* If the new metric is infinity, the deletion process
882 begins for the route, which is no longer used for
883 routing packets. Note that the deletion process is
884 started only when the metric is first set to
885 infinity. If the metric was already infinity, then a
886 new deletion process is not started. */
887 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
889 /* - The garbage-collection timer is set for 120 seconds. */
890 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
891 ripng_garbage_collect
, ripng
->garbage_time
);
892 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
894 /* - The metric for the route is set to 16
895 (infinity). This causes the route to be removed
897 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
898 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
900 /* Aggregate count decrement. */
901 ripng_aggregate_decrement (rp
, rinfo
);
903 /* - The route change flag is to indicate that this
904 entry has been changed. */
905 /* - The output process is signalled to trigger a
907 ; /* Above processes are already done previously. */
912 /* otherwise, re-initialize the timeout. */
913 ripng_timeout_update (rinfo
);
916 /* Unlock tempolary lock of the route. */
917 route_unlock_node (rp
);
921 /* Add redistributed route to RIPng table. */
923 ripng_redistribute_add (int type
, int sub_type
, struct prefix_ipv6
*p
,
924 unsigned int ifindex
, struct in6_addr
*nexthop
)
926 struct route_node
*rp
;
927 struct ripng_info
*rinfo
;
929 /* Redistribute route */
930 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
932 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
934 #if defined (MUSICA) || defined (LINUX)
935 /* XXX As long as the RIPng redistribution is applied to all the connected
936 * routes, one needs to filter the ::/96 prefixes.
937 * However it could be a wanted case, it will be removed soon.
939 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
940 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
942 #endif /* MUSICA or LINUX */
944 rp
= route_node_get (ripng
->table
, (struct prefix
*) p
);
949 if (rinfo
->type
== ZEBRA_ROUTE_CONNECT
950 && rinfo
->sub_type
== RIPNG_ROUTE_INTERFACE
951 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
) {
952 route_unlock_node (rp
);
956 /* Manually configured RIPng route check.
957 * They have the precedence on all the other entries.
959 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
960 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
961 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
)) ) {
962 if (type
!= ZEBRA_ROUTE_RIPNG
|| ((sub_type
!= RIPNG_ROUTE_STATIC
) &&
963 (sub_type
!= RIPNG_ROUTE_DEFAULT
))) {
964 route_unlock_node (rp
);
969 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
970 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
972 /* Tells the other daemons about the deletion of
975 if (ripng_route_rte (rinfo
))
976 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
980 ripng_info_free (rinfo
);
982 route_unlock_node (rp
);
986 rinfo
= ripng_info_new ();
989 rinfo
->sub_type
= sub_type
;
990 rinfo
->ifindex
= ifindex
;
994 if (nexthop
&& IN6_IS_ADDR_LINKLOCAL(nexthop
))
995 rinfo
->nexthop
= *nexthop
;
997 rinfo
->flags
|= RIPNG_RTF_FIB
;
1000 /* Aggregate check. */
1001 ripng_aggregate_increment (rp
, rinfo
);
1003 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1005 if (IS_RIPNG_DEBUG_EVENT
) {
1007 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
1008 inet6_ntop(&p
->prefix
), p
->prefixlen
,
1009 ifindex2ifname(ifindex
));
1011 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1012 inet6_ntop(&p
->prefix
), p
->prefixlen
, inet6_ntop(nexthop
),
1013 ifindex2ifname(ifindex
));
1016 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1019 /* Delete redistributed route to RIPng table. */
1021 ripng_redistribute_delete (int type
, int sub_type
, struct prefix_ipv6
*p
,
1022 unsigned int ifindex
)
1024 struct route_node
*rp
;
1025 struct ripng_info
*rinfo
;
1027 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
1029 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
1031 #if defined (MUSICA) || defined (LINUX)
1032 /* XXX As long as the RIPng redistribution is applied to all the connected
1033 * routes, one needs to filter the ::/96 prefixes.
1034 * However it could be a wanted case, it will be removed soon.
1036 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
1037 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
1039 #endif /* MUSICA or LINUX */
1041 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) p
);
1048 && rinfo
->type
== type
1049 && rinfo
->sub_type
== sub_type
1050 && rinfo
->ifindex
== ifindex
)
1052 /* Perform poisoned reverse. */
1053 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1054 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1055 ripng_garbage_collect
, ripng
->garbage_time
);
1056 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1058 /* Aggregate count decrement. */
1059 ripng_aggregate_decrement (rp
, rinfo
);
1061 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1063 if (IS_RIPNG_DEBUG_EVENT
)
1064 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1065 inet6_ntop(&p
->prefix
), p
->prefixlen
,
1066 ifindex2ifname(ifindex
));
1068 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1073 /* Withdraw redistributed route. */
1075 ripng_redistribute_withdraw (int type
)
1077 struct route_node
*rp
;
1078 struct ripng_info
*rinfo
;
1083 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1084 if ((rinfo
= rp
->info
) != NULL
)
1086 if ((rinfo
->type
== type
)
1087 && (rinfo
->sub_type
!= RIPNG_ROUTE_INTERFACE
))
1089 /* Perform poisoned reverse. */
1090 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1091 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1092 ripng_garbage_collect
, ripng
->garbage_time
);
1093 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1095 /* Aggregate count decrement. */
1096 ripng_aggregate_decrement (rp
, rinfo
);
1098 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1100 if (IS_RIPNG_DEBUG_EVENT
) {
1101 struct prefix_ipv6
*p
= (struct prefix_ipv6
*) &rp
->p
;
1103 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
1104 inet6_ntop(&p
->prefix
), p
->prefixlen
,
1105 ifindex2ifname(rinfo
->ifindex
));
1108 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1113 /* RIP routing information. */
1115 ripng_response_process (struct ripng_packet
*packet
, int size
,
1116 struct sockaddr_in6
*from
, struct interface
*ifp
,
1121 struct ripng_nexthop nexthop
;
1123 /* RFC2080 2.4.2 Response Messages:
1124 The Response must be ignored if it is not from the RIPng port. */
1125 if (ntohs (from
->sin6_port
) != RIPNG_PORT_DEFAULT
)
1127 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
1128 ntohs (from
->sin6_port
), inet6_ntop (&from
->sin6_addr
));
1129 ripng_peer_bad_packet (from
);
1133 /* The datagram's IPv6 source address should be checked to see
1134 whether the datagram is from a valid neighbor; the source of the
1135 datagram must be a link-local address. */
1136 if (! IN6_IS_ADDR_LINKLOCAL(&from
->sin6_addr
))
1138 zlog_warn ("RIPng packet comes from non link local address %s",
1139 inet6_ntop (&from
->sin6_addr
));
1140 ripng_peer_bad_packet (from
);
1144 /* It is also worth checking to see whether the response is from one
1145 of the router's own addresses. Interfaces on broadcast networks
1146 may receive copies of their own multicasts immediately. If a
1147 router processes its own output as new input, confusion is likely,
1148 and such datagrams must be ignored. */
1149 if (ripng_lladdr_check (ifp
, &from
->sin6_addr
))
1151 zlog_warn ("RIPng packet comes from my own link local address %s",
1152 inet6_ntop (&from
->sin6_addr
));
1153 ripng_peer_bad_packet (from
);
1157 /* As an additional check, periodic advertisements must have their
1158 hop counts set to 255, and inbound, multicast packets sent from the
1159 RIPng port (i.e. periodic advertisement or triggered update
1160 packets) must be examined to ensure that the hop count is 255. */
1161 if (hoplimit
>= 0 && hoplimit
!= 255)
1163 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
1164 hoplimit
, inet6_ntop (&from
->sin6_addr
));
1165 ripng_peer_bad_packet (from
);
1169 /* Update RIPng peer. */
1170 ripng_peer_update (from
, packet
->version
);
1172 /* Reset nexthop. */
1173 memset (&nexthop
, 0, sizeof (struct ripng_nexthop
));
1174 nexthop
.flag
= RIPNG_NEXTHOP_UNSPEC
;
1176 /* Set RTE pointer. */
1179 for (lim
= ((caddr_t
) packet
) + size
; (caddr_t
) rte
< lim
; rte
++)
1181 /* First of all, we have to check this RTE is next hop RTE or
1182 not. Next hop RTE is completely different with normal RTE so
1183 we need special treatment. */
1184 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
1186 ripng_nexthop_rte (rte
, from
, &nexthop
);
1190 /* RTE information validation. */
1192 /* - is the destination prefix valid (e.g., not a multicast
1193 prefix and not a link-local address) A link-local address
1194 should never be present in an RTE. */
1195 if (IN6_IS_ADDR_MULTICAST (&rte
->addr
))
1197 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
1198 inet6_ntop (&rte
->addr
), rte
->prefixlen
, rte
->metric
);
1199 ripng_peer_bad_route (from
);
1202 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
1204 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
1205 inet6_ntop (&rte
->addr
), rte
->prefixlen
, rte
->metric
);
1206 ripng_peer_bad_route (from
);
1209 if (IN6_IS_ADDR_LOOPBACK (&rte
->addr
))
1211 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
1212 inet6_ntop (&rte
->addr
), rte
->prefixlen
, rte
->metric
);
1213 ripng_peer_bad_route (from
);
1217 /* - is the prefix length valid (i.e., between 0 and 128,
1219 if (rte
->prefixlen
> 128)
1221 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
1222 inet6_ntop (&rte
->addr
), rte
->prefixlen
,
1223 inet6_ntop (&from
->sin6_addr
), ifp
->name
);
1224 ripng_peer_bad_route (from
);
1228 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1229 if (! (rte
->metric
>= 1 && rte
->metric
<= 16))
1231 zlog_warn ("Invalid metric %d from %s%%%s", rte
->metric
,
1232 inet6_ntop (&from
->sin6_addr
), ifp
->name
);
1233 ripng_peer_bad_route (from
);
1237 /* Vincent: XXX Should we compute the direclty reachable nexthop
1238 * for our RIPng network ?
1241 /* Routing table updates. */
1242 ripng_route_process (rte
, from
, &nexthop
, ifp
);
1246 /* Response to request message. */
1248 ripng_request_process (struct ripng_packet
*packet
,int size
,
1249 struct sockaddr_in6
*from
, struct interface
*ifp
)
1253 struct prefix_ipv6 p
;
1254 struct route_node
*rp
;
1255 struct ripng_info
*rinfo
;
1256 struct ripng_interface
*ri
;
1258 /* Does not reponse to the requests on the loopback interfaces */
1259 if (if_is_loopback (ifp
))
1262 /* Check RIPng process is enabled on this interface. */
1267 /* When passive interface is specified, suppress responses */
1271 /* RIPng peer update. */
1272 ripng_peer_update (from
, packet
->version
);
1274 lim
= ((caddr_t
) packet
) + size
;
1277 /* The Request is processed entry by entry. If there are no
1278 entries, no response is given. */
1279 if (lim
== (caddr_t
) rte
)
1282 /* There is one special case. If there is exactly one entry in the
1283 request, and it has a destination prefix of zero, a prefix length
1284 of zero, and a metric of infinity (i.e., 16), then this is a
1285 request to send the entire routing table. In that case, a call
1286 is made to the output process to send the routing table to the
1287 requesting address/port. */
1288 if (lim
== ((caddr_t
) (rte
+ 1)) &&
1289 IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
) &&
1290 rte
->prefixlen
== 0 &&
1291 rte
->metric
== RIPNG_METRIC_INFINITY
)
1293 /* All route with split horizon */
1294 ripng_output_process (ifp
, from
, ripng_all_route
);
1298 /* Except for this special case, processing is quite simple.
1299 Examine the list of RTEs in the Request one by one. For each
1300 entry, look up the destination in the router's routing
1301 database and, if there is a route, put that route's metric in
1302 the metric field of the RTE. If there is no explicit route
1303 to the specified destination, put infinity in the metric
1304 field. Once all the entries have been filled in, change the
1305 command from Request to Response and send the datagram back
1306 to the requestor. */
1307 memset (&p
, 0, sizeof (struct prefix_ipv6
));
1308 p
.family
= AF_INET6
;
1310 for (; ((caddr_t
) rte
) < lim
; rte
++)
1312 p
.prefix
= rte
->addr
;
1313 p
.prefixlen
= rte
->prefixlen
;
1314 apply_mask_ipv6 (&p
);
1316 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) &p
);
1321 rte
->metric
= rinfo
->metric
;
1322 route_unlock_node (rp
);
1325 rte
->metric
= RIPNG_METRIC_INFINITY
;
1327 packet
->command
= RIPNG_RESPONSE
;
1329 ripng_send_packet ((caddr_t
) packet
, size
, from
, ifp
);
1333 /* First entry point of reading RIPng packet. */
1335 ripng_read (struct thread
*thread
)
1339 struct sockaddr_in6 from
;
1340 struct ripng_packet
*packet
;
1341 unsigned int ifindex
;
1342 struct interface
*ifp
;
1345 /* Check ripng is active and alive. */
1346 assert (ripng
!= NULL
);
1347 assert (ripng
->sock
>= 0);
1349 /* Fetch thread data and set read pointer to empty for event
1350 managing. `sock' sould be same as ripng->sock. */
1351 sock
= THREAD_FD (thread
);
1352 ripng
->t_read
= NULL
;
1354 /* Add myself to the next event. */
1355 ripng_event (RIPNG_READ
, sock
);
1357 /* Read RIPng packet. */
1358 len
= ripng_recv_packet (sock
, STREAM_DATA (ripng
->ibuf
),
1359 STREAM_SIZE (ripng
->ibuf
), &from
, &ifindex
,
1363 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno
));
1367 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1368 (4)) must be multiple size of one RTE size (20). */
1369 if (((len
- 4) % 20) != 0)
1371 zlog_warn ("RIPng invalid packet size %d from %s", len
,
1372 inet6_ntop (&from
.sin6_addr
));
1373 ripng_peer_bad_packet (&from
);
1377 packet
= (struct ripng_packet
*) STREAM_DATA (ripng
->ibuf
);
1378 ifp
= if_lookup_by_index (ifindex
);
1380 /* RIPng packet received. */
1381 if (IS_RIPNG_DEBUG_EVENT
)
1382 zlog_debug ("RIPng packet received from %s port %d on %s",
1383 inet6_ntop (&from
.sin6_addr
), ntohs (from
.sin6_port
),
1384 ifp
? ifp
->name
: "unknown");
1386 /* Logging before packet checking. */
1387 if (IS_RIPNG_DEBUG_RECV
)
1388 ripng_packet_dump (packet
, len
, "RECV");
1390 /* Packet comes from unknown interface. */
1393 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex
);
1397 /* Packet version mismatch checking. */
1398 if (packet
->version
!= ripng
->version
)
1400 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1401 packet
->version
, ripng
->version
);
1402 ripng_peer_bad_packet (&from
);
1406 /* Process RIPng packet. */
1407 switch (packet
->command
)
1410 ripng_request_process (packet
, len
, &from
, ifp
);
1412 case RIPNG_RESPONSE
:
1413 ripng_response_process (packet
, len
, &from
, ifp
, hoplimit
);
1416 zlog_warn ("Invalid RIPng command %d", packet
->command
);
1417 ripng_peer_bad_packet (&from
);
1423 /* Walk down the RIPng routing table then clear changed flag. */
1425 ripng_clear_changed_flag ()
1427 struct route_node
*rp
;
1428 struct ripng_info
*rinfo
;
1430 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1431 if ((rinfo
= rp
->info
) != NULL
)
1432 if (rinfo
->flags
& RIPNG_RTF_CHANGED
)
1433 rinfo
->flags
&= ~RIPNG_RTF_CHANGED
;
1436 /* Regular update of RIPng route. Send all routing formation to RIPng
1437 enabled interface. */
1439 ripng_update (struct thread
*t
)
1441 struct listnode
*node
;
1442 struct interface
*ifp
;
1443 struct ripng_interface
*ri
;
1445 /* Clear update timer thread. */
1446 ripng
->t_update
= NULL
;
1448 /* Logging update event. */
1449 if (IS_RIPNG_DEBUG_EVENT
)
1450 zlog_debug ("RIPng update timer expired!");
1452 /* Supply routes to each interface. */
1453 for (node
= listhead (iflist
); node
; nextnode (node
))
1455 ifp
= getdata (node
);
1458 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1464 /* When passive interface is specified, suppress announce to the
1470 if (ri
->ri_send
== RIPNG_SEND_OFF
)
1472 if (IS_RIPNG_DEBUG_EVENT
)
1473 zlog (NULL
, LOG_DEBUG
,
1474 "[Event] RIPng send to if %d is suppressed by config",
1478 #endif /* RIPNG_ADVANCED */
1480 ripng_output_process (ifp
, NULL
, ripng_all_route
);
1483 /* Triggered updates may be suppressed if a regular update is due by
1484 the time the triggered update would be sent. */
1485 if (ripng
->t_triggered_interval
)
1487 thread_cancel (ripng
->t_triggered_interval
);
1488 ripng
->t_triggered_interval
= NULL
;
1492 /* Reset flush event. */
1493 ripng_event (RIPNG_UPDATE_EVENT
, 0);
1498 /* Triggered update interval timer. */
1500 ripng_triggered_interval (struct thread
*t
)
1502 ripng
->t_triggered_interval
= NULL
;
1507 ripng_triggered_update (t
);
1512 /* Execute triggered update. */
1514 ripng_triggered_update (struct thread
*t
)
1516 struct listnode
*node
;
1517 struct interface
*ifp
;
1518 struct ripng_interface
*ri
;
1521 ripng
->t_triggered_update
= NULL
;
1523 /* Cancel interval timer. */
1524 if (ripng
->t_triggered_interval
)
1526 thread_cancel (ripng
->t_triggered_interval
);
1527 ripng
->t_triggered_interval
= NULL
;
1531 /* Logging triggered update. */
1532 if (IS_RIPNG_DEBUG_EVENT
)
1533 zlog_debug ("RIPng triggered update!");
1535 /* Split Horizon processing is done when generating triggered
1536 updates as well as normal updates (see section 2.6). */
1537 for (node
= listhead (iflist
); node
; nextnode (node
))
1539 ifp
= getdata (node
);
1542 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1548 /* When passive interface is specified, suppress announce to the
1553 ripng_output_process (ifp
, NULL
, ripng_changed_route
);
1556 /* Once all of the triggered updates have been generated, the route
1557 change flags should be cleared. */
1558 ripng_clear_changed_flag ();
1560 /* After a triggered update is sent, a timer should be set for a
1561 random interval between 1 and 5 seconds. If other changes that
1562 would trigger updates occur before the timer expires, a single
1563 update is triggered when the timer expires. */
1564 interval
= (random () % 5) + 1;
1566 ripng
->t_triggered_interval
=
1567 thread_add_timer (master
, ripng_triggered_interval
, NULL
, interval
);
1572 /* Write routing table entry to the stream and return next index of
1573 the routing table entry in the stream. */
1575 ripng_write_rte (int num
, struct stream
*s
, struct prefix_ipv6
*p
,
1576 struct in6_addr
*nexthop
, u_int16_t tag
, u_char metric
)
1578 /* RIPng packet header. */
1581 stream_putc (s
, RIPNG_RESPONSE
);
1582 stream_putc (s
, RIPNG_V1
);
1586 /* Write routing table entry. */
1588 stream_write (s
, (u_char
*) &p
->prefix
, sizeof (struct in6_addr
));
1590 stream_write (s
, (u_char
*) nexthop
, sizeof (struct in6_addr
));
1591 stream_putw (s
, tag
);
1593 stream_putc (s
, p
->prefixlen
);
1596 stream_putc (s
, metric
);
1601 /* Send RESPONSE message to specified destination. */
1603 ripng_output_process (struct interface
*ifp
, struct sockaddr_in6
*to
,
1607 struct route_node
*rp
;
1608 struct ripng_info
*rinfo
;
1609 struct ripng_interface
*ri
;
1610 struct ripng_aggregate
*aggregate
;
1611 struct prefix_ipv6
*p
;
1612 struct list
* ripng_rte_list
;
1614 if (IS_RIPNG_DEBUG_EVENT
) {
1616 zlog_debug ("RIPng update routes to neighbor %s",
1617 inet6_ntop(&to
->sin6_addr
));
1619 zlog_debug ("RIPng update routes on interface %s", ifp
->name
);
1622 /* Get RIPng interface. */
1625 ripng_rte_list
= ripng_rte_new();
1627 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1629 if ((rinfo
= rp
->info
) != NULL
&& rinfo
->suppress
== 0)
1631 /* If no route-map are applied, the RTE will be these following
1634 p
= (struct prefix_ipv6
*) &rp
->p
;
1635 rinfo
->metric_out
= rinfo
->metric
;
1636 rinfo
->tag_out
= rinfo
->tag
;
1637 memset(&rinfo
->nexthop_out
, 0, sizeof(rinfo
->nexthop_out
));
1638 /* In order to avoid some local loops,
1639 * if the RIPng route has a nexthop via this interface, keep the nexthop,
1640 * otherwise set it to 0. The nexthop should not be propagated
1641 * beyond the local broadcast/multicast area in order
1642 * to avoid an IGP multi-level recursive look-up.
1644 if (rinfo
->ifindex
== ifp
->ifindex
)
1645 rinfo
->nexthop_out
= rinfo
->nexthop
;
1647 /* Apply output filters. */
1648 ret
= ripng_outgoing_filter (p
, ri
);
1652 /* Changed route only output. */
1653 if (route_type
== ripng_changed_route
&&
1654 (! (rinfo
->flags
& RIPNG_RTF_CHANGED
)))
1657 /* Split horizon. */
1658 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON
)
1660 /* We perform split horizon for RIPng routes. */
1661 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1662 rinfo
->ifindex
== ifp
->ifindex
)
1666 /* Preparation for route-map. */
1667 rinfo
->metric_set
= 0;
1670 * and tag_out are already initialized.
1673 /* Interface route-map */
1674 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1678 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1679 (struct prefix
*) p
, RMAP_RIPNG
,
1682 if (ret
== RMAP_DENYMATCH
)
1684 if (IS_RIPNG_DEBUG_PACKET
)
1685 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1686 inet6_ntop (&p
->prefix
), p
->prefixlen
);
1692 /* Redistribute route-map. */
1693 if (ripng
->route_map
[rinfo
->type
].name
)
1697 ret
= route_map_apply (ripng
->route_map
[rinfo
->type
].map
,
1698 (struct prefix
*) p
, RMAP_RIPNG
,
1701 if (ret
== RMAP_DENYMATCH
)
1703 if (IS_RIPNG_DEBUG_PACKET
)
1704 zlog_debug ("RIPng %s/%d is filtered by route-map",
1705 inet6_ntop (&p
->prefix
), p
->prefixlen
);
1710 /* When the route-map does not set metric. */
1711 if (! rinfo
->metric_set
)
1713 /* If the redistribute metric is set. */
1714 if (ripng
->route_map
[rinfo
->type
].metric_config
1715 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1717 rinfo
->metric_out
= ripng
->route_map
[rinfo
->type
].metric
;
1721 /* If the route is not connected or localy generated
1722 one, use default-metric value */
1723 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
1724 && rinfo
->type
!= ZEBRA_ROUTE_CONNECT
1725 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1726 rinfo
->metric_out
= ripng
->default_metric
;
1730 /* Apply offset-list */
1731 if (rinfo
->metric_out
!= RIPNG_METRIC_INFINITY
)
1732 ripng_offset_list_apply_out (p
, ifp
, &rinfo
->metric_out
);
1734 if (rinfo
->metric_out
> RIPNG_METRIC_INFINITY
)
1735 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1737 /* Perform split-horizon with poisoned reverse
1740 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON_POISONED_REVERSE
) {
1741 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1742 rinfo
->ifindex
== ifp
->ifindex
)
1743 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1746 /* Add RTE to the list */
1747 ripng_rte_add(ripng_rte_list
, p
, rinfo
, NULL
);
1750 /* Process the aggregated RTE entry */
1751 if ((aggregate
= rp
->aggregate
) != NULL
&&
1752 aggregate
->count
> 0 &&
1753 aggregate
->suppress
== 0)
1755 /* If no route-map are applied, the RTE will be these following
1758 p
= (struct prefix_ipv6
*) &rp
->p
;
1759 aggregate
->metric_set
= 0;
1760 aggregate
->metric_out
= aggregate
->metric
;
1761 aggregate
->tag_out
= aggregate
->tag
;
1762 memset(&aggregate
->nexthop_out
, 0, sizeof(aggregate
->nexthop_out
));
1764 /* Apply output filters.*/
1765 ret
= ripng_outgoing_filter (p
, ri
);
1769 /* Interface route-map */
1770 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1773 struct ripng_info newinfo
;
1775 /* let's cast the aggregate structure to ripng_info */
1776 memset (&newinfo
, 0, sizeof (struct ripng_info
));
1777 /* the nexthop is :: */
1778 newinfo
.metric
= aggregate
->metric
;
1779 newinfo
.metric_out
= aggregate
->metric_out
;
1780 newinfo
.tag
= aggregate
->tag
;
1781 newinfo
.tag_out
= aggregate
->tag_out
;
1783 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1784 (struct prefix
*) p
, RMAP_RIPNG
,
1787 if (ret
== RMAP_DENYMATCH
)
1789 if (IS_RIPNG_DEBUG_PACKET
)
1790 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1791 inet6_ntop (&p
->prefix
), p
->prefixlen
);
1795 aggregate
->metric_out
= newinfo
.metric_out
;
1796 aggregate
->tag_out
= newinfo
.tag_out
;
1797 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop_out
))
1798 aggregate
->nexthop_out
= newinfo
.nexthop_out
;
1801 /* There is no redistribute routemap for the aggregated RTE */
1803 /* Changed route only output. */
1804 /* XXX, vincent, in order to increase time convergence,
1805 * it should be announced if a child has changed.
1807 if (route_type
== ripng_changed_route
)
1810 /* Apply offset-list */
1811 if (aggregate
->metric_out
!= RIPNG_METRIC_INFINITY
)
1812 ripng_offset_list_apply_out (p
, ifp
, &aggregate
->metric_out
);
1814 if (aggregate
->metric_out
> RIPNG_METRIC_INFINITY
)
1815 aggregate
->metric_out
= RIPNG_METRIC_INFINITY
;
1817 /* Add RTE to the list */
1818 ripng_rte_add(ripng_rte_list
, p
, NULL
, aggregate
);
1823 /* Flush the list */
1824 ripng_rte_send(ripng_rte_list
, ifp
, to
);
1825 ripng_rte_free(ripng_rte_list
);
1828 /* Create new RIPng instance and set it to global variable. */
1832 /* ripng should be NULL. */
1833 assert (ripng
== NULL
);
1835 /* Allocaste RIPng instance. */
1836 ripng
= XMALLOC (MTYPE_RIPNG
, sizeof (struct ripng
));
1837 memset (ripng
, 0, sizeof (struct ripng
));
1839 /* Default version and timer values. */
1840 ripng
->version
= RIPNG_V1
;
1841 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
1842 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
1843 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
1844 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
1847 ripng
->ibuf
= stream_new (RIPNG_MAX_PACKET_SIZE
* 5);
1848 ripng
->obuf
= stream_new (RIPNG_MAX_PACKET_SIZE
);
1850 /* Initialize RIPng routig table. */
1851 ripng
->table
= route_table_init ();
1852 ripng
->route
= route_table_init ();
1853 ripng
->aggregate
= route_table_init ();
1856 ripng
->sock
= ripng_make_socket ();
1857 if (ripng
->sock
< 0)
1861 ripng_event (RIPNG_READ
, ripng
->sock
);
1862 ripng_event (RIPNG_UPDATE_EVENT
, 1);
1867 /* Send RIPng request to the interface. */
1869 ripng_request (struct interface
*ifp
)
1872 struct ripng_packet ripng_packet
;
1874 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
1875 if (if_is_loopback(ifp
))
1878 /* If interface is down, don't send RIP packet. */
1879 if (! if_is_up (ifp
))
1882 if (IS_RIPNG_DEBUG_EVENT
)
1883 zlog_debug ("RIPng send request to %s", ifp
->name
);
1885 memset (&ripng_packet
, 0, sizeof (ripng_packet
));
1886 ripng_packet
.command
= RIPNG_REQUEST
;
1887 ripng_packet
.version
= RIPNG_V1
;
1888 rte
= ripng_packet
.rte
;
1889 rte
->metric
= RIPNG_METRIC_INFINITY
;
1891 return ripng_send_packet ((caddr_t
) &ripng_packet
, sizeof (ripng_packet
),
1897 ripng_update_jitter (int time
)
1899 return ((rand () % (time
+ 1)) - (time
/ 2));
1903 ripng_event (enum ripng_event event
, int sock
)
1911 ripng
->t_read
= thread_add_read (master
, ripng_read
, NULL
, sock
);
1913 case RIPNG_UPDATE_EVENT
:
1914 if (ripng
->t_update
)
1916 thread_cancel (ripng
->t_update
);
1917 ripng
->t_update
= NULL
;
1919 /* Update timer jitter. */
1920 jitter
= ripng_update_jitter (ripng
->update_time
);
1923 thread_add_timer (master
, ripng_update
, NULL
,
1924 sock
? 2 : ripng
->update_time
+ jitter
);
1926 case RIPNG_TRIGGERED_UPDATE
:
1927 if (ripng
->t_triggered_interval
)
1929 else if (! ripng
->t_triggered_update
)
1930 ripng
->t_triggered_update
=
1931 thread_add_event (master
, ripng_triggered_update
, NULL
, 0);
1938 /* Each route type's strings and default preference.
1939 * FIXME: ISIS? What are these distance values? */
1944 const char *str_long
;
1948 { ZEBRA_ROUTE_SYSTEM
, "X", "system", 10},
1949 { ZEBRA_ROUTE_KERNEL
, "K", "kernel", 20},
1950 { ZEBRA_ROUTE_CONNECT
, "C", "connected", 30},
1951 { ZEBRA_ROUTE_STATIC
, "S", "static", 40},
1952 { ZEBRA_ROUTE_RIP
, "R", "rip", 50},
1953 { ZEBRA_ROUTE_RIPNG
, "R", "ripng", 50},
1954 { ZEBRA_ROUTE_OSPF
, "O", "ospf", 60},
1955 { ZEBRA_ROUTE_OSPF6
, "O", "ospf6", 60},
1956 { ZEBRA_ROUTE_BGP
, "B", "bgp", 70},
1959 /* Print out routes update time. */
1961 ripng_vty_out_uptime (struct vty
*vty
, struct ripng_info
*rinfo
)
1963 struct timeval timer_now
;
1967 char timebuf
[TIME_BUF
];
1968 struct thread
*thread
;
1970 gettimeofday (&timer_now
, NULL
);
1972 if ((thread
= rinfo
->t_timeout
) != NULL
)
1974 clock
= thread
->u
.sands
.tv_sec
- timer_now
.tv_sec
;
1975 tm
= gmtime (&clock
);
1976 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1977 vty_out (vty
, "%5s", timebuf
);
1979 else if ((thread
= rinfo
->t_garbage_collect
) != NULL
)
1981 clock
= thread
->u
.sands
.tv_sec
- timer_now
.tv_sec
;
1982 tm
= gmtime (&clock
);
1983 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1984 vty_out (vty
, "%5s", timebuf
);
1989 ripng_route_subtype_print (struct ripng_info
*rinfo
)
1994 if (rinfo
->suppress
)
1997 switch (rinfo
->sub_type
)
1999 case RIPNG_ROUTE_RTE
:
2002 case RIPNG_ROUTE_STATIC
:
2005 case RIPNG_ROUTE_DEFAULT
:
2008 case RIPNG_ROUTE_REDISTRIBUTE
:
2011 case RIPNG_ROUTE_INTERFACE
:
2022 DEFUN (show_ipv6_ripng
,
2023 show_ipv6_ripng_cmd
,
2027 "Show RIPng routes\n")
2029 struct route_node
*rp
;
2030 struct ripng_info
*rinfo
;
2031 struct ripng_aggregate
*aggregate
;
2032 struct prefix_ipv6
*p
;
2038 /* Header of display. */
2039 vty_out (vty
, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2041 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2042 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2043 " Network Next Hop Via Metric Tag Time%s",
2044 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2045 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
2047 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2049 if ((aggregate
= rp
->aggregate
) != NULL
)
2051 p
= (struct prefix_ipv6
*) &rp
->p
;
2054 len
= vty_out (vty
, "R(a) %d/%d %s/%d ",
2055 aggregate
->count
, aggregate
->suppress
,
2056 inet6_ntop (&p
->prefix
), p
->prefixlen
);
2058 len
= vty_out (vty
, "R(a) %s/%d ",
2059 inet6_ntop (&p
->prefix
), p
->prefixlen
);
2061 vty_out (vty
, "%s", VTY_NEWLINE
);
2062 vty_out (vty
, "%*s", 18, " ");
2064 vty_out (vty
, "%*s", 28, " ");
2065 vty_out (vty
, "self %2d %3d%s", aggregate
->metric
,
2070 if ((rinfo
= rp
->info
) != NULL
)
2072 p
= (struct prefix_ipv6
*) &rp
->p
;
2075 len
= vty_out (vty
, "%s(%s) 0/%d %s/%d ",
2076 route_info
[rinfo
->type
].str
,
2077 ripng_route_subtype_print(rinfo
),
2079 inet6_ntop (&p
->prefix
), p
->prefixlen
);
2081 len
= vty_out (vty
, "%s(%s) %s/%d ",
2082 route_info
[rinfo
->type
].str
,
2083 ripng_route_subtype_print(rinfo
),
2084 inet6_ntop (&p
->prefix
), p
->prefixlen
);
2086 vty_out (vty
, "%s", VTY_NEWLINE
);
2087 vty_out (vty
, "%*s", 18, " ");
2088 len
= vty_out (vty
, "%s", inet6_ntop (&rinfo
->nexthop
));
2092 len
= vty_out (vty
, "%*s", len
, " ");
2095 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2096 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2098 len
= vty_out (vty
, "%s", ifindex2ifname(rinfo
->ifindex
));
2099 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2101 len
= vty_out (vty
, "kill");
2103 len
= vty_out (vty
, "self");
2107 vty_out (vty
, "%*s", len
, " ");
2109 vty_out (vty
, " %2d %3d ",
2110 rinfo
->metric
, rinfo
->tag
);
2113 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2114 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2116 /* RTE from remote RIP routers */
2117 ripng_vty_out_uptime (vty
, rinfo
);
2118 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2120 /* poisonous reversed routes (gc) */
2121 ripng_vty_out_uptime (vty
, rinfo
);
2124 vty_out (vty
, "%s", VTY_NEWLINE
);
2131 /* Return next event time. */
2133 ripng_next_thread_timer (struct thread
*thread
)
2135 struct timeval timer_now
;
2137 gettimeofday (&timer_now
, NULL
);
2139 return thread
->u
.sands
.tv_sec
- timer_now
.tv_sec
;
2142 DEFUN (show_ipv6_ripng_status
,
2143 show_ipv6_ripng_status_cmd
,
2144 "show ipv6 ripng status",
2147 "Show RIPng routes\n"
2148 "IPv6 routing protocol process parameters and statistics\n")
2150 struct listnode
*node
;
2151 int ripng_network_write (struct vty
*, int);
2152 void ripng_redistribute_write (struct vty
*, int);
2157 vty_out (vty
, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE
);
2158 vty_out (vty
, " Sending updates every %ld seconds with +/-50%%,",
2159 ripng
->update_time
);
2160 vty_out (vty
, " next due in %d seconds%s",
2161 ripng_next_thread_timer (ripng
->t_update
),
2163 vty_out (vty
, " Timeout after %ld seconds,", ripng
->timeout_time
);
2164 vty_out (vty
, " garbage collect after %ld seconds%s", ripng
->garbage_time
,
2167 /* Filtering status show. */
2168 config_show_distribute (vty
);
2170 /* Default metric information. */
2171 vty_out (vty
, " Default redistribution metric is %d%s",
2172 ripng
->default_metric
, VTY_NEWLINE
);
2174 /* Redistribute information. */
2175 vty_out (vty
, " Redistributing:");
2176 ripng_redistribute_write (vty
, 0);
2177 vty_out (vty
, "%s", VTY_NEWLINE
);
2179 vty_out (vty
, " Default version control: send version %d,", ripng
->version
);
2180 vty_out (vty
, " receive version %d %s", ripng
->version
,
2183 vty_out (vty
, " Interface Send Recv%s", VTY_NEWLINE
);
2185 for (node
= listhead (iflist
); node
; node
= nextnode (node
))
2187 struct ripng_interface
*ri
;
2188 struct interface
*ifp
;
2190 ifp
= getdata (node
);
2193 if (ri
->enable_network
|| ri
->enable_interface
)
2196 vty_out (vty
, " %-17s%-3d %-3d%s", ifp
->name
,
2203 vty_out (vty
, " Routing for Networks:%s", VTY_NEWLINE
);
2204 ripng_network_write (vty
, 0);
2206 vty_out (vty
, " Routing Information Sources:%s", VTY_NEWLINE
);
2207 vty_out (vty
, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE
);
2208 ripng_peer_display (vty
);
2213 DEFUN (router_ripng
,
2216 "Enable a routing process\n"
2217 "Make RIPng instance command\n")
2221 vty
->node
= RIPNG_NODE
;
2225 ret
= ripng_create ();
2227 /* Notice to user we couldn't create RIPng. */
2230 zlog_warn ("can't create RIPng");
2238 DEFUN (no_router_ripng
,
2239 no_router_ripng_cmd
,
2242 "Enable a routing process\n"
2243 "Make RIPng instance command\n")
2253 "Static route setup\n"
2254 "Set static RIPng route announcement\n")
2257 struct prefix_ipv6 p
;
2258 struct route_node
*rp
;
2260 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2263 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2266 apply_mask_ipv6 (&p
);
2268 rp
= route_node_get (ripng
->route
, (struct prefix
*) &p
);
2271 vty_out (vty
, "There is already same static route.%s", VTY_NEWLINE
);
2272 route_unlock_node (rp
);
2275 rp
->info
= (void *)1;
2277 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0, NULL
);
2282 DEFUN (no_ripng_route
,
2284 "no route IPV6ADDR",
2286 "Static route setup\n"
2287 "Delete static RIPng route announcement\n")
2290 struct prefix_ipv6 p
;
2291 struct route_node
*rp
;
2293 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2296 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2299 apply_mask_ipv6 (&p
);
2301 rp
= route_node_lookup (ripng
->route
, (struct prefix
*) &p
);
2304 vty_out (vty
, "Can't find static route.%s", VTY_NEWLINE
);
2308 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0);
2309 route_unlock_node (rp
);
2312 route_unlock_node (rp
);
2317 DEFUN (ripng_aggregate_address
,
2318 ripng_aggregate_address_cmd
,
2319 "aggregate-address X:X::X:X/M",
2320 "Set aggregate RIPng route announcement\n"
2321 "Aggregate network\n")
2325 struct route_node
*node
;
2327 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2330 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2334 /* Check aggregate alredy exist or not. */
2335 node
= route_node_get (ripng
->aggregate
, &p
);
2338 vty_out (vty
, "There is already same aggregate route.%s", VTY_NEWLINE
);
2339 route_unlock_node (node
);
2342 node
->info
= (void *)1;
2344 ripng_aggregate_add (&p
);
2349 DEFUN (no_ripng_aggregate_address
,
2350 no_ripng_aggregate_address_cmd
,
2351 "no aggregate-address X:X::X:X/M",
2353 "Delete aggregate RIPng route announcement\n"
2354 "Aggregate network")
2358 struct route_node
*rn
;
2360 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &p
);
2363 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2367 rn
= route_node_lookup (ripng
->aggregate
, &p
);
2370 vty_out (vty
, "Can't find aggregate route.%s", VTY_NEWLINE
);
2373 route_unlock_node (rn
);
2375 route_unlock_node (rn
);
2377 ripng_aggregate_delete (&p
);
2382 DEFUN (ripng_default_metric
,
2383 ripng_default_metric_cmd
,
2384 "default-metric <1-16>",
2385 "Set a metric of redistribute routes\n"
2390 ripng
->default_metric
= atoi (argv
[0]);
2395 DEFUN (no_ripng_default_metric
,
2396 no_ripng_default_metric_cmd
,
2397 "no default-metric",
2399 "Set a metric of redistribute routes\n"
2404 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
2409 ALIAS (no_ripng_default_metric
,
2410 no_ripng_default_metric_val_cmd
,
2411 "no default-metric <1-16>",
2413 "Set a metric of redistribute routes\n"
2417 /* RIPng update timer setup. */
2418 DEFUN (ripng_update_timer
,
2419 ripng_update_timer_cmd
,
2420 "update-timer SECOND",
2421 "Set RIPng update timer in seconds\n"
2424 unsigned long update
;
2425 char *endptr
= NULL
;
2427 update
= strtoul (argv
[0], &endptr
, 10);
2428 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2430 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2434 ripng
->update_time
= update
;
2436 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2440 DEFUN (no_ripng_update_timer
,
2441 no_ripng_update_timer_cmd
,
2442 "no update-timer SECOND",
2444 "Unset RIPng update timer in seconds\n"
2447 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2448 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2452 /* RIPng timeout timer setup. */
2453 DEFUN (ripng_timeout_timer
,
2454 ripng_timeout_timer_cmd
,
2455 "timeout-timer SECOND",
2456 "Set RIPng timeout timer in seconds\n"
2459 unsigned long timeout
;
2460 char *endptr
= NULL
;
2462 timeout
= strtoul (argv
[0], &endptr
, 10);
2463 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2465 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2469 ripng
->timeout_time
= timeout
;
2474 DEFUN (no_ripng_timeout_timer
,
2475 no_ripng_timeout_timer_cmd
,
2476 "no timeout-timer SECOND",
2478 "Unset RIPng timeout timer in seconds\n"
2481 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2485 /* RIPng garbage timer setup. */
2486 DEFUN (ripng_garbage_timer
,
2487 ripng_garbage_timer_cmd
,
2488 "garbage-timer SECOND",
2489 "Set RIPng garbage timer in seconds\n"
2492 unsigned long garbage
;
2493 char *endptr
= NULL
;
2495 garbage
= strtoul (argv
[0], &endptr
, 10);
2496 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2498 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2502 ripng
->garbage_time
= garbage
;
2507 DEFUN (no_ripng_garbage_timer
,
2508 no_ripng_garbage_timer_cmd
,
2509 "no garbage-timer SECOND",
2511 "Unset RIPng garbage timer in seconds\n"
2514 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2519 DEFUN (ripng_timers
,
2521 "timers basic <0-65535> <0-65535> <0-65535>",
2522 "RIPng timers setup\n"
2524 "Routing table update timer value in second. Default is 30.\n"
2525 "Routing information timeout timer. Default is 180.\n"
2526 "Garbage collection timer. Default is 120.\n")
2528 unsigned long update
;
2529 unsigned long timeout
;
2530 unsigned long garbage
;
2531 char *endptr
= NULL
;
2533 update
= strtoul (argv
[0], &endptr
, 10);
2534 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2536 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2540 timeout
= strtoul (argv
[1], &endptr
, 10);
2541 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2543 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2547 garbage
= strtoul (argv
[2], &endptr
, 10);
2548 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2550 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2554 /* Set each timer value. */
2555 ripng
->update_time
= update
;
2556 ripng
->timeout_time
= timeout
;
2557 ripng
->garbage_time
= garbage
;
2559 /* Reset update timer thread. */
2560 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2565 DEFUN (no_ripng_timers
,
2566 no_ripng_timers_cmd
,
2569 "RIPng timers setup\n"
2572 /* Set each timer value to the default. */
2573 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2574 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2575 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2577 /* Reset update timer thread. */
2578 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2583 ALIAS (no_ripng_timers
,
2584 no_ripng_timers_val_cmd
,
2585 "no timers basic <0-65535> <0-65535> <0-65535>",
2587 "RIPng timers setup\n"
2589 "Routing table update timer value in second. Default is 30.\n"
2590 "Routing information timeout timer. Default is 180.\n"
2591 "Garbage collection timer. Default is 120.\n")
2593 DEFUN (show_ipv6_protocols
, show_ipv6_protocols_cmd
,
2594 "show ipv6 protocols",
2597 "Routing protocol information")
2602 vty_out (vty
, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE
);
2604 vty_out (vty
, "Sending updates every %ld seconds, next due in %d seconds%s",
2605 ripng
->update_time
, 0,
2608 vty_out (vty
, "Timerout after %ld seconds, garbage correct %ld%s",
2609 ripng
->timeout_time
,
2610 ripng
->garbage_time
,
2613 vty_out (vty
, "Outgoing update filter list for all interfaces is not set");
2614 vty_out (vty
, "Incoming update filter list for all interfaces is not set");
2619 /* Please be carefull to use this command. */
2620 DEFUN (ripng_default_information_originate
,
2621 ripng_default_information_originate_cmd
,
2622 "default-information originate",
2623 "Default route information\n"
2624 "Distribute default route\n")
2626 struct prefix_ipv6 p
;
2628 if (! ripng
->default_information
) {
2629 ripng
->default_information
= 1;
2631 str2prefix_ipv6 ("::/0", &p
);
2632 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0, NULL
);
2638 DEFUN (no_ripng_default_information_originate
,
2639 no_ripng_default_information_originate_cmd
,
2640 "no default-information originate",
2642 "Default route information\n"
2643 "Distribute default route\n")
2645 struct prefix_ipv6 p
;
2647 if (ripng
->default_information
) {
2648 ripng
->default_information
= 0;
2650 str2prefix_ipv6 ("::/0", &p
);
2651 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0);
2657 /* RIPng configuration write function. */
2659 ripng_config_write (struct vty
*vty
)
2661 int ripng_network_write (struct vty
*, int);
2662 void ripng_redistribute_write (struct vty
*, int);
2664 struct route_node
*rp
;
2670 vty_out (vty
, "router ripng%s", VTY_NEWLINE
);
2672 if (ripng
->default_information
)
2673 vty_out (vty
, " default-information originate%s", VTY_NEWLINE
);
2675 ripng_network_write (vty
, 1);
2677 /* RIPng default metric configuration */
2678 if (ripng
->default_metric
!= RIPNG_DEFAULT_METRIC_DEFAULT
)
2679 vty_out (vty
, " default-metric %d%s",
2680 ripng
->default_metric
, VTY_NEWLINE
);
2682 ripng_redistribute_write (vty
, 1);
2684 /* RIP offset-list configuration. */
2685 config_write_ripng_offset_list (vty
);
2687 /* RIPng aggregate routes. */
2688 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2689 if (rp
->info
!= NULL
)
2690 vty_out (vty
, " aggregate-address %s/%d%s",
2691 inet6_ntop (&rp
->p
.u
.prefix6
),
2696 /* RIPng static routes. */
2697 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2698 if (rp
->info
!= NULL
)
2699 vty_out (vty
, " route %s/%d%s", inet6_ntop (&rp
->p
.u
.prefix6
),
2703 /* RIPng timers configuration. */
2704 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
||
2705 ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
||
2706 ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2708 vty_out (vty
, " timers basic %ld %ld %ld%s",
2710 ripng
->timeout_time
,
2711 ripng
->garbage_time
,
2715 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
)
2716 vty_out (vty
, " update-timer %d%s", ripng
->update_time
,
2718 if (ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
)
2719 vty_out (vty
, " timeout-timer %d%s", ripng
->timeout_time
,
2721 if (ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2722 vty_out (vty
, " garbage-timer %d%s", ripng
->garbage_time
,
2726 write
+= config_write_distribute (vty
);
2728 write
+= config_write_if_rmap (vty
);
2735 /* RIPng node structure. */
2736 struct cmd_node cmd_ripng_node
=
2739 "%s(config-router)# ",
2744 ripng_distribute_update (struct distribute
*dist
)
2746 struct interface
*ifp
;
2747 struct ripng_interface
*ri
;
2748 struct access_list
*alist
;
2749 struct prefix_list
*plist
;
2754 ifp
= if_lookup_by_name (dist
->ifname
);
2760 if (dist
->list
[DISTRIBUTE_IN
])
2762 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
2764 ri
->list
[RIPNG_FILTER_IN
] = alist
;
2766 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2769 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2771 if (dist
->list
[DISTRIBUTE_OUT
])
2773 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
2775 ri
->list
[RIPNG_FILTER_OUT
] = alist
;
2777 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2780 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2782 if (dist
->prefix
[DISTRIBUTE_IN
])
2784 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
2786 ri
->prefix
[RIPNG_FILTER_IN
] = plist
;
2788 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2791 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2793 if (dist
->prefix
[DISTRIBUTE_OUT
])
2795 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
2797 ri
->prefix
[RIPNG_FILTER_OUT
] = plist
;
2799 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2802 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2806 ripng_distribute_update_interface (struct interface
*ifp
)
2808 struct distribute
*dist
;
2810 dist
= distribute_lookup (ifp
->name
);
2812 ripng_distribute_update (dist
);
2815 /* Update all interface's distribute list. */
2817 ripng_distribute_update_all (struct prefix_list
*notused
)
2819 struct interface
*ifp
;
2820 struct listnode
*node
;
2822 for (node
= listhead (iflist
); node
; nextnode (node
))
2824 ifp
= getdata (node
);
2825 ripng_distribute_update_interface (ifp
);
2830 ripng_distribute_update_all_wrapper (struct access_list
*notused
)
2832 ripng_distribute_update_all(NULL
);
2835 /* delete all the added ripng routes. */
2840 struct route_node
*rp
;
2841 struct ripng_info
*rinfo
;
2844 /* Clear RIPng routes */
2845 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
)) {
2846 if ((rinfo
= rp
->info
) != NULL
) {
2847 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2848 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2849 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
,
2850 &rinfo
->nexthop
, rinfo
->metric
);
2852 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
2853 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
2856 route_unlock_node (rp
);
2858 ripng_info_free(rinfo
);
2862 /* Cancel the RIPng timers */
2863 RIPNG_TIMER_OFF (ripng
->t_update
);
2864 RIPNG_TIMER_OFF (ripng
->t_triggered_update
);
2865 RIPNG_TIMER_OFF (ripng
->t_triggered_interval
);
2867 /* Cancel the read thread */
2868 if (ripng
->t_read
) {
2869 thread_cancel (ripng
->t_read
);
2870 ripng
->t_read
= NULL
;
2873 /* Close the RIPng socket */
2874 if (ripng
->sock
>= 0) {
2879 /* Static RIPng route configuration. */
2880 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2883 route_unlock_node (rp
);
2886 /* RIPng aggregated prefixes */
2887 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2890 route_unlock_node (rp
);
2893 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2894 if (ripng
->route_map
[i
].name
)
2895 free (ripng
->route_map
[i
].name
);
2897 XFREE (MTYPE_ROUTE_TABLE
, ripng
->table
);
2898 XFREE (MTYPE_ROUTE_TABLE
, ripng
->route
);
2899 XFREE (MTYPE_ROUTE_TABLE
, ripng
->aggregate
);
2901 XFREE (MTYPE_RIPNG
, ripng
);
2905 ripng_clean_network();
2906 ripng_passive_interface_clean ();
2907 ripng_offset_clean ();
2908 ripng_interface_clean ();
2909 ripng_redistribute_clean ();
2912 /* Reset all values to the default settings. */
2916 /* Call ripd related reset functions. */
2917 ripng_debug_reset ();
2918 ripng_route_map_reset ();
2920 /* Call library reset functions. */
2922 access_list_reset ();
2923 prefix_list_reset ();
2925 distribute_list_reset ();
2927 ripng_interface_reset ();
2929 ripng_zclient_reset ();
2933 ripng_if_rmap_update (struct if_rmap
*if_rmap
)
2935 struct interface
*ifp
;
2936 struct ripng_interface
*ri
;
2937 struct route_map
*rmap
;
2939 ifp
= if_lookup_by_name (if_rmap
->ifname
);
2945 if (if_rmap
->routemap
[IF_RMAP_IN
])
2947 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_IN
]);
2949 ri
->routemap
[IF_RMAP_IN
] = rmap
;
2951 ri
->routemap
[IF_RMAP_IN
] = NULL
;
2954 ri
->routemap
[RIPNG_FILTER_IN
] = NULL
;
2956 if (if_rmap
->routemap
[IF_RMAP_OUT
])
2958 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_OUT
]);
2960 ri
->routemap
[IF_RMAP_OUT
] = rmap
;
2962 ri
->routemap
[IF_RMAP_OUT
] = NULL
;
2965 ri
->routemap
[RIPNG_FILTER_OUT
] = NULL
;
2969 ripng_if_rmap_update_interface (struct interface
*ifp
)
2971 struct if_rmap
*if_rmap
;
2973 if_rmap
= if_rmap_lookup (ifp
->name
);
2975 ripng_if_rmap_update (if_rmap
);
2979 ripng_routemap_update_redistribute (void)
2985 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2987 if (ripng
->route_map
[i
].name
)
2988 ripng
->route_map
[i
].map
=
2989 route_map_lookup_by_name (ripng
->route_map
[i
].name
);
2995 ripng_routemap_update (const char *unused
)
2997 struct interface
*ifp
;
2998 struct listnode
*node
;
3000 for (node
= listhead (iflist
); node
; nextnode (node
))
3002 ifp
= getdata (node
);
3003 ripng_if_rmap_update_interface (ifp
);
3006 ripng_routemap_update_redistribute ();
3009 /* Initialize ripng structure and set commands. */
3014 srand (time (NULL
));
3016 /* Install RIPNG_NODE. */
3017 install_node (&cmd_ripng_node
, ripng_config_write
);
3019 /* Install ripng commands. */
3020 install_element (VIEW_NODE
, &show_ipv6_ripng_cmd
);
3021 install_element (VIEW_NODE
, &show_ipv6_ripng_status_cmd
);
3023 install_element (ENABLE_NODE
, &show_ipv6_ripng_cmd
);
3024 install_element (ENABLE_NODE
, &show_ipv6_ripng_status_cmd
);
3026 install_element (CONFIG_NODE
, &router_ripng_cmd
);
3027 install_element (CONFIG_NODE
, &no_router_ripng_cmd
);
3029 install_default (RIPNG_NODE
);
3030 install_element (RIPNG_NODE
, &ripng_route_cmd
);
3031 install_element (RIPNG_NODE
, &no_ripng_route_cmd
);
3032 install_element (RIPNG_NODE
, &ripng_aggregate_address_cmd
);
3033 install_element (RIPNG_NODE
, &no_ripng_aggregate_address_cmd
);
3035 install_element (RIPNG_NODE
, &ripng_default_metric_cmd
);
3036 install_element (RIPNG_NODE
, &no_ripng_default_metric_cmd
);
3037 install_element (RIPNG_NODE
, &no_ripng_default_metric_val_cmd
);
3039 install_element (RIPNG_NODE
, &ripng_timers_cmd
);
3040 install_element (RIPNG_NODE
, &no_ripng_timers_cmd
);
3041 install_element (RIPNG_NODE
, &no_ripng_timers_val_cmd
);
3043 install_element (RIPNG_NODE
, &ripng_update_timer_cmd
);
3044 install_element (RIPNG_NODE
, &no_ripng_update_timer_cmd
);
3045 install_element (RIPNG_NODE
, &ripng_timeout_timer_cmd
);
3046 install_element (RIPNG_NODE
, &no_ripng_timeout_timer_cmd
);
3047 install_element (RIPNG_NODE
, &ripng_garbage_timer_cmd
);
3048 install_element (RIPNG_NODE
, &no_ripng_garbage_timer_cmd
);
3051 install_element (RIPNG_NODE
, &ripng_default_information_originate_cmd
);
3052 install_element (RIPNG_NODE
, &no_ripng_default_information_originate_cmd
);
3055 ripng_debug_init ();
3057 /* Access list install. */
3058 access_list_init ();
3059 access_list_add_hook (ripng_distribute_update_all_wrapper
);
3060 access_list_delete_hook (ripng_distribute_update_all_wrapper
);
3062 /* Prefix list initialize.*/
3063 prefix_list_init ();
3064 prefix_list_add_hook (ripng_distribute_update_all
);
3065 prefix_list_delete_hook (ripng_distribute_update_all
);
3067 /* Distribute list install. */
3068 distribute_list_init (RIPNG_NODE
);
3069 distribute_list_add_hook (ripng_distribute_update
);
3070 distribute_list_delete_hook (ripng_distribute_update
);
3072 /* Route-map for interface. */
3073 ripng_route_map_init ();
3074 ripng_offset_init ();
3076 route_map_add_hook (ripng_routemap_update
);
3077 route_map_delete_hook (ripng_routemap_update
);
3079 if_rmap_init (RIPNG_NODE
);
3080 if_rmap_hook_add (ripng_if_rmap_update
);
3081 if_rmap_hook_delete (ripng_if_rmap_update
);