2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
34 #include "distribute.h"
40 #include "ripngd/ripngd.h"
41 #include "ripngd/ripng_route.h"
42 #include "ripngd/ripng_debug.h"
43 #include "ripngd/ripng_nexthop.h"
45 /* RIPng structure which includes many parameters related to RIPng
46 protocol. If ripng couldn't active or ripng doesn't configured,
47 ripng->fd must be negative value. */
48 struct ripng
*ripng
= NULL
;
56 extern struct zebra_privs_t ripngd_privs
;
60 ripng_output_process (struct interface
*, struct sockaddr_in6
*, int);
63 ripng_triggered_update (struct thread
*);
65 /* RIPng next hop specification. */
68 enum ripng_nexthop_type
73 struct in6_addr address
;
77 ripng_route_rte (struct ripng_info
*rinfo
)
79 return (rinfo
->type
== ZEBRA_ROUTE_RIPNG
&& rinfo
->sub_type
== RIPNG_ROUTE_RTE
);
82 /* Allocate new ripng information. */
86 struct ripng_info
*new;
88 new = XCALLOC (MTYPE_RIPNG_ROUTE
, sizeof (struct ripng_info
));
92 /* Free ripng information. */
94 ripng_info_free (struct ripng_info
*rinfo
)
96 XFREE (MTYPE_RIPNG_ROUTE
, rinfo
);
99 /* Create ripng socket. */
101 ripng_make_socket (void)
105 struct sockaddr_in6 ripaddr
;
107 sock
= socket (AF_INET6
, SOCK_DGRAM
, 0);
110 zlog (NULL
, LOG_ERR
, "Can't make ripng socket");
114 ret
= setsockopt_so_recvbuf (sock
, 8096);
117 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
120 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
123 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
126 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
130 memset (&ripaddr
, 0, sizeof (ripaddr
));
131 ripaddr
.sin6_family
= AF_INET6
;
133 ripaddr
.sin6_len
= sizeof (struct sockaddr_in6
);
134 #endif /* SIN6_LEN */
135 ripaddr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
137 if (ripngd_privs
.change (ZPRIVS_RAISE
))
138 zlog_err ("ripng_make_socket: could not raise privs");
140 ret
= bind (sock
, (struct sockaddr
*) &ripaddr
, sizeof (ripaddr
));
143 zlog (NULL
, LOG_ERR
, "Can't bind ripng socket: %s.", safe_strerror (errno
));
144 if (ripngd_privs
.change (ZPRIVS_LOWER
))
145 zlog_err ("ripng_make_socket: could not lower privs");
148 if (ripngd_privs
.change (ZPRIVS_LOWER
))
149 zlog_err ("ripng_make_socket: could not lower privs");
153 /* Send RIPng packet. */
155 ripng_send_packet (caddr_t buf
, int bufsize
, struct sockaddr_in6
*to
,
156 struct interface
*ifp
)
161 struct cmsghdr
*cmsgptr
;
163 struct in6_pktinfo
*pkt
;
164 struct sockaddr_in6 addr
;
166 if (IS_RIPNG_DEBUG_SEND
) {
168 zlog_debug ("send to %s", inet6_ntoa (&to
->sin6_addr
));
169 zlog_debug (" send interface %s", ifp
->name
);
170 zlog_debug (" send packet size %d", bufsize
);
173 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
174 addr
.sin6_family
= AF_INET6
;
176 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
177 #endif /* SIN6_LEN */
178 addr
.sin6_flowinfo
= htonl (RIPNG_PRIORITY_DEFAULT
);
180 /* When destination is specified. */
183 addr
.sin6_addr
= to
->sin6_addr
;
184 addr
.sin6_port
= to
->sin6_port
;
188 inet_pton(AF_INET6
, RIPNG_GROUP
, &addr
.sin6_addr
);
189 addr
.sin6_port
= htons (RIPNG_PORT_DEFAULT
);
192 msg
.msg_name
= (void *) &addr
;
193 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
196 msg
.msg_control
= (void *) adata
;
197 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
200 iov
.iov_len
= bufsize
;
202 cmsgptr
= (struct cmsghdr
*)adata
;
203 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof (struct in6_pktinfo
));
204 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
205 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
207 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
208 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
209 pkt
->ipi6_ifindex
= ifp
->ifindex
;
211 ret
= sendmsg (ripng
->sock
, &msg
, 0);
215 zlog_err ("RIPng send fail on %s to %s: %s", ifp
->name
,
216 inet6_ntoa (&to
->sin6_addr
), safe_strerror (errno
));
218 zlog_err ("RIPng send fail on %s: %s", ifp
->name
, safe_strerror (errno
));
224 /* Receive UDP RIPng packet from socket. */
226 ripng_recv_packet (int sock
, u_char
*buf
, int bufsize
,
227 struct sockaddr_in6
*from
, unsigned int *ifindex
,
233 struct cmsghdr
*cmsgptr
;
236 /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this
237 point I can't determine size of cmsghdr */
240 /* Fill in message and iovec. */
241 msg
.msg_name
= (void *) from
;
242 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
245 msg
.msg_control
= (void *) adata
;
246 msg
.msg_controllen
= sizeof adata
;
248 iov
.iov_len
= bufsize
;
250 /* If recvmsg fail return minus value. */
251 ret
= recvmsg (sock
, &msg
, 0);
255 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
256 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
258 /* I want interface index which this packet comes from. */
259 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
260 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
262 struct in6_pktinfo
*ptr
;
264 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
265 *ifindex
= ptr
->ipi6_ifindex
;
266 dst
= ptr
->ipi6_addr
;
269 zlog_warn ("Interface index returned by IPV6_PKTINFO is zero");
272 /* Incoming packet's multicast hop limit. */
273 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
274 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
275 *hoplimit
= *((int *) CMSG_DATA (cmsgptr
));
278 /* Hoplimit check shold be done when destination address is
279 multicast address. */
280 if (! IN6_IS_ADDR_MULTICAST (&dst
))
286 /* Dump rip packet */
288 ripng_packet_dump (struct ripng_packet
*packet
, int size
, const char *sndrcv
)
292 const char *command_str
;
294 /* Set command string. */
295 if (packet
->command
== RIPNG_REQUEST
)
296 command_str
= "request";
297 else if (packet
->command
== RIPNG_RESPONSE
)
298 command_str
= "response";
300 command_str
= "unknown";
302 /* Dump packet header. */
303 zlog_debug ("%s %s version %d packet size %d",
304 sndrcv
, command_str
, packet
->version
, size
);
306 /* Dump each routing table entry. */
309 for (lim
= (caddr_t
) packet
+ size
; (caddr_t
) rte
< lim
; rte
++)
311 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
312 zlog_debug (" nexthop %s/%d", inet6_ntoa (&rte
->addr
), rte
->prefixlen
);
314 zlog_debug (" %s/%d metric %d tag %d",
315 inet6_ntoa (&rte
->addr
), rte
->prefixlen
,
316 rte
->metric
, ntohs (rte
->tag
));
320 /* RIPng next hop address RTE (Route Table Entry). */
322 ripng_nexthop_rte (struct rte
*rte
,
323 struct sockaddr_in6
*from
,
324 struct ripng_nexthop
*nexthop
)
326 char buf
[INET6_BUFSIZ
];
328 /* Logging before checking RTE. */
329 if (IS_RIPNG_DEBUG_RECV
)
330 zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d",
331 inet6_ntoa (&rte
->addr
), ntohs (rte
->tag
), rte
->prefixlen
);
333 /* RFC2080 2.1.1 Next Hop:
334 The route tag and prefix length in the next hop RTE must be
335 set to zero on sending and ignored on receiption. */
336 if (ntohs (rte
->tag
) != 0)
337 zlog_warn ("RIPng nexthop RTE with non zero tag value %d from %s",
338 ntohs (rte
->tag
), inet6_ntoa (&from
->sin6_addr
));
340 if (rte
->prefixlen
!= 0)
341 zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
342 rte
->prefixlen
, inet6_ntoa (&from
->sin6_addr
));
344 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
345 next hop RTE indicates that the next hop address should be the
346 originator of the RIPng advertisement. An address specified as a
347 next hop must be a link-local address. */
348 if (IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
))
350 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
351 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
355 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
357 nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
358 IPV6_ADDR_COPY (&nexthop
->address
, &rte
->addr
);
362 /* The purpose of the next hop RTE is to eliminate packets being
363 routed through extra hops in the system. It is particularly useful
364 when RIPng is not being run on all of the routers on a network.
365 Note that next hop RTE is "advisory". That is, if the provided
366 information is ignored, a possibly sub-optimal, but absolutely
367 valid, route may be taken. If the received next hop address is not
368 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
369 zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s",
370 inet6_ntoa (&rte
->addr
),
371 inet_ntop (AF_INET6
, &from
->sin6_addr
, buf
, INET6_BUFSIZ
));
373 nexthop
->flag
= RIPNG_NEXTHOP_UNSPEC
;
374 memset (&nexthop
->address
, 0, sizeof (struct in6_addr
));
379 /* If ifp has same link-local address then return 1. */
381 ripng_lladdr_check (struct interface
*ifp
, struct in6_addr
*addr
)
383 struct listnode
*node
;
384 struct connected
*connected
;
387 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, connected
))
389 p
= connected
->address
;
391 if (p
->family
== AF_INET6
&&
392 IN6_IS_ADDR_LINKLOCAL (&p
->u
.prefix6
) &&
393 IN6_ARE_ADDR_EQUAL (&p
->u
.prefix6
, addr
))
399 /* RIPng route garbage collect timer. */
401 ripng_garbage_collect (struct thread
*t
)
403 struct ripng_info
*rinfo
;
404 struct route_node
*rp
;
406 rinfo
= THREAD_ARG (t
);
407 rinfo
->t_garbage_collect
= NULL
;
409 /* Off timeout timer. */
410 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
412 /* Get route_node pointer. */
415 /* Unlock route_node. */
417 route_unlock_node (rp
);
419 /* Free RIPng routing information. */
420 ripng_info_free (rinfo
);
425 /* Timeout RIPng routes. */
427 ripng_timeout (struct thread
*t
)
429 struct ripng_info
*rinfo
;
430 struct route_node
*rp
;
432 rinfo
= THREAD_ARG (t
);
433 rinfo
->t_timeout
= NULL
;
435 /* Get route_node pointer. */
438 /* - The garbage-collection timer is set for 120 seconds. */
439 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
, ripng_garbage_collect
,
440 ripng
->garbage_time
);
442 /* Delete this route from the kernel. */
443 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
445 /* - The metric for the route is set to 16 (infinity). This causes
446 the route to be removed from service. */
447 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
448 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
450 /* Aggregate count decrement. */
451 ripng_aggregate_decrement (rp
, rinfo
);
453 /* - The route change flag is to indicate that this entry has been
455 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
457 /* - The output process is signalled to trigger a response. */
458 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
464 ripng_timeout_update (struct ripng_info
*rinfo
)
466 if (rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
468 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
469 RIPNG_TIMER_ON (rinfo
->t_timeout
, ripng_timeout
, ripng
->timeout_time
);
474 ripng_incoming_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
476 struct distribute
*dist
;
477 struct access_list
*alist
;
478 struct prefix_list
*plist
;
480 /* Input distribute-list filtering. */
481 if (ri
->list
[RIPNG_FILTER_IN
])
483 if (access_list_apply (ri
->list
[RIPNG_FILTER_IN
],
484 (struct prefix
*) p
) == FILTER_DENY
)
486 if (IS_RIPNG_DEBUG_PACKET
)
487 zlog_debug ("%s/%d filtered by distribute in",
488 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
492 if (ri
->prefix
[RIPNG_FILTER_IN
])
494 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_IN
],
495 (struct prefix
*) p
) == PREFIX_DENY
)
497 if (IS_RIPNG_DEBUG_PACKET
)
498 zlog_debug ("%s/%d filtered by prefix-list in",
499 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
504 /* All interface filter check. */
505 dist
= distribute_lookup (NULL
);
508 if (dist
->list
[DISTRIBUTE_IN
])
510 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
514 if (access_list_apply (alist
,
515 (struct prefix
*) p
) == FILTER_DENY
)
517 if (IS_RIPNG_DEBUG_PACKET
)
518 zlog_debug ("%s/%d filtered by distribute in",
519 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
524 if (dist
->prefix
[DISTRIBUTE_IN
])
526 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
530 if (prefix_list_apply (plist
,
531 (struct prefix
*) p
) == PREFIX_DENY
)
533 if (IS_RIPNG_DEBUG_PACKET
)
534 zlog_debug ("%s/%d filtered by prefix-list in",
535 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
545 ripng_outgoing_filter (struct prefix_ipv6
*p
, struct ripng_interface
*ri
)
547 struct distribute
*dist
;
548 struct access_list
*alist
;
549 struct prefix_list
*plist
;
551 if (ri
->list
[RIPNG_FILTER_OUT
])
553 if (access_list_apply (ri
->list
[RIPNG_FILTER_OUT
],
554 (struct prefix
*) p
) == FILTER_DENY
)
556 if (IS_RIPNG_DEBUG_PACKET
)
557 zlog_debug ("%s/%d is filtered by distribute out",
558 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
562 if (ri
->prefix
[RIPNG_FILTER_OUT
])
564 if (prefix_list_apply (ri
->prefix
[RIPNG_FILTER_OUT
],
565 (struct prefix
*) p
) == PREFIX_DENY
)
567 if (IS_RIPNG_DEBUG_PACKET
)
568 zlog_debug ("%s/%d is filtered by prefix-list out",
569 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
574 /* All interface filter check. */
575 dist
= distribute_lookup (NULL
);
578 if (dist
->list
[DISTRIBUTE_OUT
])
580 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
584 if (access_list_apply (alist
,
585 (struct prefix
*) p
) == FILTER_DENY
)
587 if (IS_RIPNG_DEBUG_PACKET
)
588 zlog_debug ("%s/%d filtered by distribute out",
589 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
594 if (dist
->prefix
[DISTRIBUTE_OUT
])
596 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
600 if (prefix_list_apply (plist
,
601 (struct prefix
*) p
) == PREFIX_DENY
)
603 if (IS_RIPNG_DEBUG_PACKET
)
604 zlog_debug ("%s/%d filtered by prefix-list out",
605 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
614 /* Process RIPng route according to RFC2080. */
616 ripng_route_process (struct rte
*rte
, struct sockaddr_in6
*from
,
617 struct ripng_nexthop
*ripng_nexthop
,
618 struct interface
*ifp
)
621 struct prefix_ipv6 p
;
622 struct route_node
*rp
;
623 struct ripng_info
*rinfo
;
624 struct ripng_interface
*ri
;
625 struct in6_addr
*nexthop
;
629 /* Make prefix structure. */
630 memset (&p
, 0, sizeof (struct prefix_ipv6
));
632 /* p.prefix = rte->addr; */
633 IPV6_ADDR_COPY (&p
.prefix
, &rte
->addr
);
634 p
.prefixlen
= rte
->prefixlen
;
636 /* Make sure mask is applied. */
637 /* XXX We have to check the prefix is valid or not before call
639 apply_mask_ipv6 (&p
);
641 /* Apply input filters. */
644 ret
= ripng_incoming_filter (&p
, ri
);
649 if (ri
->routemap
[RIPNG_FILTER_IN
])
652 struct ripng_info newinfo
;
654 memset (&newinfo
, 0, sizeof (struct ripng_info
));
655 newinfo
.type
= ZEBRA_ROUTE_RIPNG
;
656 newinfo
.sub_type
= RIPNG_ROUTE_RTE
;
657 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
658 newinfo
.nexthop
= ripng_nexthop
->address
;
660 newinfo
.nexthop
= from
->sin6_addr
;
661 newinfo
.from
= from
->sin6_addr
;
662 newinfo
.ifindex
= ifp
->ifindex
;
663 newinfo
.metric
= rte
->metric
;
664 newinfo
.metric_out
= rte
->metric
; /* XXX */
665 newinfo
.tag
= ntohs(rte
->tag
); /* XXX */
667 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_IN
],
668 (struct prefix
*)&p
, RMAP_RIPNG
, &newinfo
);
670 if (ret
== RMAP_DENYMATCH
)
672 if (IS_RIPNG_DEBUG_PACKET
)
673 zlog_debug ("RIPng %s/%d is filtered by route-map in",
674 inet6_ntoa (&p
.prefix
), p
.prefixlen
);
678 /* Get back the object */
679 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
) {
680 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &ripng_nexthop
->address
) ) {
681 /* the nexthop get changed by the routemap */
682 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
))
683 ripng_nexthop
->address
= newinfo
.nexthop
;
685 ripng_nexthop
->address
= in6addr_any
;
688 if (! IPV6_ADDR_SAME(&newinfo
.nexthop
, &from
->sin6_addr
) ) {
689 /* the nexthop get changed by the routemap */
690 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop
)) {
691 ripng_nexthop
->flag
= RIPNG_NEXTHOP_ADDRESS
;
692 ripng_nexthop
->address
= newinfo
.nexthop
;
696 rte
->tag
= htons(newinfo
.tag_out
); /* XXX */
697 rte
->metric
= newinfo
.metric_out
; /* XXX: the routemap uses the metric_out field */
700 /* Once the entry has been validated, update the metric by
701 * adding the cost of the network on wich the message
702 * arrived. If the result is greater than infinity, use infinity
703 * (RFC2453 Sec. 3.9.2)
706 /* Zebra ripngd can handle offset-list in. */
707 ret
= ripng_offset_list_apply_in (&p
, ifp
, &rte
->metric
);
709 /* If offset-list does not modify the metric use interface's
712 rte
->metric
+= ifp
->metric
;
714 if (rte
->metric
> RIPNG_METRIC_INFINITY
)
715 rte
->metric
= RIPNG_METRIC_INFINITY
;
717 /* Set nexthop pointer. */
718 if (ripng_nexthop
->flag
== RIPNG_NEXTHOP_ADDRESS
)
719 nexthop
= &ripng_nexthop
->address
;
721 nexthop
= &from
->sin6_addr
;
723 /* Lookup RIPng routing table. */
724 rp
= route_node_get (ripng
->table
, (struct prefix
*) &p
);
730 /* Redistributed route check. */
731 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
732 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
735 /* Local static route. */
736 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
737 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
738 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
))
739 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
743 if (rp
->info
== NULL
)
745 /* Now, check to see whether there is already an explicit route
746 for the destination prefix. If there is no such route, add
747 this route to the routing table, unless the metric is
748 infinity (there is no point in adding a route which
750 if (rte
->metric
!= RIPNG_METRIC_INFINITY
)
752 rinfo
= ripng_info_new ();
754 /* - Setting the destination prefix and length to those in
759 /* - Setting the metric to the newly calculated metric (as
761 rinfo
->metric
= rte
->metric
;
762 rinfo
->tag
= ntohs (rte
->tag
);
764 /* - Set the next hop address to be the address of the router
765 from which the datagram came or the next hop address
766 specified by a next hop RTE. */
767 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
768 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
769 rinfo
->ifindex
= ifp
->ifindex
;
771 /* - Initialize the timeout for the route. If the
772 garbage-collection timer is running for this route, stop it. */
773 ripng_timeout_update (rinfo
);
775 /* - Set the route change flag. */
776 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
778 /* - Signal the output process to trigger an update (see section
780 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
782 /* Finally, route goes into the kernel. */
783 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
784 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
786 ripng_zebra_ipv6_add (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
787 rinfo
->flags
|= RIPNG_RTF_FIB
;
789 /* Aggregate check. */
790 ripng_aggregate_increment (rp
, rinfo
);
797 /* If there is an existing route, compare the next hop address
798 to the address of the router from which the datagram came.
799 If this datagram is from the same router as the existing
800 route, reinitialize the timeout. */
801 same
= (IN6_ARE_ADDR_EQUAL (&rinfo
->from
, &from
->sin6_addr
)
802 && (rinfo
->ifindex
== ifp
->ifindex
));
805 ripng_timeout_update (rinfo
);
807 /* Next, compare the metrics. If the datagram is from the same
808 router as the existing route, and the new metric is different
809 than the old one; or, if the new metric is lower than the old
810 one; do the following actions: */
811 if ((same
&& rinfo
->metric
!= rte
->metric
) ||
812 rte
->metric
< rinfo
->metric
)
814 /* - Adopt the route from the datagram. That is, put the
815 new metric in, and adjust the next hop address (if
817 oldmetric
= rinfo
->metric
;
818 rinfo
->metric
= rte
->metric
;
819 rinfo
->tag
= ntohs (rte
->tag
);
820 IPV6_ADDR_COPY (&rinfo
->from
, &from
->sin6_addr
);
821 rinfo
->ifindex
= ifp
->ifindex
;
823 /* Should a new route to this network be established
824 while the garbage-collection timer is running, the
825 new route will replace the one that is about to be
826 deleted. In this case the garbage-collection timer
829 if (oldmetric
== RIPNG_METRIC_INFINITY
&&
830 rinfo
->metric
< RIPNG_METRIC_INFINITY
)
832 rinfo
->type
= ZEBRA_ROUTE_RIPNG
;
833 rinfo
->sub_type
= RIPNG_ROUTE_RTE
;
835 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
837 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
838 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
840 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
);
841 rinfo
->flags
|= RIPNG_RTF_FIB
;
843 /* The aggregation counter needs to be updated because
844 the prefixes, which are into the gc, have been
845 removed from the aggregator (see ripng_timout). */
846 ripng_aggregate_increment (rp
, rinfo
);
849 /* Update nexthop and/or metric value. */
850 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
852 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
853 ripng_zebra_ipv6_add (&p
, nexthop
, ifp
->ifindex
);
854 rinfo
->flags
|= RIPNG_RTF_FIB
;
856 if (! IPV6_ADDR_SAME (&rinfo
->nexthop
, nexthop
))
857 IPV6_ADDR_COPY (&rinfo
->nexthop
, nexthop
);
860 /* - Set the route change flag and signal the output process
861 to trigger an update. */
862 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
863 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
865 /* - If the new metric is infinity, start the deletion
866 process (described above); */
867 if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
869 /* If the new metric is infinity, the deletion process
870 begins for the route, which is no longer used for
871 routing packets. Note that the deletion process is
872 started only when the metric is first set to
873 infinity. If the metric was already infinity, then a
874 new deletion process is not started. */
875 if (oldmetric
!= RIPNG_METRIC_INFINITY
)
877 /* - The garbage-collection timer is set for 120 seconds. */
878 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
879 ripng_garbage_collect
, ripng
->garbage_time
);
880 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
882 /* - The metric for the route is set to 16
883 (infinity). This causes the route to be removed
885 ripng_zebra_ipv6_delete (&p
, &rinfo
->nexthop
, rinfo
->ifindex
);
886 rinfo
->flags
&= ~RIPNG_RTF_FIB
;
888 /* Aggregate count decrement. */
889 ripng_aggregate_decrement (rp
, rinfo
);
891 /* - The route change flag is to indicate that this
892 entry has been changed. */
893 /* - The output process is signalled to trigger a
895 ; /* Above processes are already done previously. */
900 /* otherwise, re-initialize the timeout. */
901 ripng_timeout_update (rinfo
);
904 /* Unlock tempolary lock of the route. */
905 route_unlock_node (rp
);
909 /* Add redistributed route to RIPng table. */
911 ripng_redistribute_add (int type
, int sub_type
, struct prefix_ipv6
*p
,
912 unsigned int ifindex
, struct in6_addr
*nexthop
)
914 struct route_node
*rp
;
915 struct ripng_info
*rinfo
;
917 /* Redistribute route */
918 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
920 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
922 #if defined (MUSICA) || defined (LINUX)
923 /* XXX As long as the RIPng redistribution is applied to all the connected
924 * routes, one needs to filter the ::/96 prefixes.
925 * However it could be a wanted case, it will be removed soon.
927 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
928 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
930 #endif /* MUSICA or LINUX */
932 rp
= route_node_get (ripng
->table
, (struct prefix
*) p
);
937 if (rinfo
->type
== ZEBRA_ROUTE_CONNECT
938 && rinfo
->sub_type
== RIPNG_ROUTE_INTERFACE
939 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
) {
940 route_unlock_node (rp
);
944 /* Manually configured RIPng route check.
945 * They have the precedence on all the other entries.
947 if (rinfo
->type
== ZEBRA_ROUTE_RIPNG
948 && ((rinfo
->sub_type
== RIPNG_ROUTE_STATIC
) ||
949 (rinfo
->sub_type
== RIPNG_ROUTE_DEFAULT
)) ) {
950 if (type
!= ZEBRA_ROUTE_RIPNG
|| ((sub_type
!= RIPNG_ROUTE_STATIC
) &&
951 (sub_type
!= RIPNG_ROUTE_DEFAULT
))) {
952 route_unlock_node (rp
);
957 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
958 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
960 /* Tells the other daemons about the deletion of
963 if (ripng_route_rte (rinfo
))
964 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
, &rinfo
->nexthop
,
968 ripng_info_free (rinfo
);
970 route_unlock_node (rp
);
974 rinfo
= ripng_info_new ();
977 rinfo
->sub_type
= sub_type
;
978 rinfo
->ifindex
= ifindex
;
982 if (nexthop
&& IN6_IS_ADDR_LINKLOCAL(nexthop
))
983 rinfo
->nexthop
= *nexthop
;
985 rinfo
->flags
|= RIPNG_RTF_FIB
;
988 /* Aggregate check. */
989 ripng_aggregate_increment (rp
, rinfo
);
991 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
993 if (IS_RIPNG_DEBUG_EVENT
) {
995 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
996 inet6_ntoa(&p
->prefix
), p
->prefixlen
,
997 ifindex2ifname(ifindex
));
999 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1000 inet6_ntoa(&p
->prefix
), p
->prefixlen
, inet6_ntoa(nexthop
),
1001 ifindex2ifname(ifindex
));
1004 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1007 /* Delete redistributed route to RIPng table. */
1009 ripng_redistribute_delete (int type
, int sub_type
, struct prefix_ipv6
*p
,
1010 unsigned int ifindex
)
1012 struct route_node
*rp
;
1013 struct ripng_info
*rinfo
;
1015 if (IN6_IS_ADDR_LINKLOCAL (&p
->prefix
))
1017 if (IN6_IS_ADDR_LOOPBACK (&p
->prefix
))
1019 #if defined (MUSICA) || defined (LINUX)
1020 /* XXX As long as the RIPng redistribution is applied to all the connected
1021 * routes, one needs to filter the ::/96 prefixes.
1022 * However it could be a wanted case, it will be removed soon.
1024 if ((IN6_IS_ADDR_V4COMPAT(&p
->prefix
)) ||
1025 (IN6_IS_ADDR_UNSPECIFIED (&p
->prefix
) && (p
->prefixlen
== 96)))
1027 #endif /* MUSICA or LINUX */
1029 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) p
);
1036 && rinfo
->type
== type
1037 && rinfo
->sub_type
== sub_type
1038 && rinfo
->ifindex
== ifindex
)
1040 /* Perform poisoned reverse. */
1041 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1042 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1043 ripng_garbage_collect
, ripng
->garbage_time
);
1044 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1046 /* Aggregate count decrement. */
1047 ripng_aggregate_decrement (rp
, rinfo
);
1049 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1051 if (IS_RIPNG_DEBUG_EVENT
)
1052 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1053 inet6_ntoa(&p
->prefix
), p
->prefixlen
,
1054 ifindex2ifname(ifindex
));
1056 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1061 /* Withdraw redistributed route. */
1063 ripng_redistribute_withdraw (int type
)
1065 struct route_node
*rp
;
1066 struct ripng_info
*rinfo
;
1071 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1072 if ((rinfo
= rp
->info
) != NULL
)
1074 if ((rinfo
->type
== type
)
1075 && (rinfo
->sub_type
!= RIPNG_ROUTE_INTERFACE
))
1077 /* Perform poisoned reverse. */
1078 rinfo
->metric
= RIPNG_METRIC_INFINITY
;
1079 RIPNG_TIMER_ON (rinfo
->t_garbage_collect
,
1080 ripng_garbage_collect
, ripng
->garbage_time
);
1081 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
1083 /* Aggregate count decrement. */
1084 ripng_aggregate_decrement (rp
, rinfo
);
1086 rinfo
->flags
|= RIPNG_RTF_CHANGED
;
1088 if (IS_RIPNG_DEBUG_EVENT
) {
1089 struct prefix_ipv6
*p
= (struct prefix_ipv6
*) &rp
->p
;
1091 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
1092 inet6_ntoa(&p
->prefix
), p
->prefixlen
,
1093 ifindex2ifname(rinfo
->ifindex
));
1096 ripng_event (RIPNG_TRIGGERED_UPDATE
, 0);
1101 /* RIP routing information. */
1103 ripng_response_process (struct ripng_packet
*packet
, int size
,
1104 struct sockaddr_in6
*from
, struct interface
*ifp
,
1109 struct ripng_nexthop nexthop
;
1111 /* RFC2080 2.4.2 Response Messages:
1112 The Response must be ignored if it is not from the RIPng port. */
1113 if (ntohs (from
->sin6_port
) != RIPNG_PORT_DEFAULT
)
1115 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
1116 ntohs (from
->sin6_port
), inet6_ntoa (&from
->sin6_addr
));
1117 ripng_peer_bad_packet (from
);
1121 /* The datagram's IPv6 source address should be checked to see
1122 whether the datagram is from a valid neighbor; the source of the
1123 datagram must be a link-local address. */
1124 if (! IN6_IS_ADDR_LINKLOCAL(&from
->sin6_addr
))
1126 zlog_warn ("RIPng packet comes from non link local address %s",
1127 inet6_ntoa (&from
->sin6_addr
));
1128 ripng_peer_bad_packet (from
);
1132 /* It is also worth checking to see whether the response is from one
1133 of the router's own addresses. Interfaces on broadcast networks
1134 may receive copies of their own multicasts immediately. If a
1135 router processes its own output as new input, confusion is likely,
1136 and such datagrams must be ignored. */
1137 if (ripng_lladdr_check (ifp
, &from
->sin6_addr
))
1139 zlog_warn ("RIPng packet comes from my own link local address %s",
1140 inet6_ntoa (&from
->sin6_addr
));
1141 ripng_peer_bad_packet (from
);
1145 /* As an additional check, periodic advertisements must have their
1146 hop counts set to 255, and inbound, multicast packets sent from the
1147 RIPng port (i.e. periodic advertisement or triggered update
1148 packets) must be examined to ensure that the hop count is 255. */
1149 if (hoplimit
>= 0 && hoplimit
!= 255)
1151 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
1152 hoplimit
, inet6_ntoa (&from
->sin6_addr
));
1153 ripng_peer_bad_packet (from
);
1157 /* Update RIPng peer. */
1158 ripng_peer_update (from
, packet
->version
);
1160 /* Reset nexthop. */
1161 memset (&nexthop
, 0, sizeof (struct ripng_nexthop
));
1162 nexthop
.flag
= RIPNG_NEXTHOP_UNSPEC
;
1164 /* Set RTE pointer. */
1167 for (lim
= ((caddr_t
) packet
) + size
; (caddr_t
) rte
< lim
; rte
++)
1169 /* First of all, we have to check this RTE is next hop RTE or
1170 not. Next hop RTE is completely different with normal RTE so
1171 we need special treatment. */
1172 if (rte
->metric
== RIPNG_METRIC_NEXTHOP
)
1174 ripng_nexthop_rte (rte
, from
, &nexthop
);
1178 /* RTE information validation. */
1180 /* - is the destination prefix valid (e.g., not a multicast
1181 prefix and not a link-local address) A link-local address
1182 should never be present in an RTE. */
1183 if (IN6_IS_ADDR_MULTICAST (&rte
->addr
))
1185 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
1186 inet6_ntoa (&rte
->addr
), rte
->prefixlen
, rte
->metric
);
1187 ripng_peer_bad_route (from
);
1190 if (IN6_IS_ADDR_LINKLOCAL (&rte
->addr
))
1192 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
1193 inet6_ntoa (&rte
->addr
), rte
->prefixlen
, rte
->metric
);
1194 ripng_peer_bad_route (from
);
1197 if (IN6_IS_ADDR_LOOPBACK (&rte
->addr
))
1199 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
1200 inet6_ntoa (&rte
->addr
), rte
->prefixlen
, rte
->metric
);
1201 ripng_peer_bad_route (from
);
1205 /* - is the prefix length valid (i.e., between 0 and 128,
1207 if (rte
->prefixlen
> 128)
1209 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
1210 inet6_ntoa (&rte
->addr
), rte
->prefixlen
,
1211 inet6_ntoa (&from
->sin6_addr
), ifp
->name
);
1212 ripng_peer_bad_route (from
);
1216 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1217 if (! (rte
->metric
>= 1 && rte
->metric
<= 16))
1219 zlog_warn ("Invalid metric %d from %s%%%s", rte
->metric
,
1220 inet6_ntoa (&from
->sin6_addr
), ifp
->name
);
1221 ripng_peer_bad_route (from
);
1225 /* Vincent: XXX Should we compute the direclty reachable nexthop
1226 * for our RIPng network ?
1229 /* Routing table updates. */
1230 ripng_route_process (rte
, from
, &nexthop
, ifp
);
1234 /* Response to request message. */
1236 ripng_request_process (struct ripng_packet
*packet
,int size
,
1237 struct sockaddr_in6
*from
, struct interface
*ifp
)
1241 struct prefix_ipv6 p
;
1242 struct route_node
*rp
;
1243 struct ripng_info
*rinfo
;
1244 struct ripng_interface
*ri
;
1246 /* Does not reponse to the requests on the loopback interfaces */
1247 if (if_is_loopback (ifp
))
1250 /* Check RIPng process is enabled on this interface. */
1255 /* When passive interface is specified, suppress responses */
1259 /* RIPng peer update. */
1260 ripng_peer_update (from
, packet
->version
);
1262 lim
= ((caddr_t
) packet
) + size
;
1265 /* The Request is processed entry by entry. If there are no
1266 entries, no response is given. */
1267 if (lim
== (caddr_t
) rte
)
1270 /* There is one special case. If there is exactly one entry in the
1271 request, and it has a destination prefix of zero, a prefix length
1272 of zero, and a metric of infinity (i.e., 16), then this is a
1273 request to send the entire routing table. In that case, a call
1274 is made to the output process to send the routing table to the
1275 requesting address/port. */
1276 if (lim
== ((caddr_t
) (rte
+ 1)) &&
1277 IN6_IS_ADDR_UNSPECIFIED (&rte
->addr
) &&
1278 rte
->prefixlen
== 0 &&
1279 rte
->metric
== RIPNG_METRIC_INFINITY
)
1281 /* All route with split horizon */
1282 ripng_output_process (ifp
, from
, ripng_all_route
);
1286 /* Except for this special case, processing is quite simple.
1287 Examine the list of RTEs in the Request one by one. For each
1288 entry, look up the destination in the router's routing
1289 database and, if there is a route, put that route's metric in
1290 the metric field of the RTE. If there is no explicit route
1291 to the specified destination, put infinity in the metric
1292 field. Once all the entries have been filled in, change the
1293 command from Request to Response and send the datagram back
1294 to the requestor. */
1295 memset (&p
, 0, sizeof (struct prefix_ipv6
));
1296 p
.family
= AF_INET6
;
1298 for (; ((caddr_t
) rte
) < lim
; rte
++)
1300 p
.prefix
= rte
->addr
;
1301 p
.prefixlen
= rte
->prefixlen
;
1302 apply_mask_ipv6 (&p
);
1304 rp
= route_node_lookup (ripng
->table
, (struct prefix
*) &p
);
1309 rte
->metric
= rinfo
->metric
;
1310 route_unlock_node (rp
);
1313 rte
->metric
= RIPNG_METRIC_INFINITY
;
1315 packet
->command
= RIPNG_RESPONSE
;
1317 ripng_send_packet ((caddr_t
) packet
, size
, from
, ifp
);
1321 /* First entry point of reading RIPng packet. */
1323 ripng_read (struct thread
*thread
)
1327 struct sockaddr_in6 from
;
1328 struct ripng_packet
*packet
;
1329 unsigned int ifindex
;
1330 struct interface
*ifp
;
1333 /* Check ripng is active and alive. */
1334 assert (ripng
!= NULL
);
1335 assert (ripng
->sock
>= 0);
1337 /* Fetch thread data and set read pointer to empty for event
1338 managing. `sock' sould be same as ripng->sock. */
1339 sock
= THREAD_FD (thread
);
1340 ripng
->t_read
= NULL
;
1342 /* Add myself to the next event. */
1343 ripng_event (RIPNG_READ
, sock
);
1345 /* Read RIPng packet. */
1346 len
= ripng_recv_packet (sock
, STREAM_DATA (ripng
->ibuf
),
1347 STREAM_SIZE (ripng
->ibuf
), &from
, &ifindex
,
1351 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno
));
1355 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1356 (4)) must be multiple size of one RTE size (20). */
1357 if (((len
- 4) % 20) != 0)
1359 zlog_warn ("RIPng invalid packet size %d from %s", len
,
1360 inet6_ntoa (&from
.sin6_addr
));
1361 ripng_peer_bad_packet (&from
);
1365 packet
= (struct ripng_packet
*) STREAM_DATA (ripng
->ibuf
);
1366 ifp
= if_lookup_by_index (ifindex
);
1368 /* RIPng packet received. */
1369 if (IS_RIPNG_DEBUG_EVENT
)
1370 zlog_debug ("RIPng packet received from %s port %d on %s",
1371 inet6_ntoa (&from
.sin6_addr
), ntohs (from
.sin6_port
),
1372 ifp
? ifp
->name
: "unknown");
1374 /* Logging before packet checking. */
1375 if (IS_RIPNG_DEBUG_RECV
)
1376 ripng_packet_dump (packet
, len
, "RECV");
1378 /* Packet comes from unknown interface. */
1381 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex
);
1385 /* Packet version mismatch checking. */
1386 if (packet
->version
!= ripng
->version
)
1388 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1389 packet
->version
, ripng
->version
);
1390 ripng_peer_bad_packet (&from
);
1394 /* Process RIPng packet. */
1395 switch (packet
->command
)
1398 ripng_request_process (packet
, len
, &from
, ifp
);
1400 case RIPNG_RESPONSE
:
1401 ripng_response_process (packet
, len
, &from
, ifp
, hoplimit
);
1404 zlog_warn ("Invalid RIPng command %d", packet
->command
);
1405 ripng_peer_bad_packet (&from
);
1411 /* Walk down the RIPng routing table then clear changed flag. */
1413 ripng_clear_changed_flag ()
1415 struct route_node
*rp
;
1416 struct ripng_info
*rinfo
;
1418 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1419 if ((rinfo
= rp
->info
) != NULL
)
1420 if (rinfo
->flags
& RIPNG_RTF_CHANGED
)
1421 rinfo
->flags
&= ~RIPNG_RTF_CHANGED
;
1424 /* Regular update of RIPng route. Send all routing formation to RIPng
1425 enabled interface. */
1427 ripng_update (struct thread
*t
)
1429 struct listnode
*node
;
1430 struct interface
*ifp
;
1431 struct ripng_interface
*ri
;
1433 /* Clear update timer thread. */
1434 ripng
->t_update
= NULL
;
1436 /* Logging update event. */
1437 if (IS_RIPNG_DEBUG_EVENT
)
1438 zlog_debug ("RIPng update timer expired!");
1440 /* Supply routes to each interface. */
1441 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
1445 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1451 /* When passive interface is specified, suppress announce to the
1457 if (ri
->ri_send
== RIPNG_SEND_OFF
)
1459 if (IS_RIPNG_DEBUG_EVENT
)
1460 zlog (NULL
, LOG_DEBUG
,
1461 "[Event] RIPng send to if %d is suppressed by config",
1465 #endif /* RIPNG_ADVANCED */
1467 ripng_output_process (ifp
, NULL
, ripng_all_route
);
1470 /* Triggered updates may be suppressed if a regular update is due by
1471 the time the triggered update would be sent. */
1472 if (ripng
->t_triggered_interval
)
1474 thread_cancel (ripng
->t_triggered_interval
);
1475 ripng
->t_triggered_interval
= NULL
;
1479 /* Reset flush event. */
1480 ripng_event (RIPNG_UPDATE_EVENT
, 0);
1485 /* Triggered update interval timer. */
1487 ripng_triggered_interval (struct thread
*t
)
1489 ripng
->t_triggered_interval
= NULL
;
1494 ripng_triggered_update (t
);
1499 /* Execute triggered update. */
1501 ripng_triggered_update (struct thread
*t
)
1503 struct listnode
*node
;
1504 struct interface
*ifp
;
1505 struct ripng_interface
*ri
;
1508 ripng
->t_triggered_update
= NULL
;
1510 /* Cancel interval timer. */
1511 if (ripng
->t_triggered_interval
)
1513 thread_cancel (ripng
->t_triggered_interval
);
1514 ripng
->t_triggered_interval
= NULL
;
1518 /* Logging triggered update. */
1519 if (IS_RIPNG_DEBUG_EVENT
)
1520 zlog_debug ("RIPng triggered update!");
1522 /* Split Horizon processing is done when generating triggered
1523 updates as well as normal updates (see section 2.6). */
1524 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
1528 if (if_is_loopback (ifp
) || ! if_is_up (ifp
))
1534 /* When passive interface is specified, suppress announce to the
1539 ripng_output_process (ifp
, NULL
, ripng_changed_route
);
1542 /* Once all of the triggered updates have been generated, the route
1543 change flags should be cleared. */
1544 ripng_clear_changed_flag ();
1546 /* After a triggered update is sent, a timer should be set for a
1547 random interval between 1 and 5 seconds. If other changes that
1548 would trigger updates occur before the timer expires, a single
1549 update is triggered when the timer expires. */
1550 interval
= (random () % 5) + 1;
1552 ripng
->t_triggered_interval
=
1553 thread_add_timer (master
, ripng_triggered_interval
, NULL
, interval
);
1558 /* Write routing table entry to the stream and return next index of
1559 the routing table entry in the stream. */
1561 ripng_write_rte (int num
, struct stream
*s
, struct prefix_ipv6
*p
,
1562 struct in6_addr
*nexthop
, u_int16_t tag
, u_char metric
)
1564 /* RIPng packet header. */
1567 stream_putc (s
, RIPNG_RESPONSE
);
1568 stream_putc (s
, RIPNG_V1
);
1572 /* Write routing table entry. */
1574 stream_write (s
, (u_char
*) &p
->prefix
, sizeof (struct in6_addr
));
1576 stream_write (s
, (u_char
*) nexthop
, sizeof (struct in6_addr
));
1577 stream_putw (s
, tag
);
1579 stream_putc (s
, p
->prefixlen
);
1582 stream_putc (s
, metric
);
1587 /* Send RESPONSE message to specified destination. */
1589 ripng_output_process (struct interface
*ifp
, struct sockaddr_in6
*to
,
1593 struct route_node
*rp
;
1594 struct ripng_info
*rinfo
;
1595 struct ripng_interface
*ri
;
1596 struct ripng_aggregate
*aggregate
;
1597 struct prefix_ipv6
*p
;
1598 struct list
* ripng_rte_list
;
1600 if (IS_RIPNG_DEBUG_EVENT
) {
1602 zlog_debug ("RIPng update routes to neighbor %s",
1603 inet6_ntoa(&to
->sin6_addr
));
1605 zlog_debug ("RIPng update routes on interface %s", ifp
->name
);
1608 /* Get RIPng interface. */
1611 ripng_rte_list
= ripng_rte_new();
1613 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
1615 if ((rinfo
= rp
->info
) != NULL
&& rinfo
->suppress
== 0)
1617 /* If no route-map are applied, the RTE will be these following
1620 p
= (struct prefix_ipv6
*) &rp
->p
;
1621 rinfo
->metric_out
= rinfo
->metric
;
1622 rinfo
->tag_out
= rinfo
->tag
;
1623 memset(&rinfo
->nexthop_out
, 0, sizeof(rinfo
->nexthop_out
));
1624 /* In order to avoid some local loops,
1625 * if the RIPng route has a nexthop via this interface, keep the nexthop,
1626 * otherwise set it to 0. The nexthop should not be propagated
1627 * beyond the local broadcast/multicast area in order
1628 * to avoid an IGP multi-level recursive look-up.
1630 if (rinfo
->ifindex
== ifp
->ifindex
)
1631 rinfo
->nexthop_out
= rinfo
->nexthop
;
1633 /* Apply output filters. */
1634 ret
= ripng_outgoing_filter (p
, ri
);
1638 /* Changed route only output. */
1639 if (route_type
== ripng_changed_route
&&
1640 (! (rinfo
->flags
& RIPNG_RTF_CHANGED
)))
1643 /* Split horizon. */
1644 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON
)
1646 /* We perform split horizon for RIPng routes. */
1647 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1648 rinfo
->ifindex
== ifp
->ifindex
)
1652 /* Preparation for route-map. */
1653 rinfo
->metric_set
= 0;
1656 * and tag_out are already initialized.
1659 /* Interface route-map */
1660 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1664 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1665 (struct prefix
*) p
, RMAP_RIPNG
,
1668 if (ret
== RMAP_DENYMATCH
)
1670 if (IS_RIPNG_DEBUG_PACKET
)
1671 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1672 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
1678 /* Redistribute route-map. */
1679 if (ripng
->route_map
[rinfo
->type
].name
)
1683 ret
= route_map_apply (ripng
->route_map
[rinfo
->type
].map
,
1684 (struct prefix
*) p
, RMAP_RIPNG
,
1687 if (ret
== RMAP_DENYMATCH
)
1689 if (IS_RIPNG_DEBUG_PACKET
)
1690 zlog_debug ("RIPng %s/%d is filtered by route-map",
1691 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
1696 /* When the route-map does not set metric. */
1697 if (! rinfo
->metric_set
)
1699 /* If the redistribute metric is set. */
1700 if (ripng
->route_map
[rinfo
->type
].metric_config
1701 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1703 rinfo
->metric_out
= ripng
->route_map
[rinfo
->type
].metric
;
1707 /* If the route is not connected or localy generated
1708 one, use default-metric value */
1709 if (rinfo
->type
!= ZEBRA_ROUTE_RIPNG
1710 && rinfo
->type
!= ZEBRA_ROUTE_CONNECT
1711 && rinfo
->metric
!= RIPNG_METRIC_INFINITY
)
1712 rinfo
->metric_out
= ripng
->default_metric
;
1716 /* Apply offset-list */
1717 if (rinfo
->metric_out
!= RIPNG_METRIC_INFINITY
)
1718 ripng_offset_list_apply_out (p
, ifp
, &rinfo
->metric_out
);
1720 if (rinfo
->metric_out
> RIPNG_METRIC_INFINITY
)
1721 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1723 /* Perform split-horizon with poisoned reverse
1726 if (ri
->split_horizon
== RIPNG_SPLIT_HORIZON_POISONED_REVERSE
) {
1727 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
1728 rinfo
->ifindex
== ifp
->ifindex
)
1729 rinfo
->metric_out
= RIPNG_METRIC_INFINITY
;
1732 /* Add RTE to the list */
1733 ripng_rte_add(ripng_rte_list
, p
, rinfo
, NULL
);
1736 /* Process the aggregated RTE entry */
1737 if ((aggregate
= rp
->aggregate
) != NULL
&&
1738 aggregate
->count
> 0 &&
1739 aggregate
->suppress
== 0)
1741 /* If no route-map are applied, the RTE will be these following
1744 p
= (struct prefix_ipv6
*) &rp
->p
;
1745 aggregate
->metric_set
= 0;
1746 aggregate
->metric_out
= aggregate
->metric
;
1747 aggregate
->tag_out
= aggregate
->tag
;
1748 memset(&aggregate
->nexthop_out
, 0, sizeof(aggregate
->nexthop_out
));
1750 /* Apply output filters.*/
1751 ret
= ripng_outgoing_filter (p
, ri
);
1755 /* Interface route-map */
1756 if (ri
->routemap
[RIPNG_FILTER_OUT
])
1759 struct ripng_info newinfo
;
1761 /* let's cast the aggregate structure to ripng_info */
1762 memset (&newinfo
, 0, sizeof (struct ripng_info
));
1763 /* the nexthop is :: */
1764 newinfo
.metric
= aggregate
->metric
;
1765 newinfo
.metric_out
= aggregate
->metric_out
;
1766 newinfo
.tag
= aggregate
->tag
;
1767 newinfo
.tag_out
= aggregate
->tag_out
;
1769 ret
= route_map_apply (ri
->routemap
[RIPNG_FILTER_OUT
],
1770 (struct prefix
*) p
, RMAP_RIPNG
,
1773 if (ret
== RMAP_DENYMATCH
)
1775 if (IS_RIPNG_DEBUG_PACKET
)
1776 zlog_debug ("RIPng %s/%d is filtered by route-map out",
1777 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
1781 aggregate
->metric_out
= newinfo
.metric_out
;
1782 aggregate
->tag_out
= newinfo
.tag_out
;
1783 if (IN6_IS_ADDR_LINKLOCAL(&newinfo
.nexthop_out
))
1784 aggregate
->nexthop_out
= newinfo
.nexthop_out
;
1787 /* There is no redistribute routemap for the aggregated RTE */
1789 /* Changed route only output. */
1790 /* XXX, vincent, in order to increase time convergence,
1791 * it should be announced if a child has changed.
1793 if (route_type
== ripng_changed_route
)
1796 /* Apply offset-list */
1797 if (aggregate
->metric_out
!= RIPNG_METRIC_INFINITY
)
1798 ripng_offset_list_apply_out (p
, ifp
, &aggregate
->metric_out
);
1800 if (aggregate
->metric_out
> RIPNG_METRIC_INFINITY
)
1801 aggregate
->metric_out
= RIPNG_METRIC_INFINITY
;
1803 /* Add RTE to the list */
1804 ripng_rte_add(ripng_rte_list
, p
, NULL
, aggregate
);
1809 /* Flush the list */
1810 ripng_rte_send(ripng_rte_list
, ifp
, to
);
1811 ripng_rte_free(ripng_rte_list
);
1814 /* Create new RIPng instance and set it to global variable. */
1818 /* ripng should be NULL. */
1819 assert (ripng
== NULL
);
1821 /* Allocaste RIPng instance. */
1822 ripng
= XMALLOC (MTYPE_RIPNG
, sizeof (struct ripng
));
1823 memset (ripng
, 0, sizeof (struct ripng
));
1825 /* Default version and timer values. */
1826 ripng
->version
= RIPNG_V1
;
1827 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
1828 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
1829 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
1830 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
1833 ripng
->ibuf
= stream_new (RIPNG_MAX_PACKET_SIZE
* 5);
1834 ripng
->obuf
= stream_new (RIPNG_MAX_PACKET_SIZE
);
1836 /* Initialize RIPng routig table. */
1837 ripng
->table
= route_table_init ();
1838 ripng
->route
= route_table_init ();
1839 ripng
->aggregate
= route_table_init ();
1842 ripng
->sock
= ripng_make_socket ();
1843 if (ripng
->sock
< 0)
1847 ripng_event (RIPNG_READ
, ripng
->sock
);
1848 ripng_event (RIPNG_UPDATE_EVENT
, 1);
1853 /* Send RIPng request to the interface. */
1855 ripng_request (struct interface
*ifp
)
1858 struct ripng_packet ripng_packet
;
1860 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
1861 if (if_is_loopback(ifp
))
1864 /* If interface is down, don't send RIP packet. */
1865 if (! if_is_up (ifp
))
1868 if (IS_RIPNG_DEBUG_EVENT
)
1869 zlog_debug ("RIPng send request to %s", ifp
->name
);
1871 memset (&ripng_packet
, 0, sizeof (ripng_packet
));
1872 ripng_packet
.command
= RIPNG_REQUEST
;
1873 ripng_packet
.version
= RIPNG_V1
;
1874 rte
= ripng_packet
.rte
;
1875 rte
->metric
= RIPNG_METRIC_INFINITY
;
1877 return ripng_send_packet ((caddr_t
) &ripng_packet
, sizeof (ripng_packet
),
1883 ripng_update_jitter (int time
)
1885 return ((rand () % (time
+ 1)) - (time
/ 2));
1889 ripng_event (enum ripng_event event
, int sock
)
1897 ripng
->t_read
= thread_add_read (master
, ripng_read
, NULL
, sock
);
1899 case RIPNG_UPDATE_EVENT
:
1900 if (ripng
->t_update
)
1902 thread_cancel (ripng
->t_update
);
1903 ripng
->t_update
= NULL
;
1905 /* Update timer jitter. */
1906 jitter
= ripng_update_jitter (ripng
->update_time
);
1909 thread_add_timer (master
, ripng_update
, NULL
,
1910 sock
? 2 : ripng
->update_time
+ jitter
);
1912 case RIPNG_TRIGGERED_UPDATE
:
1913 if (ripng
->t_triggered_interval
)
1915 else if (! ripng
->t_triggered_update
)
1916 ripng
->t_triggered_update
=
1917 thread_add_event (master
, ripng_triggered_update
, NULL
, 0);
1924 /* Each route type's strings and default preference.
1925 * FIXME: ISIS? What are these distance values? */
1930 const char *str_long
;
1934 { ZEBRA_ROUTE_SYSTEM
, "X", "system", 10},
1935 { ZEBRA_ROUTE_KERNEL
, "K", "kernel", 20},
1936 { ZEBRA_ROUTE_CONNECT
, "C", "connected", 30},
1937 { ZEBRA_ROUTE_STATIC
, "S", "static", 40},
1938 { ZEBRA_ROUTE_RIP
, "R", "rip", 50},
1939 { ZEBRA_ROUTE_RIPNG
, "R", "ripng", 50},
1940 { ZEBRA_ROUTE_OSPF
, "O", "ospf", 60},
1941 { ZEBRA_ROUTE_OSPF6
, "O", "ospf6", 60},
1942 { ZEBRA_ROUTE_BGP
, "B", "bgp", 70},
1945 /* Print out routes update time. */
1947 ripng_vty_out_uptime (struct vty
*vty
, struct ripng_info
*rinfo
)
1949 struct timeval timer_now
;
1953 char timebuf
[TIME_BUF
];
1954 struct thread
*thread
;
1956 gettimeofday (&timer_now
, NULL
);
1958 if ((thread
= rinfo
->t_timeout
) != NULL
)
1960 clock
= thread
->u
.sands
.tv_sec
- timer_now
.tv_sec
;
1961 tm
= gmtime (&clock
);
1962 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1963 vty_out (vty
, "%5s", timebuf
);
1965 else if ((thread
= rinfo
->t_garbage_collect
) != NULL
)
1967 clock
= thread
->u
.sands
.tv_sec
- timer_now
.tv_sec
;
1968 tm
= gmtime (&clock
);
1969 strftime (timebuf
, TIME_BUF
, "%M:%S", tm
);
1970 vty_out (vty
, "%5s", timebuf
);
1975 ripng_route_subtype_print (struct ripng_info
*rinfo
)
1980 if (rinfo
->suppress
)
1983 switch (rinfo
->sub_type
)
1985 case RIPNG_ROUTE_RTE
:
1988 case RIPNG_ROUTE_STATIC
:
1991 case RIPNG_ROUTE_DEFAULT
:
1994 case RIPNG_ROUTE_REDISTRIBUTE
:
1997 case RIPNG_ROUTE_INTERFACE
:
2008 DEFUN (show_ipv6_ripng
,
2009 show_ipv6_ripng_cmd
,
2013 "Show RIPng routes\n")
2015 struct route_node
*rp
;
2016 struct ripng_info
*rinfo
;
2017 struct ripng_aggregate
*aggregate
;
2018 struct prefix_ipv6
*p
;
2024 /* Header of display. */
2025 vty_out (vty
, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2027 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2028 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2029 " Network Next Hop Via Metric Tag Time%s",
2030 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2031 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
2033 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
2035 if ((aggregate
= rp
->aggregate
) != NULL
)
2037 p
= (struct prefix_ipv6
*) &rp
->p
;
2040 len
= vty_out (vty
, "R(a) %d/%d %s/%d ",
2041 aggregate
->count
, aggregate
->suppress
,
2042 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
2044 len
= vty_out (vty
, "R(a) %s/%d ",
2045 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
2047 vty_out (vty
, "%s", VTY_NEWLINE
);
2048 vty_out (vty
, "%*s", 18, " ");
2050 vty_out (vty
, "%*s", 28, " ");
2051 vty_out (vty
, "self %2d %3d%s", aggregate
->metric
,
2056 if ((rinfo
= rp
->info
) != NULL
)
2058 p
= (struct prefix_ipv6
*) &rp
->p
;
2061 len
= vty_out (vty
, "%s(%s) 0/%d %s/%d ",
2062 route_info
[rinfo
->type
].str
,
2063 ripng_route_subtype_print(rinfo
),
2065 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
2067 len
= vty_out (vty
, "%s(%s) %s/%d ",
2068 route_info
[rinfo
->type
].str
,
2069 ripng_route_subtype_print(rinfo
),
2070 inet6_ntoa (&p
->prefix
), p
->prefixlen
);
2072 vty_out (vty
, "%s", VTY_NEWLINE
);
2073 vty_out (vty
, "%*s", 18, " ");
2074 len
= vty_out (vty
, "%s", inet6_ntoa (&rinfo
->nexthop
));
2078 len
= vty_out (vty
, "%*s", len
, " ");
2081 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2082 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2084 len
= vty_out (vty
, "%s", ifindex2ifname(rinfo
->ifindex
));
2085 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2087 len
= vty_out (vty
, "kill");
2089 len
= vty_out (vty
, "self");
2093 vty_out (vty
, "%*s", len
, " ");
2095 vty_out (vty
, " %2d %3d ",
2096 rinfo
->metric
, rinfo
->tag
);
2099 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2100 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2102 /* RTE from remote RIP routers */
2103 ripng_vty_out_uptime (vty
, rinfo
);
2104 } else if (rinfo
->metric
== RIPNG_METRIC_INFINITY
)
2106 /* poisonous reversed routes (gc) */
2107 ripng_vty_out_uptime (vty
, rinfo
);
2110 vty_out (vty
, "%s", VTY_NEWLINE
);
2117 /* Return next event time. */
2119 ripng_next_thread_timer (struct thread
*thread
)
2121 struct timeval timer_now
;
2123 gettimeofday (&timer_now
, NULL
);
2125 return thread
->u
.sands
.tv_sec
- timer_now
.tv_sec
;
2128 DEFUN (show_ipv6_ripng_status
,
2129 show_ipv6_ripng_status_cmd
,
2130 "show ipv6 ripng status",
2133 "Show RIPng routes\n"
2134 "IPv6 routing protocol process parameters and statistics\n")
2136 struct listnode
*node
;
2137 struct interface
*ifp
;
2138 int ripng_network_write (struct vty
*, int);
2139 void ripng_redistribute_write (struct vty
*, int);
2144 vty_out (vty
, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE
);
2145 vty_out (vty
, " Sending updates every %ld seconds with +/-50%%,",
2146 ripng
->update_time
);
2147 vty_out (vty
, " next due in %d seconds%s",
2148 ripng_next_thread_timer (ripng
->t_update
),
2150 vty_out (vty
, " Timeout after %ld seconds,", ripng
->timeout_time
);
2151 vty_out (vty
, " garbage collect after %ld seconds%s", ripng
->garbage_time
,
2154 /* Filtering status show. */
2155 config_show_distribute (vty
);
2157 /* Default metric information. */
2158 vty_out (vty
, " Default redistribution metric is %d%s",
2159 ripng
->default_metric
, VTY_NEWLINE
);
2161 /* Redistribute information. */
2162 vty_out (vty
, " Redistributing:");
2163 ripng_redistribute_write (vty
, 0);
2164 vty_out (vty
, "%s", VTY_NEWLINE
);
2166 vty_out (vty
, " Default version control: send version %d,", ripng
->version
);
2167 vty_out (vty
, " receive version %d %s", ripng
->version
,
2170 vty_out (vty
, " Interface Send Recv%s", VTY_NEWLINE
);
2172 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
2174 struct ripng_interface
*ri
;
2178 if (ri
->enable_network
|| ri
->enable_interface
)
2181 vty_out (vty
, " %-17s%-3d %-3d%s", ifp
->name
,
2188 vty_out (vty
, " Routing for Networks:%s", VTY_NEWLINE
);
2189 ripng_network_write (vty
, 0);
2191 vty_out (vty
, " Routing Information Sources:%s", VTY_NEWLINE
);
2192 vty_out (vty
, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE
);
2193 ripng_peer_display (vty
);
2198 DEFUN (router_ripng
,
2201 "Enable a routing process\n"
2202 "Make RIPng instance command\n")
2206 vty
->node
= RIPNG_NODE
;
2210 ret
= ripng_create ();
2212 /* Notice to user we couldn't create RIPng. */
2215 zlog_warn ("can't create RIPng");
2223 DEFUN (no_router_ripng
,
2224 no_router_ripng_cmd
,
2227 "Enable a routing process\n"
2228 "Make RIPng instance command\n")
2238 "Static route setup\n"
2239 "Set static RIPng route announcement\n")
2242 struct prefix_ipv6 p
;
2243 struct route_node
*rp
;
2245 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2248 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2251 apply_mask_ipv6 (&p
);
2253 rp
= route_node_get (ripng
->route
, (struct prefix
*) &p
);
2256 vty_out (vty
, "There is already same static route.%s", VTY_NEWLINE
);
2257 route_unlock_node (rp
);
2260 rp
->info
= (void *)1;
2262 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0, NULL
);
2267 DEFUN (no_ripng_route
,
2269 "no route IPV6ADDR",
2271 "Static route setup\n"
2272 "Delete static RIPng route announcement\n")
2275 struct prefix_ipv6 p
;
2276 struct route_node
*rp
;
2278 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2281 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2284 apply_mask_ipv6 (&p
);
2286 rp
= route_node_lookup (ripng
->route
, (struct prefix
*) &p
);
2289 vty_out (vty
, "Can't find static route.%s", VTY_NEWLINE
);
2293 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_STATIC
, &p
, 0);
2294 route_unlock_node (rp
);
2297 route_unlock_node (rp
);
2302 DEFUN (ripng_aggregate_address
,
2303 ripng_aggregate_address_cmd
,
2304 "aggregate-address X:X::X:X/M",
2305 "Set aggregate RIPng route announcement\n"
2306 "Aggregate network\n")
2310 struct route_node
*node
;
2312 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*)&p
);
2315 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2319 /* Check aggregate alredy exist or not. */
2320 node
= route_node_get (ripng
->aggregate
, &p
);
2323 vty_out (vty
, "There is already same aggregate route.%s", VTY_NEWLINE
);
2324 route_unlock_node (node
);
2327 node
->info
= (void *)1;
2329 ripng_aggregate_add (&p
);
2334 DEFUN (no_ripng_aggregate_address
,
2335 no_ripng_aggregate_address_cmd
,
2336 "no aggregate-address X:X::X:X/M",
2338 "Delete aggregate RIPng route announcement\n"
2339 "Aggregate network")
2343 struct route_node
*rn
;
2345 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &p
);
2348 vty_out (vty
, "Malformed address%s", VTY_NEWLINE
);
2352 rn
= route_node_lookup (ripng
->aggregate
, &p
);
2355 vty_out (vty
, "Can't find aggregate route.%s", VTY_NEWLINE
);
2358 route_unlock_node (rn
);
2360 route_unlock_node (rn
);
2362 ripng_aggregate_delete (&p
);
2367 DEFUN (ripng_default_metric
,
2368 ripng_default_metric_cmd
,
2369 "default-metric <1-16>",
2370 "Set a metric of redistribute routes\n"
2375 ripng
->default_metric
= atoi (argv
[0]);
2380 DEFUN (no_ripng_default_metric
,
2381 no_ripng_default_metric_cmd
,
2382 "no default-metric",
2384 "Set a metric of redistribute routes\n"
2389 ripng
->default_metric
= RIPNG_DEFAULT_METRIC_DEFAULT
;
2394 ALIAS (no_ripng_default_metric
,
2395 no_ripng_default_metric_val_cmd
,
2396 "no default-metric <1-16>",
2398 "Set a metric of redistribute routes\n"
2402 /* RIPng update timer setup. */
2403 DEFUN (ripng_update_timer
,
2404 ripng_update_timer_cmd
,
2405 "update-timer SECOND",
2406 "Set RIPng update timer in seconds\n"
2409 unsigned long update
;
2410 char *endptr
= NULL
;
2412 update
= strtoul (argv
[0], &endptr
, 10);
2413 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2415 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2419 ripng
->update_time
= update
;
2421 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2425 DEFUN (no_ripng_update_timer
,
2426 no_ripng_update_timer_cmd
,
2427 "no update-timer SECOND",
2429 "Unset RIPng update timer in seconds\n"
2432 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2433 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2437 /* RIPng timeout timer setup. */
2438 DEFUN (ripng_timeout_timer
,
2439 ripng_timeout_timer_cmd
,
2440 "timeout-timer SECOND",
2441 "Set RIPng timeout timer in seconds\n"
2444 unsigned long timeout
;
2445 char *endptr
= NULL
;
2447 timeout
= strtoul (argv
[0], &endptr
, 10);
2448 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2450 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2454 ripng
->timeout_time
= timeout
;
2459 DEFUN (no_ripng_timeout_timer
,
2460 no_ripng_timeout_timer_cmd
,
2461 "no timeout-timer SECOND",
2463 "Unset RIPng timeout timer in seconds\n"
2466 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2470 /* RIPng garbage timer setup. */
2471 DEFUN (ripng_garbage_timer
,
2472 ripng_garbage_timer_cmd
,
2473 "garbage-timer SECOND",
2474 "Set RIPng garbage timer in seconds\n"
2477 unsigned long garbage
;
2478 char *endptr
= NULL
;
2480 garbage
= strtoul (argv
[0], &endptr
, 10);
2481 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2483 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2487 ripng
->garbage_time
= garbage
;
2492 DEFUN (no_ripng_garbage_timer
,
2493 no_ripng_garbage_timer_cmd
,
2494 "no garbage-timer SECOND",
2496 "Unset RIPng garbage timer in seconds\n"
2499 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2504 DEFUN (ripng_timers
,
2506 "timers basic <0-65535> <0-65535> <0-65535>",
2507 "RIPng timers setup\n"
2509 "Routing table update timer value in second. Default is 30.\n"
2510 "Routing information timeout timer. Default is 180.\n"
2511 "Garbage collection timer. Default is 120.\n")
2513 unsigned long update
;
2514 unsigned long timeout
;
2515 unsigned long garbage
;
2516 char *endptr
= NULL
;
2518 update
= strtoul (argv
[0], &endptr
, 10);
2519 if (update
== ULONG_MAX
|| *endptr
!= '\0')
2521 vty_out (vty
, "update timer value error%s", VTY_NEWLINE
);
2525 timeout
= strtoul (argv
[1], &endptr
, 10);
2526 if (timeout
== ULONG_MAX
|| *endptr
!= '\0')
2528 vty_out (vty
, "timeout timer value error%s", VTY_NEWLINE
);
2532 garbage
= strtoul (argv
[2], &endptr
, 10);
2533 if (garbage
== ULONG_MAX
|| *endptr
!= '\0')
2535 vty_out (vty
, "garbage timer value error%s", VTY_NEWLINE
);
2539 /* Set each timer value. */
2540 ripng
->update_time
= update
;
2541 ripng
->timeout_time
= timeout
;
2542 ripng
->garbage_time
= garbage
;
2544 /* Reset update timer thread. */
2545 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2550 DEFUN (no_ripng_timers
,
2551 no_ripng_timers_cmd
,
2554 "RIPng timers setup\n"
2557 /* Set each timer value to the default. */
2558 ripng
->update_time
= RIPNG_UPDATE_TIMER_DEFAULT
;
2559 ripng
->timeout_time
= RIPNG_TIMEOUT_TIMER_DEFAULT
;
2560 ripng
->garbage_time
= RIPNG_GARBAGE_TIMER_DEFAULT
;
2562 /* Reset update timer thread. */
2563 ripng_event (RIPNG_UPDATE_EVENT
, 0);
2568 ALIAS (no_ripng_timers
,
2569 no_ripng_timers_val_cmd
,
2570 "no timers basic <0-65535> <0-65535> <0-65535>",
2572 "RIPng timers setup\n"
2574 "Routing table update timer value in second. Default is 30.\n"
2575 "Routing information timeout timer. Default is 180.\n"
2576 "Garbage collection timer. Default is 120.\n")
2578 DEFUN (show_ipv6_protocols
, show_ipv6_protocols_cmd
,
2579 "show ipv6 protocols",
2582 "Routing protocol information")
2587 vty_out (vty
, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE
);
2589 vty_out (vty
, "Sending updates every %ld seconds, next due in %d seconds%s",
2590 ripng
->update_time
, 0,
2593 vty_out (vty
, "Timerout after %ld seconds, garbage correct %ld%s",
2594 ripng
->timeout_time
,
2595 ripng
->garbage_time
,
2598 vty_out (vty
, "Outgoing update filter list for all interfaces is not set");
2599 vty_out (vty
, "Incoming update filter list for all interfaces is not set");
2604 /* Please be carefull to use this command. */
2605 DEFUN (ripng_default_information_originate
,
2606 ripng_default_information_originate_cmd
,
2607 "default-information originate",
2608 "Default route information\n"
2609 "Distribute default route\n")
2611 struct prefix_ipv6 p
;
2613 if (! ripng
->default_information
) {
2614 ripng
->default_information
= 1;
2616 str2prefix_ipv6 ("::/0", &p
);
2617 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0, NULL
);
2623 DEFUN (no_ripng_default_information_originate
,
2624 no_ripng_default_information_originate_cmd
,
2625 "no default-information originate",
2627 "Default route information\n"
2628 "Distribute default route\n")
2630 struct prefix_ipv6 p
;
2632 if (ripng
->default_information
) {
2633 ripng
->default_information
= 0;
2635 str2prefix_ipv6 ("::/0", &p
);
2636 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG
, RIPNG_ROUTE_DEFAULT
, &p
, 0);
2642 /* RIPng configuration write function. */
2644 ripng_config_write (struct vty
*vty
)
2646 int ripng_network_write (struct vty
*, int);
2647 void ripng_redistribute_write (struct vty
*, int);
2649 struct route_node
*rp
;
2655 vty_out (vty
, "router ripng%s", VTY_NEWLINE
);
2657 if (ripng
->default_information
)
2658 vty_out (vty
, " default-information originate%s", VTY_NEWLINE
);
2660 ripng_network_write (vty
, 1);
2662 /* RIPng default metric configuration */
2663 if (ripng
->default_metric
!= RIPNG_DEFAULT_METRIC_DEFAULT
)
2664 vty_out (vty
, " default-metric %d%s",
2665 ripng
->default_metric
, VTY_NEWLINE
);
2667 ripng_redistribute_write (vty
, 1);
2669 /* RIP offset-list configuration. */
2670 config_write_ripng_offset_list (vty
);
2672 /* RIPng aggregate routes. */
2673 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2674 if (rp
->info
!= NULL
)
2675 vty_out (vty
, " aggregate-address %s/%d%s",
2676 inet6_ntoa (&rp
->p
.u
.prefix6
),
2681 /* RIPng static routes. */
2682 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2683 if (rp
->info
!= NULL
)
2684 vty_out (vty
, " route %s/%d%s", inet6_ntoa (&rp
->p
.u
.prefix6
),
2688 /* RIPng timers configuration. */
2689 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
||
2690 ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
||
2691 ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2693 vty_out (vty
, " timers basic %ld %ld %ld%s",
2695 ripng
->timeout_time
,
2696 ripng
->garbage_time
,
2700 if (ripng
->update_time
!= RIPNG_UPDATE_TIMER_DEFAULT
)
2701 vty_out (vty
, " update-timer %d%s", ripng
->update_time
,
2703 if (ripng
->timeout_time
!= RIPNG_TIMEOUT_TIMER_DEFAULT
)
2704 vty_out (vty
, " timeout-timer %d%s", ripng
->timeout_time
,
2706 if (ripng
->garbage_time
!= RIPNG_GARBAGE_TIMER_DEFAULT
)
2707 vty_out (vty
, " garbage-timer %d%s", ripng
->garbage_time
,
2711 write
+= config_write_distribute (vty
);
2713 write
+= config_write_if_rmap (vty
);
2720 /* RIPng node structure. */
2721 struct cmd_node cmd_ripng_node
=
2724 "%s(config-router)# ",
2729 ripng_distribute_update (struct distribute
*dist
)
2731 struct interface
*ifp
;
2732 struct ripng_interface
*ri
;
2733 struct access_list
*alist
;
2734 struct prefix_list
*plist
;
2739 ifp
= if_lookup_by_name (dist
->ifname
);
2745 if (dist
->list
[DISTRIBUTE_IN
])
2747 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_IN
]);
2749 ri
->list
[RIPNG_FILTER_IN
] = alist
;
2751 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2754 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
2756 if (dist
->list
[DISTRIBUTE_OUT
])
2758 alist
= access_list_lookup (AFI_IP6
, dist
->list
[DISTRIBUTE_OUT
]);
2760 ri
->list
[RIPNG_FILTER_OUT
] = alist
;
2762 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2765 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
2767 if (dist
->prefix
[DISTRIBUTE_IN
])
2769 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_IN
]);
2771 ri
->prefix
[RIPNG_FILTER_IN
] = plist
;
2773 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2776 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
2778 if (dist
->prefix
[DISTRIBUTE_OUT
])
2780 plist
= prefix_list_lookup (AFI_IP6
, dist
->prefix
[DISTRIBUTE_OUT
]);
2782 ri
->prefix
[RIPNG_FILTER_OUT
] = plist
;
2784 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2787 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
2791 ripng_distribute_update_interface (struct interface
*ifp
)
2793 struct distribute
*dist
;
2795 dist
= distribute_lookup (ifp
->name
);
2797 ripng_distribute_update (dist
);
2800 /* Update all interface's distribute list. */
2802 ripng_distribute_update_all (struct prefix_list
*notused
)
2804 struct interface
*ifp
;
2805 struct listnode
*node
;
2807 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
2808 ripng_distribute_update_interface (ifp
);
2812 ripng_distribute_update_all_wrapper (struct access_list
*notused
)
2814 ripng_distribute_update_all(NULL
);
2817 /* delete all the added ripng routes. */
2822 struct route_node
*rp
;
2823 struct ripng_info
*rinfo
;
2826 /* Clear RIPng routes */
2827 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
)) {
2828 if ((rinfo
= rp
->info
) != NULL
) {
2829 if ((rinfo
->type
== ZEBRA_ROUTE_RIPNG
) &&
2830 (rinfo
->sub_type
== RIPNG_ROUTE_RTE
))
2831 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*)&rp
->p
,
2832 &rinfo
->nexthop
, rinfo
->metric
);
2834 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
2835 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
2838 route_unlock_node (rp
);
2840 ripng_info_free(rinfo
);
2844 /* Cancel the RIPng timers */
2845 RIPNG_TIMER_OFF (ripng
->t_update
);
2846 RIPNG_TIMER_OFF (ripng
->t_triggered_update
);
2847 RIPNG_TIMER_OFF (ripng
->t_triggered_interval
);
2849 /* Cancel the read thread */
2850 if (ripng
->t_read
) {
2851 thread_cancel (ripng
->t_read
);
2852 ripng
->t_read
= NULL
;
2855 /* Close the RIPng socket */
2856 if (ripng
->sock
>= 0) {
2861 /* Static RIPng route configuration. */
2862 for (rp
= route_top (ripng
->route
); rp
; rp
= route_next (rp
))
2865 route_unlock_node (rp
);
2868 /* RIPng aggregated prefixes */
2869 for (rp
= route_top (ripng
->aggregate
); rp
; rp
= route_next (rp
))
2872 route_unlock_node (rp
);
2875 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2876 if (ripng
->route_map
[i
].name
)
2877 free (ripng
->route_map
[i
].name
);
2879 XFREE (MTYPE_ROUTE_TABLE
, ripng
->table
);
2880 XFREE (MTYPE_ROUTE_TABLE
, ripng
->route
);
2881 XFREE (MTYPE_ROUTE_TABLE
, ripng
->aggregate
);
2883 XFREE (MTYPE_RIPNG
, ripng
);
2887 ripng_clean_network();
2888 ripng_passive_interface_clean ();
2889 ripng_offset_clean ();
2890 ripng_interface_clean ();
2891 ripng_redistribute_clean ();
2894 /* Reset all values to the default settings. */
2898 /* Call ripd related reset functions. */
2899 ripng_debug_reset ();
2900 ripng_route_map_reset ();
2902 /* Call library reset functions. */
2904 access_list_reset ();
2905 prefix_list_reset ();
2907 distribute_list_reset ();
2909 ripng_interface_reset ();
2911 ripng_zclient_reset ();
2915 ripng_if_rmap_update (struct if_rmap
*if_rmap
)
2917 struct interface
*ifp
;
2918 struct ripng_interface
*ri
;
2919 struct route_map
*rmap
;
2921 ifp
= if_lookup_by_name (if_rmap
->ifname
);
2927 if (if_rmap
->routemap
[IF_RMAP_IN
])
2929 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_IN
]);
2931 ri
->routemap
[IF_RMAP_IN
] = rmap
;
2933 ri
->routemap
[IF_RMAP_IN
] = NULL
;
2936 ri
->routemap
[RIPNG_FILTER_IN
] = NULL
;
2938 if (if_rmap
->routemap
[IF_RMAP_OUT
])
2940 rmap
= route_map_lookup_by_name (if_rmap
->routemap
[IF_RMAP_OUT
]);
2942 ri
->routemap
[IF_RMAP_OUT
] = rmap
;
2944 ri
->routemap
[IF_RMAP_OUT
] = NULL
;
2947 ri
->routemap
[RIPNG_FILTER_OUT
] = NULL
;
2951 ripng_if_rmap_update_interface (struct interface
*ifp
)
2953 struct if_rmap
*if_rmap
;
2955 if_rmap
= if_rmap_lookup (ifp
->name
);
2957 ripng_if_rmap_update (if_rmap
);
2961 ripng_routemap_update_redistribute (void)
2967 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
2969 if (ripng
->route_map
[i
].name
)
2970 ripng
->route_map
[i
].map
=
2971 route_map_lookup_by_name (ripng
->route_map
[i
].name
);
2977 ripng_routemap_update (const char *unused
)
2979 struct interface
*ifp
;
2980 struct listnode
*node
;
2982 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
2983 ripng_if_rmap_update_interface (ifp
);
2985 ripng_routemap_update_redistribute ();
2988 /* Initialize ripng structure and set commands. */
2993 srand (time (NULL
));
2995 /* Install RIPNG_NODE. */
2996 install_node (&cmd_ripng_node
, ripng_config_write
);
2998 /* Install ripng commands. */
2999 install_element (VIEW_NODE
, &show_ipv6_ripng_cmd
);
3000 install_element (VIEW_NODE
, &show_ipv6_ripng_status_cmd
);
3002 install_element (ENABLE_NODE
, &show_ipv6_ripng_cmd
);
3003 install_element (ENABLE_NODE
, &show_ipv6_ripng_status_cmd
);
3005 install_element (CONFIG_NODE
, &router_ripng_cmd
);
3006 install_element (CONFIG_NODE
, &no_router_ripng_cmd
);
3008 install_default (RIPNG_NODE
);
3009 install_element (RIPNG_NODE
, &ripng_route_cmd
);
3010 install_element (RIPNG_NODE
, &no_ripng_route_cmd
);
3011 install_element (RIPNG_NODE
, &ripng_aggregate_address_cmd
);
3012 install_element (RIPNG_NODE
, &no_ripng_aggregate_address_cmd
);
3014 install_element (RIPNG_NODE
, &ripng_default_metric_cmd
);
3015 install_element (RIPNG_NODE
, &no_ripng_default_metric_cmd
);
3016 install_element (RIPNG_NODE
, &no_ripng_default_metric_val_cmd
);
3018 install_element (RIPNG_NODE
, &ripng_timers_cmd
);
3019 install_element (RIPNG_NODE
, &no_ripng_timers_cmd
);
3020 install_element (RIPNG_NODE
, &no_ripng_timers_val_cmd
);
3022 install_element (RIPNG_NODE
, &ripng_update_timer_cmd
);
3023 install_element (RIPNG_NODE
, &no_ripng_update_timer_cmd
);
3024 install_element (RIPNG_NODE
, &ripng_timeout_timer_cmd
);
3025 install_element (RIPNG_NODE
, &no_ripng_timeout_timer_cmd
);
3026 install_element (RIPNG_NODE
, &ripng_garbage_timer_cmd
);
3027 install_element (RIPNG_NODE
, &no_ripng_garbage_timer_cmd
);
3030 install_element (RIPNG_NODE
, &ripng_default_information_originate_cmd
);
3031 install_element (RIPNG_NODE
, &no_ripng_default_information_originate_cmd
);
3034 ripng_debug_init ();
3036 /* Access list install. */
3037 access_list_init ();
3038 access_list_add_hook (ripng_distribute_update_all_wrapper
);
3039 access_list_delete_hook (ripng_distribute_update_all_wrapper
);
3041 /* Prefix list initialize.*/
3042 prefix_list_init ();
3043 prefix_list_add_hook (ripng_distribute_update_all
);
3044 prefix_list_delete_hook (ripng_distribute_update_all
);
3046 /* Distribute list install. */
3047 distribute_list_init (RIPNG_NODE
);
3048 distribute_list_add_hook (ripng_distribute_update
);
3049 distribute_list_delete_hook (ripng_distribute_update
);
3051 /* Route-map for interface. */
3052 ripng_route_map_init ();
3053 ripng_offset_init ();
3055 route_map_add_hook (ripng_routemap_update
);
3056 route_map_delete_hook (ripng_routemap_update
);
3058 if_rmap_init (RIPNG_NODE
);
3059 if_rmap_hook_add (ripng_if_rmap_update
);
3060 if_rmap_hook_delete (ripng_if_rmap_update
);