1 /* Router advertisement
2 * Copyright (C) 2016 Cumulus Networks
3 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
4 * Copyright (C) 1999 Kunihiro Ishiguro
6 * This file is part of GNU Zebra.
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "zebra_memory.h"
38 #include "zebra/interface.h"
39 #include "zebra/rtadv.h"
40 #include "zebra/debug.h"
41 #include "zebra/rib.h"
42 #include "zebra/zserv.h"
43 #include "zebra/zebra_ns.h"
44 #include "zebra/zebra_vrf.h"
46 extern struct zebra_privs_t zserv_privs
;
48 #if defined(HAVE_RTADV)
51 #include <netinet/icmp6.h>
54 /* If RFC2133 definition is used. */
55 #ifndef IPV6_JOIN_GROUP
56 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
58 #ifndef IPV6_LEAVE_GROUP
59 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
62 #define ALLNODE "ff02::1"
63 #define ALLROUTER "ff02::2"
65 /* Order is intentional. Matches RFC4191. This array is also used for
66 command matching, so only modify with care. */
67 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
77 static void rtadv_event(struct zebra_ns
*, enum rtadv_event
, int);
79 static int if_join_all_router(int, struct interface
*);
80 static int if_leave_all_router(int, struct interface
*);
82 static int rtadv_increment_received(struct zebra_ns
*zns
, ifindex_t
*ifindex
)
85 struct interface
*iface
;
88 iface
= if_lookup_by_index_per_ns(zns
, *ifindex
);
89 if (iface
&& iface
->info
) {
97 static int rtadv_recv_packet(struct zebra_ns
*zns
, int sock
, u_char
*buf
,
98 int buflen
, struct sockaddr_in6
*from
,
99 ifindex_t
*ifindex
, int *hoplimit
)
104 struct cmsghdr
*cmsgptr
;
109 /* Fill in message and iovec. */
110 memset(&msg
, 0, sizeof(msg
));
111 msg
.msg_name
= (void *)from
;
112 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
115 msg
.msg_control
= (void *)adata
;
116 msg
.msg_controllen
= sizeof adata
;
118 iov
.iov_len
= buflen
;
120 /* If recvmsg fail return minus value. */
121 ret
= recvmsg(sock
, &msg
, 0);
125 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
126 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
) {
130 struct in6_pktinfo
*ptr
;
132 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
133 *ifindex
= ptr
->ipi6_ifindex
;
134 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
137 /* Incoming packet's hop limit. */
138 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
139 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
140 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
145 rtadv_increment_received(zns
, ifindex
);
149 #define RTADV_MSG_SIZE 4096
151 /* Send router advertisement packet. */
152 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
156 struct cmsghdr
*cmsgptr
;
157 struct in6_pktinfo
*pkt
;
158 struct sockaddr_in6 addr
;
159 static void *adata
= NULL
;
160 unsigned char buf
[RTADV_MSG_SIZE
];
161 struct nd_router_advert
*rtadv
;
164 struct zebra_if
*zif
;
165 struct rtadv_prefix
*rprefix
;
166 u_char all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
167 0, 0, 0, 0, 0, 0, 0, 1};
168 struct listnode
*node
;
169 u_int16_t pkt_RouterLifetime
;
172 * Allocate control message bufffer. This is dynamic because
173 * CMSG_SPACE is not guaranteed not to call a function. Note that
174 * the size will be different on different architectures due to
175 * differing alignment rules.
178 /* XXX Free on shutdown. */
179 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
183 "rtadv_send_packet: can't malloc control data");
188 /* Logging of packet. */
189 if (IS_ZEBRA_DEBUG_PACKET
)
190 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
193 /* Fill in sockaddr_in6. */
194 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
195 addr
.sin6_family
= AF_INET6
;
197 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
198 #endif /* SIN6_LEN */
199 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
200 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
202 /* Fetch interface information. */
205 /* Make router advertisement message. */
206 rtadv
= (struct nd_router_advert
*)buf
;
208 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
209 rtadv
->nd_ra_code
= 0;
210 rtadv
->nd_ra_cksum
= 0;
212 rtadv
->nd_ra_curhoplimit
= 64;
214 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
215 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
217 : zif
->rtadv
.DefaultPreference
;
218 rtadv
->nd_ra_flags_reserved
<<= 3;
220 if (zif
->rtadv
.AdvManagedFlag
)
221 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
222 if (zif
->rtadv
.AdvOtherConfigFlag
)
223 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
224 if (zif
->rtadv
.AdvHomeAgentFlag
)
225 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
226 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
227 * AdvDefaultLifetime is by default based on the value of
228 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
229 * field of Router Advertisements. Given that this field is expressed
230 * in seconds, a small MaxRtrAdvInterval value can result in a zero
231 * value for this field. To prevent this, routers SHOULD keep
232 * AdvDefaultLifetime in at least one second, even if the use of
233 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
235 zif
->rtadv
.AdvDefaultLifetime
!= -1
236 ? zif
->rtadv
.AdvDefaultLifetime
237 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
238 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
239 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
240 rtadv
->nd_ra_retransmit
= htonl(0);
242 len
= sizeof(struct nd_router_advert
);
244 /* If both the Home Agent Preference and Home Agent Lifetime are set to
245 * their default values specified above, this option SHOULD NOT be
246 * included in the Router Advertisement messages sent by this home
247 * agent. -- RFC6275, 7.4 */
248 if (zif
->rtadv
.AdvHomeAgentFlag
249 && (zif
->rtadv
.HomeAgentPreference
250 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
251 struct nd_opt_homeagent_info
*ndopt_hai
=
252 (struct nd_opt_homeagent_info
*)(buf
+ len
);
253 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
254 ndopt_hai
->nd_opt_hai_len
= 1;
255 ndopt_hai
->nd_opt_hai_reserved
= 0;
256 ndopt_hai
->nd_opt_hai_preference
=
257 htons(zif
->rtadv
.HomeAgentPreference
);
258 /* 16-bit unsigned integer. The lifetime associated with the
260 * agent in units of seconds. The default value is the same as
262 * Router Lifetime, as specified in the main body of the Router
263 * Advertisement. The maximum value corresponds to 18.2 hours.
265 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
266 ndopt_hai
->nd_opt_hai_lifetime
=
267 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
268 ? zif
->rtadv
.HomeAgentLifetime
269 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
274 len
+= sizeof(struct nd_opt_homeagent_info
);
277 if (zif
->rtadv
.AdvIntervalOption
) {
278 struct nd_opt_adv_interval
*ndopt_adv
=
279 (struct nd_opt_adv_interval
*)(buf
+ len
);
280 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
281 ndopt_adv
->nd_opt_ai_len
= 1;
282 ndopt_adv
->nd_opt_ai_reserved
= 0;
283 ndopt_adv
->nd_opt_ai_interval
=
284 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
285 len
+= sizeof(struct nd_opt_adv_interval
);
288 /* Fill in prefix. */
289 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
290 struct nd_opt_prefix_info
*pinfo
;
292 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
294 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
295 pinfo
->nd_opt_pi_len
= 4;
296 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
298 pinfo
->nd_opt_pi_flags_reserved
= 0;
299 if (rprefix
->AdvOnLinkFlag
)
300 pinfo
->nd_opt_pi_flags_reserved
|=
301 ND_OPT_PI_FLAG_ONLINK
;
302 if (rprefix
->AdvAutonomousFlag
)
303 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
304 if (rprefix
->AdvRouterAddressFlag
)
305 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
307 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
308 pinfo
->nd_opt_pi_preferred_time
=
309 htonl(rprefix
->AdvPreferredLifetime
);
310 pinfo
->nd_opt_pi_reserved2
= 0;
312 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
313 &rprefix
->prefix
.prefix
);
317 u_char buf
[INET6_ADDRSTRLEN
];
319 zlog_debug("DEBUG %s",
320 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
321 buf
, INET6_ADDRSTRLEN
));
325 len
+= sizeof(struct nd_opt_prefix_info
);
328 /* Hardware address. */
329 if (ifp
->hw_addr_len
!= 0) {
330 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
332 /* Option length should be rounded up to next octet if
333 the link address does not end on an octet boundary. */
334 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
336 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
337 len
+= ifp
->hw_addr_len
;
339 /* Pad option to end on an octet boundary. */
340 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
341 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
345 if (zif
->rtadv
.AdvLinkMTU
) {
346 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
347 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
348 opt
->nd_opt_mtu_len
= 1;
349 opt
->nd_opt_mtu_reserved
= 0;
350 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
351 len
+= sizeof(struct nd_opt_mtu
);
354 msg
.msg_name
= (void *)&addr
;
355 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
358 msg
.msg_control
= (void *)adata
;
359 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
364 cmsgptr
= ZCMSG_FIRSTHDR(&msg
);
365 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
366 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
367 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
369 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
370 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
371 pkt
->ipi6_ifindex
= ifp
->ifindex
;
373 ret
= sendmsg(sock
, &msg
, 0);
375 zlog_err("%s(%u): Tx RA failed, socket %u error %d (%s)",
376 ifp
->name
, ifp
->ifindex
, sock
, errno
,
377 safe_strerror(errno
));
382 static int rtadv_timer(struct thread
*thread
)
384 struct zebra_ns
*zns
= THREAD_ARG(thread
);
386 struct interface
*ifp
;
387 struct zebra_if
*zif
;
390 zns
->rtadv
.ra_timer
= NULL
;
391 if (zns
->rtadv
.adv_msec_if_count
== 0) {
392 period
= 1000; /* 1 s */
393 rtadv_event(zns
, RTADV_TIMER
, 1 /* 1 s */);
395 period
= 10; /* 10 ms */
396 rtadv_event(zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
399 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
400 FOR_ALL_INTERFACES (vrf
, ifp
) {
401 if (if_is_loopback(ifp
)
402 || CHECK_FLAG(ifp
->status
,
403 ZEBRA_INTERFACE_VRF_LOOPBACK
)
404 || !if_is_operative(ifp
))
409 if (zif
->rtadv
.AdvSendAdvertisements
) {
410 if (zif
->rtadv
.inFastRexmit
) {
411 /* We assume we fast rexmit every sec so
414 if (--zif
->rtadv
.NumFastReXmitsRemain
416 zif
->rtadv
.inFastRexmit
= 0;
418 if (IS_ZEBRA_DEBUG_SEND
)
420 "Fast RA Rexmit on interface %s",
423 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
425 zif
->rtadv
.AdvIntervalTimer
-= period
;
426 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
428 MaxRtrAdvInterval each
429 time isn't what section
430 6.2.4 of RFC4861 tells to do.
432 zif
->rtadv
.AdvIntervalTimer
=
436 zns
->rtadv
.sock
, ifp
);
445 static void rtadv_process_solicit(struct interface
*ifp
)
447 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
448 struct zebra_ns
*zns
= zvrf
->zns
;
451 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
454 static void rtadv_process_advert(u_char
*msg
, unsigned int len
,
455 struct interface
*ifp
,
456 struct sockaddr_in6
*addr
)
458 struct nd_router_advert
*radvert
;
459 char addr_str
[INET6_ADDRSTRLEN
];
460 struct zebra_if
*zif
;
465 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
467 if (len
< sizeof(struct nd_router_advert
)) {
468 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
469 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
472 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
474 "%s(%u): Rx RA with non-linklocal source address from %s",
475 ifp
->name
, ifp
->ifindex
, addr_str
);
479 radvert
= (struct nd_router_advert
*)msg
;
481 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
482 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
484 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
485 ifp
->name
, ifp
->ifindex
, addr_str
);
488 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
489 && !zif
->rtadv
.AdvManagedFlag
) {
491 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
492 ifp
->name
, ifp
->ifindex
, addr_str
);
495 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
496 && !zif
->rtadv
.AdvOtherConfigFlag
) {
498 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
499 ifp
->name
, ifp
->ifindex
, addr_str
);
502 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
503 && (ntohl(radvert
->nd_ra_reachable
)
504 != zif
->rtadv
.AdvReachableTime
)) {
506 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
507 ifp
->name
, ifp
->ifindex
, addr_str
);
510 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
511 && (ntohl(radvert
->nd_ra_retransmit
)
512 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
514 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
515 ifp
->name
, ifp
->ifindex
, addr_str
);
518 /* Create entry for neighbor if not known. */
520 IPV6_ADDR_COPY(&p
.u
.prefix
, &addr
->sin6_addr
);
521 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
523 if (!nbr_connected_check(ifp
, &p
))
524 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
528 static void rtadv_process_packet(u_char
*buf
, unsigned int len
,
529 ifindex_t ifindex
, int hoplimit
,
530 struct sockaddr_in6
*from
,
531 struct zebra_ns
*zns
)
533 struct icmp6_hdr
*icmph
;
534 struct interface
*ifp
;
535 struct zebra_if
*zif
;
536 char addr_str
[INET6_ADDRSTRLEN
];
538 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
540 /* Interface search. */
541 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
543 zlog_warn("RA/RS received on unknown IF %u from %s", ifindex
,
548 if (IS_ZEBRA_DEBUG_PACKET
)
549 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
550 ifp
->ifindex
, len
, addr_str
);
552 if (if_is_loopback(ifp
)
553 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
556 /* Check interface configuration. */
558 if (!zif
->rtadv
.AdvSendAdvertisements
)
561 /* ICMP message length check. */
562 if (len
< sizeof(struct icmp6_hdr
)) {
563 zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
564 ifp
->name
, ifp
->ifindex
, len
);
568 icmph
= (struct icmp6_hdr
*)buf
;
570 /* ICMP message type check. */
571 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
572 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
573 zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
574 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
578 /* Hoplimit check. */
579 if (hoplimit
>= 0 && hoplimit
!= 255) {
580 zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
581 ifp
->ifindex
, hoplimit
);
585 /* Check ICMP message type. */
586 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
587 rtadv_process_solicit(ifp
);
588 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
589 rtadv_process_advert(buf
, len
, ifp
, from
);
594 static int rtadv_read(struct thread
*thread
)
598 u_char buf
[RTADV_MSG_SIZE
];
599 struct sockaddr_in6 from
;
600 ifindex_t ifindex
= 0;
602 struct zebra_ns
*zns
= THREAD_ARG(thread
);
604 sock
= THREAD_FD(thread
);
605 zns
->rtadv
.ra_read
= NULL
;
607 /* Register myself. */
608 rtadv_event(zns
, RTADV_READ
, sock
);
610 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
614 zlog_warn("RA/RS recv failed, socket %u error %s", sock
,
615 safe_strerror(errno
));
619 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
624 static int rtadv_make_socket(void)
628 struct icmp6_filter filter
;
630 if (zserv_privs
.change(ZPRIVS_RAISE
))
631 zlog_err("rtadv_make_socket: could not raise privs, %s",
632 safe_strerror(errno
));
634 sock
= socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
636 if (zserv_privs
.change(ZPRIVS_LOWER
))
637 zlog_err("rtadv_make_socket: could not lower privs, %s",
638 safe_strerror(errno
));
644 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
649 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
654 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
659 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
664 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
670 ICMP6_FILTER_SETBLOCKALL(&filter
);
671 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
672 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
674 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
675 sizeof(struct icmp6_filter
));
677 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
685 static struct rtadv_prefix
*rtadv_prefix_new(void)
687 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
690 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
692 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
695 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
696 struct prefix_ipv6
*p
)
698 struct listnode
*node
;
699 struct rtadv_prefix
*rprefix
;
701 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
702 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
708 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
709 struct prefix_ipv6
*p
)
711 struct rtadv_prefix
*rprefix
;
713 rprefix
= rtadv_prefix_lookup(rplist
, p
);
717 rprefix
= rtadv_prefix_new();
718 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
719 listnode_add(rplist
, rprefix
);
724 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
726 struct rtadv_prefix
*rprefix
;
728 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
730 /* Set parameters. */
731 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
732 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
733 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
734 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
735 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
738 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
740 struct rtadv_prefix
*rprefix
;
742 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
743 if (rprefix
!= NULL
) {
744 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
745 rtadv_prefix_free(rprefix
);
751 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
752 ipv6_nd_suppress_ra_status status
)
754 struct zebra_if
*zif
;
755 struct zebra_vrf
*zvrf
;
756 struct zebra_ns
*zns
;
759 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
762 if (status
== RA_SUPPRESS
) {
763 /* RA is currently enabled */
764 if (zif
->rtadv
.AdvSendAdvertisements
) {
765 zif
->rtadv
.AdvSendAdvertisements
= 0;
766 zif
->rtadv
.AdvIntervalTimer
= 0;
767 zns
->rtadv
.adv_if_count
--;
769 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
771 if (zns
->rtadv
.adv_if_count
== 0)
772 rtadv_event(zns
, RTADV_STOP
, 0);
775 if (!zif
->rtadv
.AdvSendAdvertisements
) {
776 zif
->rtadv
.AdvSendAdvertisements
= 1;
777 zif
->rtadv
.AdvIntervalTimer
= 0;
778 zns
->rtadv
.adv_if_count
++;
780 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
781 /* Enable Fast RA only when RA interval is in
783 zif
->rtadv
.inFastRexmit
= 1;
784 zif
->rtadv
.NumFastReXmitsRemain
=
785 RTADV_NUM_FAST_REXMITS
;
788 if_join_all_router(zns
->rtadv
.sock
, ifp
);
790 if (zns
->rtadv
.adv_if_count
== 1)
791 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
797 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
798 * Note that while the client could request RA on an interface on which the
799 * operator has not enabled RA, RA won't be disabled upon client request
800 * if the operator has explicitly enabled RA. The enable request can also
801 * specify a RA interval (in seconds).
803 void zebra_interface_radv_set(struct zserv
*client
, u_short length
,
804 struct zebra_vrf
*zvrf
, int enable
)
808 struct interface
*ifp
;
809 struct zebra_if
*zif
;
814 /* Get interface index and RA interval. */
815 STREAM_GETL(s
, ifindex
);
816 STREAM_GETL(s
, ra_interval
);
818 if (IS_ZEBRA_DEBUG_EVENT
)
819 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
820 zvrf_id(zvrf
), ifindex
,
821 enable
? "enable" : "disable",
822 zebra_route_string(client
->proto
), ra_interval
);
824 /* Locate interface and check VRF match. */
825 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
827 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
828 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
829 zebra_route_string(client
->proto
));
832 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
833 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
834 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
835 zebra_route_string(client
->proto
), ifp
->vrf_id
);
841 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
843 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
)
844 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
846 if (!zif
->rtadv
.configured
) {
847 zif
->rtadv
.MaxRtrAdvInterval
=
848 RTADV_MAX_RTR_ADV_INTERVAL
;
849 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
856 DEFUN (ipv6_nd_suppress_ra
,
857 ipv6_nd_suppress_ra_cmd
,
858 "ipv6 nd suppress-ra",
859 "Interface IPv6 config commands\n"
860 "Neighbor discovery\n"
861 "Suppress Router Advertisement\n")
863 VTY_DECLVAR_CONTEXT(interface
, ifp
);
864 struct zebra_if
*zif
= ifp
->info
;
866 if (if_is_loopback(ifp
)
867 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
869 "Cannot configure IPv6 Router Advertisements on this interface\n");
870 return CMD_WARNING_CONFIG_FAILED
;
873 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
874 zif
->rtadv
.configured
= 0;
878 DEFUN (no_ipv6_nd_suppress_ra
,
879 no_ipv6_nd_suppress_ra_cmd
,
880 "no ipv6 nd suppress-ra",
882 "Interface IPv6 config commands\n"
883 "Neighbor discovery\n"
884 "Suppress Router Advertisement\n")
886 VTY_DECLVAR_CONTEXT(interface
, ifp
);
887 struct zebra_if
*zif
= ifp
->info
;
889 if (if_is_loopback(ifp
)
890 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
892 "Cannot configure IPv6 Router Advertisements on this interface\n");
893 return CMD_WARNING_CONFIG_FAILED
;
896 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
897 zif
->rtadv
.configured
= 1;
901 DEFUN (ipv6_nd_ra_interval_msec
,
902 ipv6_nd_ra_interval_msec_cmd
,
903 "ipv6 nd ra-interval msec (70-1800000)",
904 "Interface IPv6 config commands\n"
905 "Neighbor discovery\n"
906 "Router Advertisement interval\n"
907 "Router Advertisement interval in milliseconds\n"
908 "Router Advertisement interval in milliseconds\n")
911 VTY_DECLVAR_CONTEXT(interface
, ifp
);
913 struct zebra_if
*zif
= ifp
->info
;
914 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
915 struct zebra_ns
*zns
;
918 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
919 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
920 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
922 "This ra-interval would conflict with configured ra-lifetime!\n");
923 return CMD_WARNING_CONFIG_FAILED
;
926 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
927 zns
->rtadv
.adv_msec_if_count
--;
930 zns
->rtadv
.adv_msec_if_count
++;
932 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
933 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
934 zif
->rtadv
.AdvIntervalTimer
= 0;
939 DEFUN (ipv6_nd_ra_interval
,
940 ipv6_nd_ra_interval_cmd
,
941 "ipv6 nd ra-interval (1-1800)",
942 "Interface IPv6 config commands\n"
943 "Neighbor discovery\n"
944 "Router Advertisement interval\n"
945 "Router Advertisement interval in seconds\n")
948 VTY_DECLVAR_CONTEXT(interface
, ifp
);
950 struct zebra_if
*zif
= ifp
->info
;
951 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
952 struct zebra_ns
*zns
;
955 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
956 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
957 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
959 "This ra-interval would conflict with configured ra-lifetime!\n");
960 return CMD_WARNING_CONFIG_FAILED
;
963 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
964 zns
->rtadv
.adv_msec_if_count
--;
966 /* convert to milliseconds */
967 interval
= interval
* 1000;
969 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
970 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
971 zif
->rtadv
.AdvIntervalTimer
= 0;
976 DEFUN (no_ipv6_nd_ra_interval
,
977 no_ipv6_nd_ra_interval_cmd
,
978 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
980 "Interface IPv6 config commands\n"
981 "Neighbor discovery\n"
982 "Router Advertisement interval\n"
983 "Router Advertisement interval in seconds\n"
984 "Specify millisecond router advertisement interval\n"
985 "Router Advertisement interval in milliseconds\n")
987 VTY_DECLVAR_CONTEXT(interface
, ifp
);
988 struct zebra_if
*zif
= ifp
->info
;
989 struct zebra_vrf
*zvrf
;
990 struct zebra_ns
*zns
;
992 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
995 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
996 zns
->rtadv
.adv_msec_if_count
--;
998 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
999 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1000 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1005 DEFUN (ipv6_nd_ra_lifetime
,
1006 ipv6_nd_ra_lifetime_cmd
,
1007 "ipv6 nd ra-lifetime (0-9000)",
1008 "Interface IPv6 config commands\n"
1009 "Neighbor discovery\n"
1011 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1014 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1015 struct zebra_if
*zif
= ifp
->info
;
1018 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1020 /* The value to be placed in the Router Lifetime field
1021 * of Router Advertisements sent from the interface,
1022 * in seconds. MUST be either zero or between
1023 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1024 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1026 "This ra-lifetime would conflict with configured ra-interval\n");
1027 return CMD_WARNING_CONFIG_FAILED
;
1030 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1035 DEFUN (no_ipv6_nd_ra_lifetime
,
1036 no_ipv6_nd_ra_lifetime_cmd
,
1037 "no ipv6 nd ra-lifetime [(0-9000)]",
1039 "Interface IPv6 config commands\n"
1040 "Neighbor discovery\n"
1042 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1044 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1045 struct zebra_if
*zif
= ifp
->info
;
1047 zif
->rtadv
.AdvDefaultLifetime
= -1;
1052 DEFUN (ipv6_nd_reachable_time
,
1053 ipv6_nd_reachable_time_cmd
,
1054 "ipv6 nd reachable-time (1-3600000)",
1055 "Interface IPv6 config commands\n"
1056 "Neighbor discovery\n"
1058 "Reachable time in milliseconds\n")
1061 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1062 struct zebra_if
*zif
= ifp
->info
;
1063 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1067 DEFUN (no_ipv6_nd_reachable_time
,
1068 no_ipv6_nd_reachable_time_cmd
,
1069 "no ipv6 nd reachable-time [(1-3600000)]",
1071 "Interface IPv6 config commands\n"
1072 "Neighbor discovery\n"
1074 "Reachable time in milliseconds\n")
1076 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1077 struct zebra_if
*zif
= ifp
->info
;
1079 zif
->rtadv
.AdvReachableTime
= 0;
1084 DEFUN (ipv6_nd_homeagent_preference
,
1085 ipv6_nd_homeagent_preference_cmd
,
1086 "ipv6 nd home-agent-preference (0-65535)",
1087 "Interface IPv6 config commands\n"
1088 "Neighbor discovery\n"
1089 "Home Agent preference\n"
1090 "preference value (default is 0, least preferred)\n")
1093 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1094 struct zebra_if
*zif
= ifp
->info
;
1095 zif
->rtadv
.HomeAgentPreference
=
1096 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1100 DEFUN (no_ipv6_nd_homeagent_preference
,
1101 no_ipv6_nd_homeagent_preference_cmd
,
1102 "no ipv6 nd home-agent-preference [(0-65535)]",
1104 "Interface IPv6 config commands\n"
1105 "Neighbor discovery\n"
1106 "Home Agent preference\n"
1107 "preference value (default is 0, least preferred)\n")
1109 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1110 struct zebra_if
*zif
= ifp
->info
;
1112 zif
->rtadv
.HomeAgentPreference
= 0;
1117 DEFUN (ipv6_nd_homeagent_lifetime
,
1118 ipv6_nd_homeagent_lifetime_cmd
,
1119 "ipv6 nd home-agent-lifetime (0-65520)",
1120 "Interface IPv6 config commands\n"
1121 "Neighbor discovery\n"
1122 "Home Agent lifetime\n"
1123 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1126 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1127 struct zebra_if
*zif
= ifp
->info
;
1128 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1132 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1133 no_ipv6_nd_homeagent_lifetime_cmd
,
1134 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1136 "Interface IPv6 config commands\n"
1137 "Neighbor discovery\n"
1138 "Home Agent lifetime\n"
1139 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1141 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1142 struct zebra_if
*zif
= ifp
->info
;
1144 zif
->rtadv
.HomeAgentLifetime
= -1;
1149 DEFUN (ipv6_nd_managed_config_flag
,
1150 ipv6_nd_managed_config_flag_cmd
,
1151 "ipv6 nd managed-config-flag",
1152 "Interface IPv6 config commands\n"
1153 "Neighbor discovery\n"
1154 "Managed address configuration flag\n")
1156 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1157 struct zebra_if
*zif
= ifp
->info
;
1159 zif
->rtadv
.AdvManagedFlag
= 1;
1164 DEFUN (no_ipv6_nd_managed_config_flag
,
1165 no_ipv6_nd_managed_config_flag_cmd
,
1166 "no ipv6 nd managed-config-flag",
1168 "Interface IPv6 config commands\n"
1169 "Neighbor discovery\n"
1170 "Managed address configuration flag\n")
1172 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1173 struct zebra_if
*zif
= ifp
->info
;
1175 zif
->rtadv
.AdvManagedFlag
= 0;
1180 DEFUN (ipv6_nd_homeagent_config_flag
,
1181 ipv6_nd_homeagent_config_flag_cmd
,
1182 "ipv6 nd home-agent-config-flag",
1183 "Interface IPv6 config commands\n"
1184 "Neighbor discovery\n"
1185 "Home Agent configuration flag\n")
1187 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1188 struct zebra_if
*zif
= ifp
->info
;
1190 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1195 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1196 no_ipv6_nd_homeagent_config_flag_cmd
,
1197 "no ipv6 nd home-agent-config-flag",
1199 "Interface IPv6 config commands\n"
1200 "Neighbor discovery\n"
1201 "Home Agent configuration flag\n")
1203 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1204 struct zebra_if
*zif
= ifp
->info
;
1206 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1211 DEFUN (ipv6_nd_adv_interval_config_option
,
1212 ipv6_nd_adv_interval_config_option_cmd
,
1213 "ipv6 nd adv-interval-option",
1214 "Interface IPv6 config commands\n"
1215 "Neighbor discovery\n"
1216 "Advertisement Interval Option\n")
1218 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1219 struct zebra_if
*zif
= ifp
->info
;
1221 zif
->rtadv
.AdvIntervalOption
= 1;
1226 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1227 no_ipv6_nd_adv_interval_config_option_cmd
,
1228 "no ipv6 nd adv-interval-option",
1230 "Interface IPv6 config commands\n"
1231 "Neighbor discovery\n"
1232 "Advertisement Interval Option\n")
1234 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1235 struct zebra_if
*zif
= ifp
->info
;
1237 zif
->rtadv
.AdvIntervalOption
= 0;
1242 DEFUN (ipv6_nd_other_config_flag
,
1243 ipv6_nd_other_config_flag_cmd
,
1244 "ipv6 nd other-config-flag",
1245 "Interface IPv6 config commands\n"
1246 "Neighbor discovery\n"
1247 "Other statefull configuration flag\n")
1249 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1250 struct zebra_if
*zif
= ifp
->info
;
1252 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1257 DEFUN (no_ipv6_nd_other_config_flag
,
1258 no_ipv6_nd_other_config_flag_cmd
,
1259 "no ipv6 nd other-config-flag",
1261 "Interface IPv6 config commands\n"
1262 "Neighbor discovery\n"
1263 "Other statefull configuration flag\n")
1265 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1266 struct zebra_if
*zif
= ifp
->info
;
1268 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1273 DEFUN (ipv6_nd_prefix
,
1275 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1276 "Interface IPv6 config commands\n"
1277 "Neighbor discovery\n"
1278 "Prefix information\n"
1280 "Valid lifetime in seconds\n"
1281 "Infinite valid lifetime\n"
1282 "Preferred lifetime in seconds\n"
1283 "Infinite preferred lifetime\n"
1284 "Set Router Address flag\n"
1285 "Do not use prefix for onlink determination\n"
1286 "Do not use prefix for autoconfiguration\n"
1287 "Do not use prefix for autoconfiguration\n"
1288 "Do not use prefix for onlink determination\n")
1291 char *prefix
= argv
[3]->arg
;
1292 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1293 || strmatch(argv
[4]->text
, "infinite"));
1294 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1296 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1298 char *lifetime
= NULL
, *preflifetime
= NULL
;
1299 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1301 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1303 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1308 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1310 offlink
= (argc
> idx_routeropts
+ 1
1311 || strmatch(argv
[idx_routeropts
]->text
,
1313 noautoconf
= (argc
> idx_routeropts
+ 1
1314 || strmatch(argv
[idx_routeropts
]->text
,
1320 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1321 struct zebra_if
*zebra_if
= ifp
->info
;
1323 struct rtadv_prefix rp
;
1325 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1327 vty_out(vty
, "Malformed IPv6 prefix\n");
1328 return CMD_WARNING_CONFIG_FAILED
;
1330 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1331 rp
.AdvOnLinkFlag
= !offlink
;
1332 rp
.AdvAutonomousFlag
= !noautoconf
;
1333 rp
.AdvRouterAddressFlag
= routeraddr
;
1334 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1335 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1338 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1340 : strtoll(lifetime
, NULL
, 10);
1341 rp
.AdvPreferredLifetime
=
1342 strmatch(preflifetime
, "infinite")
1344 : strtoll(preflifetime
, NULL
, 10);
1345 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1346 vty_out(vty
, "Invalid preferred lifetime\n");
1347 return CMD_WARNING_CONFIG_FAILED
;
1351 rtadv_prefix_set(zebra_if
, &rp
);
1356 DEFUN (no_ipv6_nd_prefix
,
1357 no_ipv6_nd_prefix_cmd
,
1358 "no ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1360 "Interface IPv6 config commands\n"
1361 "Neighbor discovery\n"
1362 "Prefix information\n"
1364 "Valid lifetime in seconds\n"
1365 "Infinite valid lifetime\n"
1366 "Preferred lifetime in seconds\n"
1367 "Infinite preferred lifetime\n"
1368 "Set Router Address flag\n"
1369 "Do not use prefix for onlink determination\n"
1370 "Do not use prefix for autoconfiguration\n"
1371 "Do not use prefix for autoconfiguration\n"
1372 "Do not use prefix for onlink determination\n")
1374 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1375 struct zebra_if
*zebra_if
= ifp
->info
;
1377 struct rtadv_prefix rp
;
1378 char *prefix
= argv
[4]->arg
;
1380 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1382 vty_out(vty
, "Malformed IPv6 prefix\n");
1383 return CMD_WARNING_CONFIG_FAILED
;
1385 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1387 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1389 vty_out(vty
, "Non-existant IPv6 prefix\n");
1390 return CMD_WARNING_CONFIG_FAILED
;
1396 DEFUN (ipv6_nd_router_preference
,
1397 ipv6_nd_router_preference_cmd
,
1398 "ipv6 nd router-preference <high|medium|low>",
1399 "Interface IPv6 config commands\n"
1400 "Neighbor discovery\n"
1401 "Default router preference\n"
1402 "High default router preference\n"
1403 "Medium default router preference (default)\n"
1404 "Low default router preference\n")
1406 int idx_high_medium_low
= 3;
1407 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1408 struct zebra_if
*zif
= ifp
->info
;
1411 while (0 != rtadv_pref_strs
[i
]) {
1412 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1415 zif
->rtadv
.DefaultPreference
= i
;
1421 return CMD_ERR_NO_MATCH
;
1424 DEFUN (no_ipv6_nd_router_preference
,
1425 no_ipv6_nd_router_preference_cmd
,
1426 "no ipv6 nd router-preference [<high|medium|low>]",
1428 "Interface IPv6 config commands\n"
1429 "Neighbor discovery\n"
1430 "Default router preference\n"
1431 "High default router preference\n"
1432 "Medium default router preference (default)\n"
1433 "Low default router preference\n")
1435 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1436 struct zebra_if
*zif
= ifp
->info
;
1438 zif
->rtadv
.DefaultPreference
=
1439 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1446 "ipv6 nd mtu (1-65535)",
1447 "Interface IPv6 config commands\n"
1448 "Neighbor discovery\n"
1453 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1454 struct zebra_if
*zif
= ifp
->info
;
1455 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1459 DEFUN (no_ipv6_nd_mtu
,
1461 "no ipv6 nd mtu [(1-65535)]",
1463 "Interface IPv6 config commands\n"
1464 "Neighbor discovery\n"
1468 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1469 struct zebra_if
*zif
= ifp
->info
;
1470 zif
->rtadv
.AdvLinkMTU
= 0;
1474 /* Dump interface ND information to vty. */
1475 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1477 struct zebra_if
*zif
;
1478 struct rtadvconf
*rtadv
;
1481 zif
= (struct zebra_if
*)ifp
->info
;
1482 rtadv
= &zif
->rtadv
;
1484 if (rtadv
->AdvSendAdvertisements
) {
1486 " ND advertised reachable time is %d milliseconds\n",
1487 rtadv
->AdvReachableTime
);
1489 " ND advertised retransmit interval is %d milliseconds\n",
1490 rtadv
->AdvRetransTimer
);
1491 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1492 zif
->ra_sent
, zif
->ra_rcvd
);
1493 interval
= rtadv
->MaxRtrAdvInterval
;
1494 if (interval
% 1000)
1496 " ND router advertisements are sent every "
1497 "%d milliseconds\n",
1501 " ND router advertisements are sent every "
1504 if (rtadv
->AdvDefaultLifetime
!= -1)
1506 " ND router advertisements live for %d seconds\n",
1507 rtadv
->AdvDefaultLifetime
);
1510 " ND router advertisements lifetime tracks ra-interval\n");
1512 " ND router advertisement default router preference is "
1514 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1515 if (rtadv
->AdvManagedFlag
)
1517 " Hosts use DHCP to obtain routable addresses.\n");
1520 " Hosts use stateless autoconfig for addresses.\n");
1521 if (rtadv
->AdvHomeAgentFlag
) {
1523 " ND router advertisements with Home Agent flag bit set.\n");
1524 if (rtadv
->HomeAgentLifetime
!= -1)
1526 " Home Agent lifetime is %u seconds\n",
1527 rtadv
->HomeAgentLifetime
);
1530 " Home Agent lifetime tracks ra-lifetime\n");
1531 vty_out(vty
, " Home Agent preference is %u\n",
1532 rtadv
->HomeAgentPreference
);
1534 if (rtadv
->AdvIntervalOption
)
1536 " ND router advertisements with Adv. Interval option.\n");
1542 /* Write configuration about router advertisement. */
1543 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1545 struct zebra_if
*zif
;
1546 struct listnode
*node
;
1547 struct rtadv_prefix
*rprefix
;
1548 char buf
[PREFIX_STRLEN
];
1553 if (!(if_is_loopback(ifp
)
1554 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1555 if (zif
->rtadv
.AdvSendAdvertisements
)
1556 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1559 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1560 if (interval
% 1000)
1561 vty_out(vty
, " ipv6 nd ra-interval msec %d\n", interval
);
1562 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1563 vty_out(vty
, " ipv6 nd ra-interval %d\n", interval
/ 1000);
1565 if (zif
->rtadv
.AdvIntervalOption
)
1566 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1568 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1569 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1570 zif
->rtadv
.AdvDefaultLifetime
);
1572 if (zif
->rtadv
.HomeAgentPreference
)
1573 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1574 zif
->rtadv
.HomeAgentPreference
);
1576 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1577 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1578 zif
->rtadv
.HomeAgentLifetime
);
1580 if (zif
->rtadv
.AdvHomeAgentFlag
)
1581 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1583 if (zif
->rtadv
.AdvReachableTime
)
1584 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1585 zif
->rtadv
.AdvReachableTime
);
1587 if (zif
->rtadv
.AdvManagedFlag
)
1588 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1590 if (zif
->rtadv
.AdvOtherConfigFlag
)
1591 vty_out(vty
, " ipv6 nd other-config-flag\n");
1593 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1594 vty_out(vty
, " ipv6 nd router-preference %s\n",
1595 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1597 if (zif
->rtadv
.AdvLinkMTU
)
1598 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1600 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1601 vty_out(vty
, " ipv6 nd prefix %s",
1602 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1603 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1604 || (rprefix
->AdvPreferredLifetime
1605 != RTADV_PREFERRED_LIFETIME
)) {
1606 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1607 vty_out(vty
, " infinite");
1609 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1610 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1611 vty_out(vty
, " infinite");
1614 rprefix
->AdvPreferredLifetime
);
1616 if (!rprefix
->AdvOnLinkFlag
)
1617 vty_out(vty
, " off-link");
1618 if (!rprefix
->AdvAutonomousFlag
)
1619 vty_out(vty
, " no-autoconfig");
1620 if (rprefix
->AdvRouterAddressFlag
)
1621 vty_out(vty
, " router-address");
1628 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1630 struct rtadv
*rtadv
= &zns
->rtadv
;
1634 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1636 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1640 if (rtadv
->ra_timer
) {
1641 thread_cancel(rtadv
->ra_timer
);
1642 rtadv
->ra_timer
= NULL
;
1644 if (rtadv
->ra_read
) {
1645 thread_cancel(rtadv
->ra_read
);
1646 rtadv
->ra_read
= NULL
;
1650 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1653 case RTADV_TIMER_MSEC
:
1654 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1658 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1667 void rtadv_init(struct zebra_ns
*zns
)
1669 zns
->rtadv
.sock
= rtadv_make_socket();
1672 void rtadv_terminate(struct zebra_ns
*zns
)
1674 rtadv_event(zns
, RTADV_STOP
, 0);
1675 if (zns
->rtadv
.sock
>= 0) {
1676 close(zns
->rtadv
.sock
);
1677 zns
->rtadv
.sock
= -1;
1680 zns
->rtadv
.adv_if_count
= 0;
1681 zns
->rtadv
.adv_msec_if_count
= 0;
1684 void rtadv_cmd_init(void)
1686 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1687 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1689 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1690 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1691 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1692 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1693 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1694 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1695 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1696 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1697 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1698 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1699 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1700 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1701 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1702 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1703 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1704 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1705 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1706 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1707 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1708 install_element(INTERFACE_NODE
,
1709 &ipv6_nd_adv_interval_config_option_cmd
);
1710 install_element(INTERFACE_NODE
,
1711 &no_ipv6_nd_adv_interval_config_option_cmd
);
1712 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1713 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1714 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1715 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1716 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1717 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1720 static int if_join_all_router(int sock
, struct interface
*ifp
)
1724 struct ipv6_mreq mreq
;
1726 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1727 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1728 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1730 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1733 zlog_warn("%s(%u): Failed to join group, socket %u error %s",
1734 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1736 if (IS_ZEBRA_DEBUG_EVENT
)
1738 "%s(%u): Join All-Routers multicast group, socket %u",
1739 ifp
->name
, ifp
->ifindex
, sock
);
1744 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1748 struct ipv6_mreq mreq
;
1750 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1751 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1752 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1754 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1757 zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
1758 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1760 if (IS_ZEBRA_DEBUG_EVENT
)
1762 "%s(%u): Leave All-Routers multicast group, socket %u",
1763 ifp
->name
, ifp
->ifindex
, sock
);
1769 void rtadv_init(struct zebra_ns
*zns
)
1773 void rtadv_terminate(struct zebra_ns
*zns
)
1777 void rtadv_cmd_init(void)
1781 #endif /* HAVE_RTADV */