1 /* Router advertisement
2 * Copyright (C) 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 "zebra/interface.h"
35 #include "zebra/rtadv.h"
36 #include "zebra/debug.h"
37 #include "zebra/rib.h"
38 #include "zebra/zserv.h"
40 extern struct zebra_privs_t zserv_privs
;
42 #if defined (HAVE_IPV6) && defined (RTADV)
45 #include <netinet/icmp6.h>
48 /* If RFC2133 definition is used. */
49 #ifndef IPV6_JOIN_GROUP
50 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
52 #ifndef IPV6_LEAVE_GROUP
53 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
56 #define ALLNODE "ff02::1"
57 #define ALLROUTER "ff02::2"
59 extern struct zebra_t zebrad
;
61 enum rtadv_event
{RTADV_START
, RTADV_STOP
, RTADV_TIMER
, RTADV_READ
};
63 void rtadv_event (enum rtadv_event
, int);
65 int if_join_all_router (int, struct interface
*);
66 int if_leave_all_router (int, struct interface
*);
68 /* Structure which hold status of router advertisement. */
75 struct thread
*ra_read
;
76 struct thread
*ra_timer
;
79 struct rtadv
*rtadv
= NULL
;
85 new = XMALLOC (MTYPE_TMP
, sizeof (struct rtadv
));
86 memset (new, 0, sizeof (struct rtadv
));
91 rtadv_free (struct rtadv
*rtadv
)
93 XFREE (MTYPE_TMP
, rtadv
);
97 rtadv_recv_packet (int sock
, u_char
*buf
, int buflen
,
98 struct sockaddr_in6
*from
, unsigned int *ifindex
,
104 struct cmsghdr
*cmsgptr
;
109 /* Fill in message and iovec. */
110 msg
.msg_name
= (void *) from
;
111 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
114 msg
.msg_control
= (void *) adata
;
115 msg
.msg_controllen
= sizeof adata
;
117 iov
.iov_len
= buflen
;
119 /* If recvmsg fail return minus value. */
120 ret
= recvmsg (sock
, &msg
, 0);
124 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
125 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
127 /* I want interface index which this packet comes from. */
128 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
129 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
131 struct in6_pktinfo
*ptr
;
133 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
134 *ifindex
= ptr
->ipi6_ifindex
;
135 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
138 /* Incoming packet's hop limit. */
139 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
140 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
141 *hoplimit
= *((int *) CMSG_DATA (cmsgptr
));
146 #define RTADV_MSG_SIZE 4096
148 /* Send router advertisement packet. */
150 rtadv_send_packet (int sock
, struct interface
*ifp
)
154 struct cmsghdr
*cmsgptr
;
155 struct in6_pktinfo
*pkt
;
156 struct sockaddr_in6 addr
;
157 #ifdef HAVE_SOCKADDR_DL
158 struct sockaddr_dl
*sdl
;
159 #endif /* HAVE_SOCKADDR_DL */
160 static void *adata
= NULL
;
161 unsigned char buf
[RTADV_MSG_SIZE
];
162 struct nd_router_advert
*rtadv
;
165 struct zebra_if
*zif
;
166 u_char all_nodes_addr
[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
170 * Allocate control message bufffer. This is dynamic because
171 * CMSG_SPACE is not guaranteed not to call a function. Note that
172 * the size will be different on different architectures due to
173 * differing alignment rules.
177 /* XXX Free on shutdown. */
178 adata
= malloc(CMSG_SPACE(sizeof(struct in6_pktinfo
)));
181 zlog_err("rtadv_send_packet: can't malloc control data\n");
184 /* Logging of packet. */
185 if (IS_ZEBRA_DEBUG_PACKET
)
186 zlog_info ("Router advertisement send to %s", ifp
->name
);
188 /* Fill in sockaddr_in6. */
189 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
190 addr
.sin6_family
= AF_INET6
;
192 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
193 #endif /* SIN6_LEN */
194 addr
.sin6_port
= htons (IPPROTO_ICMPV6
);
195 memcpy (&addr
.sin6_addr
, all_nodes_addr
, sizeof (struct in6_addr
));
197 /* Fetch interface information. */
200 /* Make router advertisement message. */
201 rtadv
= (struct nd_router_advert
*) buf
;
203 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
204 rtadv
->nd_ra_code
= 0;
205 rtadv
->nd_ra_cksum
= 0;
207 rtadv
->nd_ra_curhoplimit
= 64;
208 rtadv
->nd_ra_flags_reserved
= 0;
209 if (zif
->rtadv
.AdvManagedFlag
)
210 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
211 if (zif
->rtadv
.AdvOtherConfigFlag
)
212 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
213 rtadv
->nd_ra_router_lifetime
= htons (zif
->rtadv
.AdvDefaultLifetime
);
214 rtadv
->nd_ra_reachable
= htonl (zif
->rtadv
.AdvReachableTime
);
215 rtadv
->nd_ra_retransmit
= htonl (0);
217 len
= sizeof (struct nd_router_advert
);
219 /* Fill in prefix. */
220 for (node
= listhead (zif
->rtadv
.AdvPrefixList
); node
; node
= nextnode (node
))
222 struct nd_opt_prefix_info
*pinfo
;
223 struct rtadv_prefix
*rprefix
;
225 rprefix
= getdata (node
);
227 pinfo
= (struct nd_opt_prefix_info
*) (buf
+ len
);
229 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
230 pinfo
->nd_opt_pi_len
= 4;
231 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
233 pinfo
->nd_opt_pi_flags_reserved
= 0;
234 if (rprefix
->AdvOnLinkFlag
)
235 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_ONLINK
;
236 if (rprefix
->AdvAutonomousFlag
)
237 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
239 pinfo
->nd_opt_pi_valid_time
= htonl (rprefix
->AdvValidLifetime
);
240 pinfo
->nd_opt_pi_preferred_time
= htonl (rprefix
->AdvPreferredLifetime
);
241 pinfo
->nd_opt_pi_reserved2
= 0;
243 memcpy (&pinfo
->nd_opt_pi_prefix
, &rprefix
->prefix
.u
.prefix6
,
244 sizeof (struct in6_addr
));
248 u_char buf
[INET6_ADDRSTRLEN
];
250 zlog_info ("DEBUG %s", inet_ntop (AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
251 buf
, INET6_ADDRSTRLEN
));
256 len
+= sizeof (struct nd_opt_prefix_info
);
259 /* Hardware address. */
260 #ifdef HAVE_SOCKADDR_DL
262 if (sdl
!= NULL
&& sdl
->sdl_alen
!= 0)
264 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
265 buf
[len
++] = (sdl
->sdl_alen
+ 2) >> 3;
267 memcpy (buf
+ len
, LLADDR (sdl
), sdl
->sdl_alen
);
268 len
+= sdl
->sdl_alen
;
271 if (ifp
->hw_addr_len
!= 0)
273 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
274 buf
[len
++] = (ifp
->hw_addr_len
+ 2) >> 3;
276 memcpy (buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
277 len
+= ifp
->hw_addr_len
;
279 #endif /* HAVE_SOCKADDR_DL */
281 msg
.msg_name
= (void *) &addr
;
282 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
285 msg
.msg_control
= (void *) adata
;
286 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
291 cmsgptr
= CMSG_FIRSTHDR(&msg
);
292 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
293 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
294 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
296 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
297 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
298 pkt
->ipi6_ifindex
= ifp
->ifindex
;
300 ret
= sendmsg (sock
, &msg
, 0);
303 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
304 errno
, strerror(errno
));
309 rtadv_timer (struct thread
*thread
)
312 struct interface
*ifp
;
313 struct zebra_if
*zif
;
315 rtadv
->ra_timer
= NULL
;
316 rtadv_event (RTADV_TIMER
, 1);
318 for (node
= listhead (iflist
); node
; nextnode (node
))
320 ifp
= getdata (node
);
322 if (if_is_loopback (ifp
))
327 if (zif
->rtadv
.AdvSendAdvertisements
)
328 if (--zif
->rtadv
.AdvIntervalTimer
<= 0)
330 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
331 rtadv_send_packet (rtadv
->sock
, ifp
);
338 rtadv_process_solicit (struct interface
*ifp
)
340 zlog_info ("Router solicitation received on %s", ifp
->name
);
342 rtadv_send_packet (rtadv
->sock
, ifp
);
346 rtadv_process_advert ()
348 zlog_info ("Router advertisement received");
352 rtadv_process_packet (u_char
*buf
, int len
, unsigned int ifindex
, int hoplimit
)
354 struct icmp6_hdr
*icmph
;
355 struct interface
*ifp
;
356 struct zebra_if
*zif
;
358 /* Interface search. */
359 ifp
= if_lookup_by_index (ifindex
);
362 zlog_warn ("Unknown interface index: %d", ifindex
);
366 if (if_is_loopback (ifp
))
369 /* Check interface configuration. */
371 if (! zif
->rtadv
.AdvSendAdvertisements
)
374 /* ICMP message length check. */
375 if (len
< sizeof (struct icmp6_hdr
))
377 zlog_warn ("Invalid ICMPV6 packet length: %d", len
);
381 icmph
= (struct icmp6_hdr
*) buf
;
383 /* ICMP message type check. */
384 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
&&
385 icmph
->icmp6_type
!= ND_ROUTER_ADVERT
)
387 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph
->icmp6_type
);
391 /* Hoplimit check. */
392 if (hoplimit
>= 0 && hoplimit
!= 255)
394 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
399 /* Check ICMP message type. */
400 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
401 rtadv_process_solicit (ifp
);
402 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
403 rtadv_process_advert ();
409 rtadv_read (struct thread
*thread
)
413 u_char buf
[RTADV_MSG_SIZE
];
414 struct sockaddr_in6 from
;
415 unsigned int ifindex
;
418 sock
= THREAD_FD (thread
);
419 rtadv
->ra_read
= NULL
;
421 /* Register myself. */
422 rtadv_event (RTADV_READ
, sock
);
424 len
= rtadv_recv_packet (sock
, buf
, BUFSIZ
, &from
, &ifindex
, &hoplimit
);
428 zlog_warn ("router solicitation recv failed: %s.", strerror (errno
));
432 rtadv_process_packet (buf
, len
, ifindex
, hoplimit
);
438 rtadv_make_socket (void)
442 struct icmp6_filter filter
;
444 if ( zserv_privs
.change (ZPRIVS_RAISE
) )
445 zlog_err ("rtadv_make_socket: could not raise privs, %s",
448 sock
= socket (AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
450 if ( zserv_privs
.change (ZPRIVS_LOWER
) )
451 zlog_err ("rtadv_make_socket: could not lower privs, %s",
454 /* When we can't make ICMPV6 socket simply back. Router
455 advertisement feature will not be supported. */
459 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
462 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
465 ret
= setsockopt_ipv6_unicast_hops (sock
, 255);
468 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
471 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
475 ICMP6_FILTER_SETBLOCKALL(&filter
);
476 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT
, &filter
);
477 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT
, &filter
);
479 ret
= setsockopt (sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
480 sizeof (struct icmp6_filter
));
483 zlog_info ("ICMP6_FILTER set fail: %s", strerror (errno
));
490 struct rtadv_prefix
*
493 struct rtadv_prefix
*new;
495 new = XMALLOC (MTYPE_RTADV_PREFIX
, sizeof (struct rtadv_prefix
));
496 memset (new, 0, sizeof (struct rtadv_prefix
));
502 rtadv_prefix_free (struct rtadv_prefix
*rtadv_prefix
)
504 XFREE (MTYPE_RTADV_PREFIX
, rtadv_prefix
);
507 struct rtadv_prefix
*
508 rtadv_prefix_lookup (list rplist
, struct prefix
*p
)
511 struct rtadv_prefix
*rprefix
;
513 for (node
= listhead (rplist
); node
; node
= nextnode (node
))
515 rprefix
= getdata (node
);
516 if (prefix_same (&rprefix
->prefix
, p
))
522 struct rtadv_prefix
*
523 rtadv_prefix_get (list rplist
, struct prefix
*p
)
525 struct rtadv_prefix
*rprefix
;
527 rprefix
= rtadv_prefix_lookup (rplist
, p
);
531 rprefix
= rtadv_prefix_new ();
532 memcpy (&rprefix
->prefix
, p
, sizeof (struct prefix
));
533 listnode_add (rplist
, rprefix
);
539 rtadv_prefix_set (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
541 struct rtadv_prefix
*rprefix
;
543 rprefix
= rtadv_prefix_get (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
545 /* Set parameters. */
546 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
547 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
548 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
549 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
553 rtadv_prefix_reset (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
555 struct rtadv_prefix
*rprefix
;
557 rprefix
= rtadv_prefix_lookup (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
560 listnode_delete (zif
->rtadv
.AdvPrefixList
, (void *) rprefix
);
561 rtadv_prefix_free (rprefix
);
568 DEFUN (ipv6_nd_suppress_ra
,
569 ipv6_nd_suppress_ra_cmd
,
570 "ipv6 nd suppress-ra",
571 "Interface IPv6 config commands\n"
572 "Neighbor discovery\n"
573 "Suppress Router Advertisement\n")
575 struct interface
*ifp
;
576 struct zebra_if
*zif
;
581 if (if_is_loopback (ifp
))
583 vty_out (vty
, "Invalid interface%s", VTY_NEWLINE
);
587 if (zif
->rtadv
.AdvSendAdvertisements
)
589 zif
->rtadv
.AdvSendAdvertisements
= 0;
590 zif
->rtadv
.AdvIntervalTimer
= 0;
591 rtadv
->adv_if_count
--;
593 if_leave_all_router (rtadv
->sock
, ifp
);
595 if (rtadv
->adv_if_count
== 0)
596 rtadv_event (RTADV_STOP
, 0);
602 DEFUN (no_ipv6_nd_suppress_ra
,
603 no_ipv6_nd_suppress_ra_cmd
,
604 "no ipv6 nd suppress-ra",
606 "Interface IPv6 config commands\n"
607 "Neighbor discovery\n"
608 "Suppress Router Advertisement\n")
610 struct interface
*ifp
;
611 struct zebra_if
*zif
;
616 if (if_is_loopback (ifp
))
618 vty_out (vty
, "Invalid interface%s", VTY_NEWLINE
);
622 if (! zif
->rtadv
.AdvSendAdvertisements
)
624 zif
->rtadv
.AdvSendAdvertisements
= 1;
625 zif
->rtadv
.AdvIntervalTimer
= 0;
626 rtadv
->adv_if_count
++;
628 if_join_all_router (rtadv
->sock
, ifp
);
630 if (rtadv
->adv_if_count
== 1)
631 rtadv_event (RTADV_START
, rtadv
->sock
);
637 DEFUN (ipv6_nd_ra_interval
,
638 ipv6_nd_ra_interval_cmd
,
639 "ipv6 nd ra-interval SECONDS",
640 "Interface IPv6 config commands\n"
641 "Neighbor discovery\n"
642 "Router Advertisement interval\n"
643 "Router Advertisement interval in seconds\n")
646 struct interface
*ifp
;
647 struct zebra_if
*zif
;
649 ifp
= (struct interface
*) vty
->index
;
652 interval
= atoi (argv
[0]);
656 vty_out (vty
, "Invalid Router Advertisement Interval%s", VTY_NEWLINE
);
660 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
661 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
662 zif
->rtadv
.AdvIntervalTimer
= 0;
667 DEFUN (no_ipv6_nd_ra_interval
,
668 no_ipv6_nd_ra_interval_cmd
,
669 "no ipv6 nd ra-interval",
671 "Interface IPv6 config commands\n"
672 "Neighbor discovery\n"
673 "Router Advertisement interval\n")
675 struct interface
*ifp
;
676 struct zebra_if
*zif
;
678 ifp
= (struct interface
*) vty
->index
;
681 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
682 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
683 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
688 DEFUN (ipv6_nd_ra_lifetime
,
689 ipv6_nd_ra_lifetime_cmd
,
690 "ipv6 nd ra-lifetime SECONDS",
691 "Interface IPv6 config commands\n"
692 "Neighbor discovery\n"
694 "Router lifetime in seconds\n")
697 struct interface
*ifp
;
698 struct zebra_if
*zif
;
700 ifp
= (struct interface
*) vty
->index
;
703 lifetime
= atoi (argv
[0]);
705 if (lifetime
< 0 || lifetime
> 0xffff)
707 vty_out (vty
, "Invalid Router Lifetime%s", VTY_NEWLINE
);
711 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
716 DEFUN (no_ipv6_nd_ra_lifetime
,
717 no_ipv6_nd_ra_lifetime_cmd
,
718 "no ipv6 nd ra-lifetime",
720 "Interface IPv6 config commands\n"
721 "Neighbor discovery\n"
724 struct interface
*ifp
;
725 struct zebra_if
*zif
;
727 ifp
= (struct interface
*) vty
->index
;
730 zif
->rtadv
.AdvDefaultLifetime
= RTADV_ADV_DEFAULT_LIFETIME
;
735 DEFUN (ipv6_nd_reachable_time
,
736 ipv6_nd_reachable_time_cmd
,
737 "ipv6 nd reachable-time MILLISECONDS",
738 "Interface IPv6 config commands\n"
739 "Neighbor discovery\n"
741 "Reachable time in milliseconds\n")
744 struct interface
*ifp
;
745 struct zebra_if
*zif
;
747 ifp
= (struct interface
*) vty
->index
;
750 rtime
= (u_int32_t
) atol (argv
[0]);
752 if (rtime
> RTADV_MAX_REACHABLE_TIME
)
754 vty_out (vty
, "Invalid Reachable time%s", VTY_NEWLINE
);
758 zif
->rtadv
.AdvReachableTime
= rtime
;
763 DEFUN (no_ipv6_nd_reachable_time
,
764 no_ipv6_nd_reachable_time_cmd
,
765 "no ipv6 nd reachable-time",
767 "Interface IPv6 config commands\n"
768 "Neighbor discovery\n"
771 struct interface
*ifp
;
772 struct zebra_if
*zif
;
774 ifp
= (struct interface
*) vty
->index
;
777 zif
->rtadv
.AdvReachableTime
= 0;
782 DEFUN (ipv6_nd_managed_config_flag
,
783 ipv6_nd_managed_config_flag_cmd
,
784 "ipv6 nd managed-config-flag",
785 "Interface IPv6 config commands\n"
786 "Neighbor discovery\n"
787 "Managed address configuration flag\n")
789 struct interface
*ifp
;
790 struct zebra_if
*zif
;
792 ifp
= (struct interface
*) vty
->index
;
795 zif
->rtadv
.AdvManagedFlag
= 1;
800 DEFUN (no_ipv6_nd_managed_config_flag
,
801 no_ipv6_nd_managed_config_flag_cmd
,
802 "no ipv6 nd managed-config-flag",
804 "Interface IPv6 config commands\n"
805 "Neighbor discovery\n"
806 "Managed address configuration flag\n")
808 struct interface
*ifp
;
809 struct zebra_if
*zif
;
811 ifp
= (struct interface
*) vty
->index
;
814 zif
->rtadv
.AdvManagedFlag
= 0;
819 DEFUN (ipv6_nd_other_config_flag
,
820 ipv6_nd_other_config_flag_cmd
,
821 "ipv6 nd other-config-flag",
822 "Interface IPv6 config commands\n"
823 "Neighbor discovery\n"
824 "Other statefull configuration flag\n")
826 struct interface
*ifp
;
827 struct zebra_if
*zif
;
829 ifp
= (struct interface
*) vty
->index
;
832 zif
->rtadv
.AdvOtherConfigFlag
= 1;
837 DEFUN (no_ipv6_nd_other_config_flag
,
838 no_ipv6_nd_other_config_flag_cmd
,
839 "no ipv6 nd other-config-flag",
841 "Interface IPv6 config commands\n"
842 "Neighbor discovery\n"
843 "Other statefull configuration flag\n")
845 struct interface
*ifp
;
846 struct zebra_if
*zif
;
848 ifp
= (struct interface
*) vty
->index
;
851 zif
->rtadv
.AdvOtherConfigFlag
= 0;
856 DEFUN (ipv6_nd_prefix
,
858 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
859 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
860 "Interface IPv6 config commands\n"
861 "Neighbor discovery\n"
862 "Prefix information\n"
864 "Valid lifetime in seconds\n"
865 "Infinite valid lifetime\n"
866 "Preferred lifetime in seconds\n"
867 "Infinite preferred lifetime\n"
868 "Do not use prefix for onlink determination\n"
869 "Do not use prefix for autoconfiguration\n")
874 struct interface
*ifp
;
875 struct zebra_if
*zebra_if
;
876 struct rtadv_prefix rp
;
878 ifp
= (struct interface
*) vty
->index
;
879 zebra_if
= ifp
->info
;
881 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &rp
.prefix
);
884 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
887 rp
.AdvOnLinkFlag
= 1;
888 rp
.AdvAutonomousFlag
= 1;
889 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
890 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
894 if ((isdigit(argv
[1][0])) || strncmp (argv
[1], "i", 1) == 0)
896 if ( strncmp (argv
[1], "i", 1) == 0)
897 rp
.AdvValidLifetime
= UINT32_MAX
;
899 rp
.AdvValidLifetime
= (u_int32_t
) strtoll (argv
[1],
902 if ( strncmp (argv
[2], "i", 1) == 0)
903 rp
.AdvPreferredLifetime
= UINT32_MAX
;
905 rp
.AdvPreferredLifetime
= (u_int32_t
) strtoll (argv
[2],
908 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
)
910 vty_out (vty
, "Invalid preferred lifetime%s", VTY_NEWLINE
);
917 for (i
= cursor
; i
< argc
; i
++)
919 if (strncmp (argv
[i
], "of", 2) == 0)
920 rp
.AdvOnLinkFlag
= 0;
921 if (strncmp (argv
[i
], "no", 2) == 0)
922 rp
.AdvAutonomousFlag
= 0;
927 rtadv_prefix_set (zebra_if
, &rp
);
932 ALIAS (ipv6_nd_prefix
,
933 ipv6_nd_prefix_val_rev_cmd
,
934 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
935 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
936 "Interface IPv6 config commands\n"
937 "Neighbor discovery\n"
938 "Prefix information\n"
940 "Valid lifetime in seconds\n"
941 "Infinite valid lifetime\n"
942 "Preferred lifetime in seconds\n"
943 "Infinite preferred lifetime\n"
944 "Do not use prefix for autoconfiguration\n"
945 "Do not use prefix for onlink determination\n")
947 ALIAS (ipv6_nd_prefix
,
948 ipv6_nd_prefix_val_noauto_cmd
,
949 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
950 "(<0-4294967295>|infinite) (no-autoconfig|)",
951 "Interface IPv6 config commands\n"
952 "Neighbor discovery\n"
953 "Prefix information\n"
955 "Valid lifetime in seconds\n"
956 "Infinite valid lifetime\n"
957 "Preferred lifetime in seconds\n"
958 "Infinite preferred lifetime\n"
959 "Do not use prefix for autoconfigurationn")
961 ALIAS (ipv6_nd_prefix
,
962 ipv6_nd_prefix_val_offlink_cmd
,
963 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
964 "(<0-4294967295>|infinite) (off-link|)",
965 "Interface IPv6 config commands\n"
966 "Neighbor discovery\n"
967 "Prefix information\n"
969 "Valid lifetime in seconds\n"
970 "Infinite valid lifetime\n"
971 "Preferred lifetime in seconds\n"
972 "Infinite preferred lifetime\n"
973 "Do not use prefix for onlink determination\n")
975 ALIAS (ipv6_nd_prefix
,
976 ipv6_nd_prefix_val_cmd
,
977 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
978 "(<0-4294967295>|infinite)",
979 "Interface IPv6 config commands\n"
980 "Neighbor discovery\n"
981 "Prefix information\n"
983 "Valid lifetime in seconds\n"
984 "Infinite valid lifetime\n"
985 "Preferred lifetime in seconds\n"
986 "Infinite preferred lifetime\n")
988 ALIAS (ipv6_nd_prefix
,
989 ipv6_nd_prefix_noval_cmd
,
990 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
991 "Interface IPv6 config commands\n"
992 "Neighbor discovery\n"
993 "Prefix information\n"
995 "Do not use prefix for autoconfiguration\n"
996 "Do not use prefix for onlink determination\n")
998 ALIAS (ipv6_nd_prefix
,
999 ipv6_nd_prefix_noval_rev_cmd
,
1000 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1001 "Interface IPv6 config commands\n"
1002 "Neighbor discovery\n"
1003 "Prefix information\n"
1005 "Do not use prefix for onlink determination\n"
1006 "Do not use prefix for autoconfiguration\n")
1008 ALIAS (ipv6_nd_prefix
,
1009 ipv6_nd_prefix_noval_noauto_cmd
,
1010 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1011 "Interface IPv6 config commands\n"
1012 "Neighbor discovery\n"
1013 "Prefix information\n"
1015 "Do not use prefix for autoconfiguration\n")
1017 ALIAS (ipv6_nd_prefix
,
1018 ipv6_nd_prefix_noval_offlink_cmd
,
1019 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1020 "Interface IPv6 config commands\n"
1021 "Neighbor discovery\n"
1022 "Prefix information\n"
1024 "Do not use prefix for onlink determination\n")
1026 ALIAS (ipv6_nd_prefix
,
1027 ipv6_nd_prefix_prefix_cmd
,
1028 "ipv6 nd prefix X:X::X:X/M",
1029 "Interface IPv6 config commands\n"
1030 "Neighbor discovery\n"
1031 "Prefix information\n"
1034 DEFUN (no_ipv6_nd_prefix
,
1035 no_ipv6_nd_prefix_cmd
,
1036 "no ipv6 nd prefix IPV6PREFIX",
1038 "Interface IPv6 config commands\n"
1039 "Neighbor discovery\n"
1040 "Prefix information\n"
1044 struct interface
*ifp
;
1045 struct zebra_if
*zebra_if
;
1046 struct rtadv_prefix rp
;
1048 ifp
= (struct interface
*) vty
->index
;
1049 zebra_if
= ifp
->info
;
1051 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &rp
.prefix
);
1054 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
1058 ret
= rtadv_prefix_reset (zebra_if
, &rp
);
1061 vty_out (vty
, "Non-exist IPv6 prefix%s", VTY_NEWLINE
);
1068 /* Write configuration about router advertisement. */
1070 rtadv_config_write (struct vty
*vty
, struct interface
*ifp
)
1072 struct zebra_if
*zif
;
1074 struct rtadv_prefix
*rprefix
;
1075 u_char buf
[INET6_ADDRSTRLEN
];
1082 if (! if_is_loopback (ifp
))
1084 if (zif
->rtadv
.AdvSendAdvertisements
)
1085 vty_out (vty
, " no ipv6 nd suppress-ra%s", VTY_NEWLINE
);
1087 vty_out (vty
, " ipv6 nd suppress-ra%s", VTY_NEWLINE
);
1090 if (zif
->rtadv
.MaxRtrAdvInterval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1091 vty_out (vty
, " ipv6 nd ra-interval %d%s", zif
->rtadv
.MaxRtrAdvInterval
,
1094 if (zif
->rtadv
.AdvDefaultLifetime
!= RTADV_ADV_DEFAULT_LIFETIME
)
1095 vty_out (vty
, " ipv6 nd ra-lifetime %d%s", zif
->rtadv
.AdvDefaultLifetime
,
1098 if (zif
->rtadv
.AdvReachableTime
)
1099 vty_out (vty
, " ipv6 nd reachable-time %d%s", zif
->rtadv
.AdvReachableTime
,
1102 if (zif
->rtadv
.AdvManagedFlag
)
1103 vty_out (vty
, " ipv6 nd managed-config-flag%s", VTY_NEWLINE
);
1105 if (zif
->rtadv
.AdvOtherConfigFlag
)
1106 vty_out (vty
, " ipv6 nd other-config-flag%s", VTY_NEWLINE
);
1108 for (node
= listhead(zif
->rtadv
.AdvPrefixList
); node
; node
= nextnode (node
))
1110 rprefix
= getdata (node
);
1111 vty_out (vty
, " ipv6 nd prefix %s/%d",
1112 inet_ntop (AF_INET6
, &rprefix
->prefix
.u
.prefix6
,
1113 buf
, INET6_ADDRSTRLEN
),
1114 rprefix
->prefix
.prefixlen
);
1115 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
) ||
1116 (rprefix
->AdvPreferredLifetime
!= RTADV_PREFERRED_LIFETIME
))
1118 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1119 vty_out (vty
, " infinite");
1121 vty_out (vty
, " %u", rprefix
->AdvValidLifetime
);
1122 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1123 vty_out (vty
, " infinite");
1125 vty_out (vty
, " %u", rprefix
->AdvPreferredLifetime
);
1127 if (!rprefix
->AdvOnLinkFlag
)
1128 vty_out (vty
, " off-link");
1129 if (!rprefix
->AdvAutonomousFlag
)
1130 vty_out (vty
, " no-autoconfig");
1131 vty_out (vty
, "%s", VTY_NEWLINE
);
1137 rtadv_event (enum rtadv_event event
, int val
)
1142 if (! rtadv
->ra_read
)
1143 rtadv
->ra_read
= thread_add_read (zebrad
.master
, rtadv_read
, NULL
, val
);
1144 if (! rtadv
->ra_timer
)
1145 rtadv
->ra_timer
= thread_add_event (zebrad
.master
, rtadv_timer
,
1149 if (rtadv
->ra_timer
)
1151 thread_cancel (rtadv
->ra_timer
);
1152 rtadv
->ra_timer
= NULL
;
1156 thread_cancel (rtadv
->ra_read
);
1157 rtadv
->ra_read
= NULL
;
1161 if (! rtadv
->ra_timer
)
1162 rtadv
->ra_timer
= thread_add_timer (zebrad
.master
, rtadv_timer
, NULL
,
1166 if (! rtadv
->ra_read
)
1167 rtadv
->ra_read
= thread_add_read (zebrad
.master
, rtadv_read
, NULL
, val
);
1180 sock
= rtadv_make_socket ();
1184 rtadv
= rtadv_new ();
1187 install_element (INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1188 install_element (INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1189 install_element (INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1190 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1191 install_element (INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1192 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1193 install_element (INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1194 install_element (INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1195 install_element (INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1196 install_element (INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1197 install_element (INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1198 install_element (INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1199 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1200 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_val_rev_cmd
);
1201 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_val_noauto_cmd
);
1202 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_val_offlink_cmd
);
1203 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_val_cmd
);
1204 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_noval_cmd
);
1205 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_noval_rev_cmd
);
1206 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_noval_noauto_cmd
);
1207 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_noval_offlink_cmd
);
1208 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_prefix_cmd
);
1209 install_element (INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1213 if_join_all_router (int sock
, struct interface
*ifp
)
1217 struct ipv6_mreq mreq
;
1219 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1220 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1221 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1223 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
1224 (char *) &mreq
, sizeof mreq
);
1226 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno
));
1228 zlog_info ("rtadv: %s join to all-routers multicast group", ifp
->name
);
1234 if_leave_all_router (int sock
, struct interface
*ifp
)
1238 struct ipv6_mreq mreq
;
1240 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1241 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1242 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1244 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
1245 (char *) &mreq
, sizeof mreq
);
1247 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", strerror (errno
));
1249 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp
->name
);
1260 #endif /* RTADV && HAVE_IPV6 */