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
37 #include "lib_errors.h"
39 #include "zebra/interface.h"
40 #include "zebra/rtadv.h"
41 #include "zebra/debug.h"
42 #include "zebra/rib.h"
43 #include "zebra/zapi_msg.h"
44 #include "zebra/zebra_vrf.h"
45 #include "zebra/zebra_errors.h"
46 #include "zebra/zebra_router.h"
48 extern struct zebra_privs_t zserv_privs
;
50 static uint32_t interfaces_configured_for_ra_from_bgp
;
52 #if defined(HAVE_RTADV)
54 #ifndef VTYSH_EXTRACT_PL
55 #include "zebra/rtadv_clippy.c"
58 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_PREFIX
, "Router Advertisement Prefix");
59 DEFINE_MTYPE_STATIC(ZEBRA
, ADV_IF
, "Advertised Interface");
62 #include <netinet/icmp6.h>
65 /* If RFC2133 definition is used. */
66 #ifndef IPV6_JOIN_GROUP
67 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
69 #ifndef IPV6_LEAVE_GROUP
70 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
73 #define ALLNODE "ff02::1"
74 #define ALLROUTER "ff02::2"
78 char name
[INTERFACE_NAMSIZ
];
79 struct adv_if_list_item list_item
;
82 static int adv_if_cmp(const struct adv_if
*a
, const struct adv_if
*b
)
84 return if_cmp_name_func(a
->name
, b
->name
);
87 DECLARE_SORTLIST_UNIQ(adv_if_list
, struct adv_if
, list_item
, adv_if_cmp
);
89 static int rtadv_prefix_cmp(const struct rtadv_prefix
*a
,
90 const struct rtadv_prefix
*b
)
92 return prefix_cmp(&a
->prefix
, &b
->prefix
);
95 DECLARE_RBTREE_UNIQ(rtadv_prefixes
, struct rtadv_prefix
, item
,
98 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS");
99 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL");
101 /* Order is intentional. Matches RFC4191. This array is also used for
102 command matching, so only modify with care. */
103 static const char *const rtadv_pref_strs
[] = {
104 "medium", "high", "INVALID", "low", 0
115 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
117 static int if_join_all_router(int, struct interface
*);
118 static int if_leave_all_router(int, struct interface
*);
120 static struct zebra_vrf
*rtadv_interface_get_zvrf(const struct interface
*ifp
)
122 /* We use the default vrf for rtadv handling except in netns */
123 if (!vrf_is_backend_netns())
124 return vrf_info_lookup(VRF_DEFAULT
);
126 return ifp
->vrf
->info
;
129 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
132 struct interface
*iface
;
133 struct zebra_if
*zif
;
135 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
136 if (iface
&& iface
->info
) {
144 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
145 int buflen
, struct sockaddr_in6
*from
,
146 ifindex_t
*ifindex
, int *hoplimit
)
151 struct cmsghdr
*cmsgptr
;
156 /* Fill in message and iovec. */
157 memset(&msg
, 0, sizeof(msg
));
158 msg
.msg_name
= (void *)from
;
159 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
162 msg
.msg_control
= (void *)adata
;
163 msg
.msg_controllen
= sizeof(adata
);
165 iov
.iov_len
= buflen
;
167 /* If recvmsg fail return minus value. */
168 ret
= recvmsg(sock
, &msg
, 0);
172 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
173 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
174 /* I want interface index which this packet comes from. */
175 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
176 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
177 struct in6_pktinfo
*ptr
;
179 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
180 *ifindex
= ptr
->ipi6_ifindex
;
181 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
184 /* Incoming packet's hop limit. */
185 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
186 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
187 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
192 rtadv_increment_received(zvrf
, ifindex
);
196 #define RTADV_MSG_SIZE 4096
198 /* Send router advertisement packet. */
199 static void rtadv_send_packet(int sock
, struct interface
*ifp
,
200 enum ipv6_nd_suppress_ra_status stop
)
204 struct cmsghdr
*cmsgptr
;
205 struct in6_pktinfo
*pkt
;
206 struct sockaddr_in6 addr
;
207 static void *adata
= NULL
;
208 unsigned char buf
[RTADV_MSG_SIZE
];
209 struct nd_router_advert
*rtadv
;
212 struct zebra_if
*zif
;
213 struct rtadv_prefix
*rprefix
;
214 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
215 0, 0, 0, 0, 0, 0, 0, 1};
216 struct listnode
*node
;
217 uint16_t pkt_RouterLifetime
;
220 * Allocate control message bufffer. This is dynamic because
221 * CMSG_SPACE is not guaranteed not to call a function. Note that
222 * the size will be different on different architectures due to
223 * differing alignment rules.
226 /* XXX Free on shutdown. */
227 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
230 zlog_debug("%s: can't malloc control data", __func__
);
235 /* Logging of packet. */
236 if (IS_ZEBRA_DEBUG_PACKET
)
237 zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp
->name
,
238 ifp
->vrf
->name
, ifp
->ifindex
, sock
);
240 /* Fill in sockaddr_in6. */
241 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
242 addr
.sin6_family
= AF_INET6
;
244 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
245 #endif /* SIN6_LEN */
246 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
247 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
249 /* Fetch interface information. */
252 /* Make router advertisement message. */
253 rtadv
= (struct nd_router_advert
*)buf
;
255 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
256 rtadv
->nd_ra_code
= 0;
257 rtadv
->nd_ra_cksum
= 0;
259 rtadv
->nd_ra_curhoplimit
= zif
->rtadv
.AdvCurHopLimit
;
261 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
262 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
264 : zif
->rtadv
.DefaultPreference
;
265 rtadv
->nd_ra_flags_reserved
<<= 3;
267 if (zif
->rtadv
.AdvManagedFlag
)
268 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
269 if (zif
->rtadv
.AdvOtherConfigFlag
)
270 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
271 if (zif
->rtadv
.AdvHomeAgentFlag
)
272 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
273 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
274 * AdvDefaultLifetime is by default based on the value of
275 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
276 * field of Router Advertisements. Given that this field is expressed
277 * in seconds, a small MaxRtrAdvInterval value can result in a zero
278 * value for this field. To prevent this, routers SHOULD keep
279 * AdvDefaultLifetime in at least one second, even if the use of
280 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
282 zif
->rtadv
.AdvDefaultLifetime
!= -1
283 ? zif
->rtadv
.AdvDefaultLifetime
284 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
286 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
287 rtadv
->nd_ra_router_lifetime
=
288 (stop
== RA_SUPPRESS
) ? htons(0) : htons(pkt_RouterLifetime
);
289 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
290 rtadv
->nd_ra_retransmit
= htonl(zif
->rtadv
.AdvRetransTimer
);
292 len
= sizeof(struct nd_router_advert
);
294 /* If both the Home Agent Preference and Home Agent Lifetime are set to
295 * their default values specified above, this option SHOULD NOT be
296 * included in the Router Advertisement messages sent by this home
297 * agent. -- RFC6275, 7.4 */
298 if (zif
->rtadv
.AdvHomeAgentFlag
299 && (zif
->rtadv
.HomeAgentPreference
300 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
301 struct nd_opt_homeagent_info
*ndopt_hai
=
302 (struct nd_opt_homeagent_info
*)(buf
+ len
);
303 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
304 ndopt_hai
->nd_opt_hai_len
= 1;
305 ndopt_hai
->nd_opt_hai_reserved
= 0;
306 ndopt_hai
->nd_opt_hai_preference
=
307 htons(zif
->rtadv
.HomeAgentPreference
);
308 /* 16-bit unsigned integer. The lifetime associated with the
310 * agent in units of seconds. The default value is the same as
312 * Router Lifetime, as specified in the main body of the Router
313 * Advertisement. The maximum value corresponds to 18.2 hours.
315 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
316 ndopt_hai
->nd_opt_hai_lifetime
=
317 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
318 ? zif
->rtadv
.HomeAgentLifetime
319 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
324 len
+= sizeof(struct nd_opt_homeagent_info
);
327 if (zif
->rtadv
.AdvIntervalOption
) {
328 struct nd_opt_adv_interval
*ndopt_adv
=
329 (struct nd_opt_adv_interval
*)(buf
+ len
);
330 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
331 ndopt_adv
->nd_opt_ai_len
= 1;
332 ndopt_adv
->nd_opt_ai_reserved
= 0;
333 ndopt_adv
->nd_opt_ai_interval
=
334 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
335 len
+= sizeof(struct nd_opt_adv_interval
);
338 /* Fill in prefix. */
339 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
340 struct nd_opt_prefix_info
*pinfo
;
342 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
344 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
345 pinfo
->nd_opt_pi_len
= 4;
346 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
348 pinfo
->nd_opt_pi_flags_reserved
= 0;
349 if (rprefix
->AdvOnLinkFlag
)
350 pinfo
->nd_opt_pi_flags_reserved
|=
351 ND_OPT_PI_FLAG_ONLINK
;
352 if (rprefix
->AdvAutonomousFlag
)
353 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
354 if (rprefix
->AdvRouterAddressFlag
)
355 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
357 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
358 pinfo
->nd_opt_pi_preferred_time
=
359 htonl(rprefix
->AdvPreferredLifetime
);
360 pinfo
->nd_opt_pi_reserved2
= 0;
362 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
363 &rprefix
->prefix
.prefix
);
365 len
+= sizeof(struct nd_opt_prefix_info
);
368 /* Hardware address. */
369 if (ifp
->hw_addr_len
!= 0) {
370 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
372 /* Option length should be rounded up to next octet if
373 the link address does not end on an octet boundary. */
374 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
376 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
377 len
+= ifp
->hw_addr_len
;
379 /* Pad option to end on an octet boundary. */
380 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
381 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
385 if (zif
->rtadv
.AdvLinkMTU
) {
386 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
387 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
388 opt
->nd_opt_mtu_len
= 1;
389 opt
->nd_opt_mtu_reserved
= 0;
390 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
391 len
+= sizeof(struct nd_opt_mtu
);
395 * There is no limit on the number of configurable recursive DNS
396 * servers or search list entries. We don't want the RA message
397 * to exceed the link's MTU (risking fragmentation) or even
398 * blow the stack buffer allocated for it.
400 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
402 /* Recursive DNS servers */
403 struct rtadv_rdnss
*rdnss
;
405 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
407 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
409 if (len
+ opt_len
> max_len
) {
411 "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
412 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
);
415 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
417 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
418 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
419 opt
->nd_opt_rdnss_reserved
= 0;
420 opt
->nd_opt_rdnss_lifetime
= htonl(
423 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
425 len
+= sizeof(struct nd_opt_rdnss
);
427 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
428 len
+= sizeof(struct in6_addr
);
431 /* DNS search list */
432 struct rtadv_dnssl
*dnssl
;
434 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
435 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
436 + ((dnssl
->encoded_len
+ 7) & ~7);
438 if (len
+ opt_len
> max_len
) {
440 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
441 ifp
->name
, ifp
->ifindex
);
444 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
446 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
447 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
448 opt
->nd_opt_dnssl_reserved
= 0;
449 opt
->nd_opt_dnssl_lifetime
= htonl(
452 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
454 len
+= sizeof(struct nd_opt_dnssl
);
456 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
457 len
+= dnssl
->encoded_len
;
459 /* Zero-pad to 8-octet boundary */
466 msg
.msg_name
= (void *)&addr
;
467 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
470 msg
.msg_control
= (void *)adata
;
471 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
476 cmsgptr
= CMSG_FIRSTHDR(&msg
);
477 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
478 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
479 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
481 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
482 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
483 pkt
->ipi6_ifindex
= ifp
->ifindex
;
485 ret
= sendmsg(sock
, &msg
, 0);
487 flog_err_sys(EC_LIB_SOCKET
,
488 "%s(%u): Tx RA failed, socket %u error %d (%s)",
489 ifp
->name
, ifp
->ifindex
, sock
, errno
,
490 safe_strerror(errno
));
495 static void rtadv_timer(struct thread
*thread
)
497 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
499 struct interface
*ifp
;
500 struct zebra_if
*zif
;
503 zvrf
->rtadv
.ra_timer
= NULL
;
504 if (adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
) == 0) {
505 period
= 1000; /* 1 s */
506 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
508 period
= 10; /* 10 ms */
509 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
512 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
513 FOR_ALL_INTERFACES (vrf
, ifp
) {
514 if (if_is_loopback(ifp
) || !if_is_operative(ifp
) ||
515 IS_ZEBRA_IF_BRIDGE_SLAVE(ifp
) ||
516 !connected_get_linklocal(ifp
) ||
517 (vrf_is_backend_netns() &&
518 ifp
->vrf
->vrf_id
!= zvrf
->vrf
->vrf_id
))
523 if (zif
->rtadv
.AdvSendAdvertisements
) {
524 if (zif
->rtadv
.inFastRexmit
525 && zif
->rtadv
.UseFastRexmit
) {
526 /* We assume we fast rexmit every sec so
529 if (--zif
->rtadv
.NumFastReXmitsRemain
531 zif
->rtadv
.inFastRexmit
= 0;
533 if (IS_ZEBRA_DEBUG_SEND
)
535 "Fast RA Rexmit on interface %s(%s:%u)",
540 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
,
543 zif
->rtadv
.AdvIntervalTimer
-= period
;
544 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
546 MaxRtrAdvInterval each
547 time isn't what section
548 6.2.4 of RFC4861 tells to do.
550 zif
->rtadv
.AdvIntervalTimer
=
554 zvrf
->rtadv
.sock
, ifp
,
562 static void rtadv_process_solicit(struct interface
*ifp
)
564 struct zebra_vrf
*zvrf
;
565 struct zebra_if
*zif
;
567 zvrf
= rtadv_interface_get_zvrf(ifp
);
572 * If FastRetransmit is enabled, send the RA immediately.
573 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
574 * (3 seconds) since the last RA was sent, send it now and reset
575 * the timer to start at the max (configured) again.
576 * If not enabled and it is less than 3 seconds since the last
577 * RA packet was sent, set the timer for 3 seconds so the next
578 * one will be sent with a minimum of 3 seconds between RAs.
581 if ((zif
->rtadv
.UseFastRexmit
)
582 || (zif
->rtadv
.AdvIntervalTimer
<=
583 (zif
->rtadv
.MaxRtrAdvInterval
- MIN_DELAY_BETWEEN_RAS
))) {
584 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_ENABLE
);
585 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
587 zif
->rtadv
.AdvIntervalTimer
= MIN_DELAY_BETWEEN_RAS
;
591 * This function processes optional attributes off of
592 * end of a RA packet received. At this point in
593 * time we only care about this in one situation
594 * which is when a interface does not have a LL
595 * v6 address. We still need to be able to install
596 * the mac address for v4 to v6 resolution
598 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
599 struct interface
*ifp
,
600 struct sockaddr_in6
*addr
)
605 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
607 switch(opt_hdr
->nd_opt_type
) {
608 case ND_OPT_SOURCE_LINKADDR
:
609 mac
= (char *)(optional
+2);
610 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
611 &addr
->sin6_addr
, 1);
617 len
-= 8 * opt_hdr
->nd_opt_len
;
618 optional
+= 8 * opt_hdr
->nd_opt_len
;
622 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
623 struct interface
*ifp
,
624 struct sockaddr_in6
*addr
)
626 struct nd_router_advert
*radvert
;
627 char addr_str
[INET6_ADDRSTRLEN
];
628 struct zebra_if
*zif
;
633 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
635 if (len
< sizeof(struct nd_router_advert
)) {
636 if (IS_ZEBRA_DEBUG_PACKET
)
638 "%s(%s:%u): Rx RA with invalid length %d from %s",
639 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, len
,
644 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
645 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
646 len
- sizeof(struct nd_router_advert
),
648 if (IS_ZEBRA_DEBUG_PACKET
)
650 "%s(%s:%u): Rx RA with non-linklocal source address from %s",
651 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
,
656 radvert
= (struct nd_router_advert
*)msg
;
658 #define SIXHOUR2USEC (int64_t)6 * 60 * 60 * 1000000
660 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
) &&
661 (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
) &&
662 (monotime_since(&zif
->rtadv
.lastadvcurhoplimit
, NULL
) >
664 zif
->rtadv
.lastadvcurhoplimit
.tv_sec
== 0)) {
666 EC_ZEBRA_RA_PARAM_MISMATCH
,
667 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
668 ifp
->name
, ifp
->ifindex
, addr_str
);
669 monotime(&zif
->rtadv
.lastadvcurhoplimit
);
672 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
) &&
673 !zif
->rtadv
.AdvManagedFlag
&&
674 (monotime_since(&zif
->rtadv
.lastadvmanagedflag
, NULL
) >
676 zif
->rtadv
.lastadvmanagedflag
.tv_sec
== 0)) {
678 EC_ZEBRA_RA_PARAM_MISMATCH
,
679 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
680 ifp
->name
, ifp
->ifindex
, addr_str
);
681 monotime(&zif
->rtadv
.lastadvmanagedflag
);
684 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
) &&
685 !zif
->rtadv
.AdvOtherConfigFlag
&&
686 (monotime_since(&zif
->rtadv
.lastadvotherconfigflag
, NULL
) >
688 zif
->rtadv
.lastadvotherconfigflag
.tv_sec
== 0)) {
690 EC_ZEBRA_RA_PARAM_MISMATCH
,
691 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
692 ifp
->name
, ifp
->ifindex
, addr_str
);
693 monotime(&zif
->rtadv
.lastadvotherconfigflag
);
696 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
) &&
697 (ntohl(radvert
->nd_ra_reachable
) != zif
->rtadv
.AdvReachableTime
) &&
698 (monotime_since(&zif
->rtadv
.lastadvreachabletime
, NULL
) >
700 zif
->rtadv
.lastadvreachabletime
.tv_sec
== 0)) {
702 EC_ZEBRA_RA_PARAM_MISMATCH
,
703 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
704 ifp
->name
, ifp
->ifindex
, addr_str
);
705 monotime(&zif
->rtadv
.lastadvreachabletime
);
708 if ((ntohl(radvert
->nd_ra_retransmit
) !=
709 (unsigned int)zif
->rtadv
.AdvRetransTimer
) &&
710 (monotime_since(&zif
->rtadv
.lastadvretranstimer
, NULL
) >
712 zif
->rtadv
.lastadvretranstimer
.tv_sec
== 0)) {
714 EC_ZEBRA_RA_PARAM_MISMATCH
,
715 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
716 ifp
->name
, ifp
->ifindex
, addr_str
);
717 monotime(&zif
->rtadv
.lastadvretranstimer
);
720 /* Create entry for neighbor if not known. */
722 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
723 p
.prefixlen
= IPV6_MAX_BITLEN
;
725 if (!nbr_connected_check(ifp
, &p
))
726 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
730 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
731 ifindex_t ifindex
, int hoplimit
,
732 struct sockaddr_in6
*from
,
733 struct zebra_vrf
*zvrf
)
735 struct icmp6_hdr
*icmph
;
736 struct interface
*ifp
;
737 struct zebra_if
*zif
;
738 char addr_str
[INET6_ADDRSTRLEN
];
740 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
742 /* Interface search. */
743 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
745 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
746 "RA/RS received on unknown IF %u from %s", ifindex
,
751 if (IS_ZEBRA_DEBUG_PACKET
)
752 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp
->name
,
753 ifp
->vrf
->name
, ifp
->ifindex
, len
, addr_str
);
755 if (if_is_loopback(ifp
))
758 /* Check interface configuration. */
760 if (!zif
->rtadv
.AdvSendAdvertisements
)
763 /* ICMP message length check. */
764 if (len
< sizeof(struct icmp6_hdr
)) {
766 "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
767 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, len
);
771 icmph
= (struct icmp6_hdr
*)buf
;
773 /* ICMP message type check. */
774 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
775 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
776 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
777 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
,
782 /* Hoplimit check. */
783 if (hoplimit
>= 0 && hoplimit
!= 255) {
784 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
785 ifp
->vrf
->name
, ifp
->ifindex
, hoplimit
);
789 /* Check ICMP message type. */
790 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
791 rtadv_process_solicit(ifp
);
792 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
793 rtadv_process_advert(buf
, len
, ifp
, from
);
798 static void rtadv_read(struct thread
*thread
)
802 uint8_t buf
[RTADV_MSG_SIZE
];
803 struct sockaddr_in6 from
;
804 ifindex_t ifindex
= 0;
806 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
808 sock
= THREAD_FD(thread
);
809 zvrf
->rtadv
.ra_read
= NULL
;
811 /* Register myself. */
812 rtadv_event(zvrf
, RTADV_READ
, 0);
814 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
818 flog_err_sys(EC_LIB_SOCKET
,
819 "RA/RS recv failed, socket %u error %s", sock
,
820 safe_strerror(errno
));
824 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
827 static int rtadv_make_socket(ns_id_t ns_id
)
831 struct icmp6_filter filter
;
834 frr_with_privs(&zserv_privs
) {
836 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
838 * with privs might set errno too if it fails save
845 zlog_warn("RTADV socket for ns: %u failure to create: %s(%u)",
846 ns_id
, safe_strerror(error
), error
);
850 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
852 zlog_warn("RTADV failure to set Packet Information");
856 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
858 zlog_warn("RTADV failure to set multicast Loop detection");
862 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
864 zlog_warn("RTADV failure to set maximum unicast hops");
868 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
870 zlog_warn("RTADV failure to set maximum multicast hops");
874 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
876 zlog_warn("RTADV failure to set maximum incoming hop limit");
881 ICMP6_FILTER_SETBLOCKALL(&filter
);
882 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
883 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
885 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
886 sizeof(struct icmp6_filter
));
888 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
896 static struct adv_if
*adv_if_new(const char *name
)
900 new = XCALLOC(MTYPE_ADV_IF
, sizeof(struct adv_if
));
902 strlcpy(new->name
, name
, sizeof(new->name
));
907 static void adv_if_free(struct adv_if
*adv_if
)
909 XFREE(MTYPE_ADV_IF
, adv_if
);
912 static bool adv_if_is_empty_internal(const struct adv_if_list_head
*adv_if_head
)
914 return adv_if_list_count(adv_if_head
) ? false : true;
917 static struct adv_if
*adv_if_add_internal(struct adv_if_list_head
*adv_if_head
,
920 struct adv_if adv_if_lookup
= {};
921 struct adv_if
*adv_if
= NULL
;
923 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
924 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
929 adv_if
= adv_if_new(adv_if_lookup
.name
);
930 adv_if_list_add(adv_if_head
, adv_if
);
935 static struct adv_if
*adv_if_del_internal(struct adv_if_list_head
*adv_if_head
,
938 struct adv_if adv_if_lookup
= {};
939 struct adv_if
*adv_if
= NULL
;
941 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
942 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
947 adv_if_list_del(adv_if_head
, adv_if
);
952 static void adv_if_clean_internal(struct adv_if_list_head
*adv_if_head
)
954 struct adv_if
*node
= NULL
;
956 if (!adv_if_is_empty_internal(adv_if_head
)) {
957 frr_each_safe (adv_if_list
, adv_if_head
, node
) {
958 adv_if_list_del(adv_if_head
, node
);
963 adv_if_list_fini(adv_if_head
);
968 * Add to list. On Success, return NULL, otherwise return already existing
971 static struct adv_if
*adv_if_add(struct zebra_vrf
*zvrf
, const char *name
)
973 struct adv_if
*adv_if
= NULL
;
975 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_if
, name
);
980 if (IS_ZEBRA_DEBUG_EVENT
) {
981 struct vrf
*vrf
= zvrf
->vrf
;
983 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
984 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
985 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
992 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
995 static struct adv_if
*adv_if_del(struct zebra_vrf
*zvrf
, const char *name
)
997 struct adv_if
*adv_if
= NULL
;
999 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_if
, name
);
1004 if (IS_ZEBRA_DEBUG_EVENT
) {
1005 struct vrf
*vrf
= zvrf
->vrf
;
1007 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1008 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1009 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1016 * Add to list. On Success, return NULL, otherwise return already existing
1019 static struct adv_if
*adv_msec_if_add(struct zebra_vrf
*zvrf
, const char *name
)
1021 struct adv_if
*adv_if
= NULL
;
1023 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1028 if (IS_ZEBRA_DEBUG_EVENT
) {
1029 struct vrf
*vrf
= zvrf
->vrf
;
1031 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1032 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1033 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1040 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1043 static struct adv_if
*adv_msec_if_del(struct zebra_vrf
*zvrf
, const char *name
)
1045 struct adv_if
*adv_if
= NULL
;
1047 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1052 if (IS_ZEBRA_DEBUG_EVENT
) {
1053 struct vrf
*vrf
= zvrf
->vrf
;
1055 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1056 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1057 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1063 /* Clean adv_if list, called on vrf terminate */
1064 static void adv_if_clean(struct zebra_vrf
*zvrf
)
1066 if (IS_ZEBRA_DEBUG_EVENT
) {
1067 struct vrf
*vrf
= zvrf
->vrf
;
1069 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1070 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1071 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1074 adv_if_clean_internal(&zvrf
->rtadv
.adv_if
);
1077 /* Clean adv_msec_if list, called on vrf terminate */
1078 static void adv_msec_if_clean(struct zebra_vrf
*zvrf
)
1080 if (IS_ZEBRA_DEBUG_EVENT
) {
1081 struct vrf
*vrf
= zvrf
->vrf
;
1083 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1084 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1085 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1088 adv_if_clean_internal(&zvrf
->rtadv
.adv_msec_if
);
1091 static struct rtadv_prefix
*rtadv_prefix_new(void)
1093 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
1096 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
1098 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
1101 static struct rtadv_prefix
*rtadv_prefix_get(struct rtadv_prefixes_head
*list
,
1102 struct prefix_ipv6
*p
)
1104 struct rtadv_prefix
*rprefix
, ref
;
1108 rprefix
= rtadv_prefixes_find(list
, &ref
);
1112 rprefix
= rtadv_prefix_new();
1113 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
1114 rtadv_prefixes_add(list
, rprefix
);
1119 static void rtadv_prefix_set_defaults(struct rtadv_prefix
*rp
)
1121 rp
->AdvAutonomousFlag
= 1;
1122 rp
->AdvOnLinkFlag
= 1;
1123 rp
->AdvRouterAddressFlag
= 0;
1124 rp
->AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1125 rp
->AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1128 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1130 struct rtadv_prefix
*rprefix
;
1132 rprefix
= rtadv_prefix_get(zif
->rtadv
.prefixes
, &rp
->prefix
);
1135 * Set parameters based on where the prefix is created.
1136 * If auto-created based on kernel address addition, set the
1137 * default values. If created from a manual "ipv6 nd prefix"
1138 * command, take the parameters from the manual command. Note
1139 * that if the manual command exists, the default values will
1140 * not overwrite the manual values.
1142 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1143 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_AUTO
)
1144 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1146 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1148 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
1149 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
1150 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
1151 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
1152 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
1153 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1154 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
1155 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1157 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1158 rtadv_prefix_set_defaults(rprefix
);
1163 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1165 struct rtadv_prefix
*rprefix
;
1167 rprefix
= rtadv_prefixes_find(zif
->rtadv
.prefixes
, rp
);
1168 if (rprefix
!= NULL
) {
1171 * When deleting an address from the list, need to take care
1172 * it wasn't defined both automatically via kernel
1173 * address addition as well as manually by vtysh cli. If both,
1174 * we don't actually delete but may change the parameters
1175 * back to default if a manually defined entry is deleted.
1177 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1178 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1179 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1180 rtadv_prefix_set_defaults(rprefix
);
1183 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1184 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1185 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1190 rtadv_prefixes_del(zif
->rtadv
.prefixes
, rprefix
);
1191 rtadv_prefix_free(rprefix
);
1197 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
1198 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
1200 struct rtadv_prefix rp
;
1203 apply_mask_ipv6(&rp
.prefix
);
1204 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1205 rtadv_prefix_set(zif
, &rp
);
1208 /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
1209 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
1211 struct rtadv_prefix rp
;
1213 rp
.prefix
= *((struct prefix_ipv6
*)p
);
1214 apply_mask_ipv6(&rp
.prefix
);
1215 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1216 rtadv_prefix_reset(zif
, &rp
);
1219 static void rtadv_start_interface_events(struct zebra_vrf
*zvrf
,
1220 struct zebra_if
*zif
)
1222 struct adv_if
*adv_if
= NULL
;
1224 if (zif
->ifp
->ifindex
== IFINDEX_INTERNAL
) {
1225 if (IS_ZEBRA_DEBUG_EVENT
)
1227 "%s(%s) has not configured an ifindex yet, delaying until we have one",
1228 zif
->ifp
->name
, zvrf
->vrf
->name
);
1232 adv_if
= adv_if_add(zvrf
, zif
->ifp
->name
);
1234 return; /* Already added */
1236 if_join_all_router(zvrf
->rtadv
.sock
, zif
->ifp
);
1238 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 1)
1239 rtadv_event(zvrf
, RTADV_START
, 0);
1242 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
1243 enum ipv6_nd_suppress_ra_status status
)
1245 struct zebra_if
*zif
;
1246 struct zebra_vrf
*zvrf
;
1247 struct adv_if
*adv_if
= NULL
;
1251 zvrf
= rtadv_interface_get_zvrf(ifp
);
1253 if (status
== RA_SUPPRESS
) {
1254 /* RA is currently enabled */
1255 if (zif
->rtadv
.AdvSendAdvertisements
) {
1256 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1257 zif
->rtadv
.AdvSendAdvertisements
= 0;
1258 zif
->rtadv
.AdvIntervalTimer
= 0;
1260 adv_if
= adv_if_del(zvrf
, ifp
->name
);
1262 return; /* Nothing to delete */
1264 adv_if_free(adv_if
);
1266 if_leave_all_router(zvrf
->rtadv
.sock
, ifp
);
1268 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 0)
1269 rtadv_event(zvrf
, RTADV_STOP
, 0);
1272 if (!zif
->rtadv
.AdvSendAdvertisements
) {
1273 zif
->rtadv
.AdvSendAdvertisements
= 1;
1274 zif
->rtadv
.AdvIntervalTimer
= 0;
1275 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
1276 && zif
->rtadv
.UseFastRexmit
) {
1278 * Enable Fast RA only when RA interval is in
1279 * secs and Fast RA retransmit is enabled
1281 zif
->rtadv
.inFastRexmit
= 1;
1282 zif
->rtadv
.NumFastReXmitsRemain
=
1283 RTADV_NUM_FAST_REXMITS
;
1286 rtadv_start_interface_events(zvrf
, zif
);
1292 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1293 * Note that while the client could request RA on an interface on which the
1294 * operator has not enabled RA, RA won't be disabled upon client request
1295 * if the operator has explicitly enabled RA. The enable request can also
1296 * specify a RA interval (in seconds).
1298 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
1302 struct interface
*ifp
;
1303 struct zebra_if
*zif
;
1304 uint32_t ra_interval
;
1308 /* Get interface index and RA interval. */
1309 STREAM_GETL(s
, ifindex
);
1310 STREAM_GETL(s
, ra_interval
);
1312 if (IS_ZEBRA_DEBUG_EVENT
) {
1313 struct vrf
*vrf
= zvrf
->vrf
;
1315 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1316 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1317 enable
? "enable" : "disable",
1318 zebra_route_string(client
->proto
), ra_interval
);
1321 /* Locate interface and check VRF match. */
1322 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
1324 struct vrf
*vrf
= zvrf
->vrf
;
1326 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
1327 "%s:%u: IF %u RA %s client %s - interface unknown",
1328 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1329 enable
? "enable" : "disable",
1330 zebra_route_string(client
->proto
));
1333 if (vrf_is_backend_netns() && ifp
->vrf
->vrf_id
!= zvrf_id(zvrf
)) {
1335 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1336 ifp
->vrf
->name
, zvrf_id(zvrf
), ifindex
,
1337 enable
? "enable" : "disable",
1338 zebra_route_string(client
->proto
), ifp
->vrf
->vrf_id
);
1344 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1345 interfaces_configured_for_ra_from_bgp
++;
1347 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1348 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1350 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1351 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1352 VTY_RA_INTERVAL_CONFIGURED
))
1353 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1355 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1356 interfaces_configured_for_ra_from_bgp
--;
1358 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1359 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1360 VTY_RA_INTERVAL_CONFIGURED
))
1361 zif
->rtadv
.MaxRtrAdvInterval
=
1362 RTADV_MAX_RTR_ADV_INTERVAL
;
1363 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1364 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1371 * send router lifetime value of zero in RAs on this interface since we're
1372 * ceasing to advertise and want to let our neighbors know.
1373 * RFC 4861 secion 6.2.5
1375 void rtadv_stop_ra(struct interface
*ifp
)
1377 struct zebra_if
*zif
;
1378 struct zebra_vrf
*zvrf
;
1381 zvrf
= rtadv_interface_get_zvrf(ifp
);
1383 if (zif
->rtadv
.AdvSendAdvertisements
)
1384 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1388 * Send router lifetime value of zero in RAs on all interfaces since we're
1389 * ceasing to advertise globally and want to let all of our neighbors know
1390 * RFC 4861 secion 6.2.5
1392 * Delete all ipv6 global prefixes added to the router advertisement prefix
1393 * lists prior to ceasing.
1395 void rtadv_stop_ra_all(void)
1398 struct interface
*ifp
;
1399 struct zebra_if
*zif
;
1400 struct rtadv_prefix
*rprefix
;
1402 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1403 FOR_ALL_INTERFACES (vrf
, ifp
) {
1406 frr_each_safe (rtadv_prefixes
, zif
->rtadv
.prefixes
,
1408 rtadv_prefix_reset(zif
, rprefix
);
1414 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1416 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1418 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1420 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1423 static void show_zvrf_rtadv_adv_if_helper(struct vty
*vty
,
1424 struct adv_if_list_head
*adv_if_head
)
1426 struct adv_if
*node
= NULL
;
1428 if (!adv_if_is_empty_internal(adv_if_head
)) {
1429 frr_each (adv_if_list
, adv_if_head
, node
) {
1430 vty_out(vty
, " %s\n", node
->name
);
1437 static void show_zvrf_rtadv_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
)
1439 vty_out(vty
, "VRF: %s\n", zvrf_name(zvrf
));
1440 vty_out(vty
, " Interfaces:\n");
1441 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_if
);
1443 vty_out(vty
, " Interfaces(msec):\n");
1444 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_msec_if
);
1447 DEFPY(show_ipv6_nd_ra_if
, show_ipv6_nd_ra_if_cmd
,
1448 "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
1450 "Neighbor discovery\n"
1451 "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR
)
1453 struct zebra_vrf
*zvrf
= NULL
;
1455 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1457 "%% VRF subcommand only applicable for netns-based vrfs.\n");
1464 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1465 struct zebra_vrf
*zvrf
;
1471 show_zvrf_rtadv_helper(vty
, zvrf
);
1478 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1480 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1483 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1488 show_zvrf_rtadv_helper(vty
, zvrf
);
1493 DEFUN (ipv6_nd_ra_fast_retrans
,
1494 ipv6_nd_ra_fast_retrans_cmd
,
1495 "ipv6 nd ra-fast-retrans",
1496 "Interface IPv6 config commands\n"
1497 "Neighbor discovery\n"
1498 "Fast retransmit of RA packets\n")
1500 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1501 struct zebra_if
*zif
= ifp
->info
;
1503 if (if_is_loopback(ifp
)) {
1505 "Cannot configure IPv6 Router Advertisements on this interface\n");
1506 return CMD_WARNING_CONFIG_FAILED
;
1509 zif
->rtadv
.UseFastRexmit
= true;
1514 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1515 no_ipv6_nd_ra_fast_retrans_cmd
,
1516 "no ipv6 nd ra-fast-retrans",
1518 "Interface IPv6 config commands\n"
1519 "Neighbor discovery\n"
1520 "Fast retransmit of RA packets\n")
1522 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1523 struct zebra_if
*zif
= ifp
->info
;
1525 if (if_is_loopback(ifp
)) {
1527 "Cannot configure IPv6 Router Advertisements on this interface\n");
1528 return CMD_WARNING_CONFIG_FAILED
;
1531 zif
->rtadv
.UseFastRexmit
= false;
1536 DEFPY (ipv6_nd_ra_hop_limit
,
1537 ipv6_nd_ra_hop_limit_cmd
,
1538 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1539 "Interface IPv6 config commands\n"
1540 "Neighbor discovery\n"
1541 "Advertisement Hop Limit\n"
1542 "Advertisement Hop Limit in hops (default:64)\n")
1544 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1545 struct zebra_if
*zif
= ifp
->info
;
1547 if (if_is_loopback(ifp
)) {
1549 "Cannot configure IPv6 Router Advertisements on this interface\n");
1550 return CMD_WARNING_CONFIG_FAILED
;
1553 zif
->rtadv
.AdvCurHopLimit
= hopcount
;
1558 DEFPY (no_ipv6_nd_ra_hop_limit
,
1559 no_ipv6_nd_ra_hop_limit_cmd
,
1560 "no ipv6 nd ra-hop-limit [(0-255)]",
1562 "Interface IPv6 config commands\n"
1563 "Neighbor discovery\n"
1564 "Advertisement Hop Limit\n"
1565 "Advertisement Hop Limit in hops\n")
1567 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1568 struct zebra_if
*zif
= ifp
->info
;
1570 if (if_is_loopback(ifp
)) {
1572 "Cannot configure IPv6 Router Advertisements on this interface\n");
1573 return CMD_WARNING_CONFIG_FAILED
;
1576 zif
->rtadv
.AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
1581 DEFPY (ipv6_nd_ra_retrans_interval
,
1582 ipv6_nd_ra_retrans_interval_cmd
,
1583 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1584 "Interface IPv6 config commands\n"
1585 "Neighbor discovery\n"
1586 "Advertisement Retransmit Interval\n"
1587 "Advertisement Retransmit Interval in msec\n")
1589 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1590 struct zebra_if
*zif
= ifp
->info
;
1592 if (if_is_loopback(ifp
)) {
1594 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1595 return CMD_WARNING_CONFIG_FAILED
;
1598 zif
->rtadv
.AdvRetransTimer
= interval
;
1603 DEFPY (no_ipv6_nd_ra_retrans_interval
,
1604 no_ipv6_nd_ra_retrans_interval_cmd
,
1605 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1607 "Interface IPv6 config commands\n"
1608 "Neighbor discovery\n"
1609 "Advertisement Retransmit Interval\n"
1610 "Advertisement Retransmit Interval in msec\n")
1612 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1613 struct zebra_if
*zif
= ifp
->info
;
1615 if (if_is_loopback(ifp
)) {
1617 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1618 return CMD_WARNING_CONFIG_FAILED
;
1621 zif
->rtadv
.AdvRetransTimer
= 0;
1626 DEFUN (ipv6_nd_suppress_ra
,
1627 ipv6_nd_suppress_ra_cmd
,
1628 "ipv6 nd suppress-ra",
1629 "Interface IPv6 config commands\n"
1630 "Neighbor discovery\n"
1631 "Suppress Router Advertisement\n")
1633 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1634 struct zebra_if
*zif
= ifp
->info
;
1636 if (if_is_loopback(ifp
)) {
1638 "Cannot configure IPv6 Router Advertisements on this interface\n");
1639 return CMD_WARNING_CONFIG_FAILED
;
1642 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1643 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1645 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1649 DEFUN (no_ipv6_nd_suppress_ra
,
1650 no_ipv6_nd_suppress_ra_cmd
,
1651 "no ipv6 nd suppress-ra",
1653 "Interface IPv6 config commands\n"
1654 "Neighbor discovery\n"
1655 "Suppress Router Advertisement\n")
1657 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1658 struct zebra_if
*zif
= ifp
->info
;
1660 if (if_is_loopback(ifp
)) {
1662 "Cannot configure IPv6 Router Advertisements on this interface\n");
1663 return CMD_WARNING_CONFIG_FAILED
;
1666 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1667 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1671 DEFUN (ipv6_nd_ra_interval_msec
,
1672 ipv6_nd_ra_interval_msec_cmd
,
1673 "ipv6 nd ra-interval msec (70-1800000)",
1674 "Interface IPv6 config commands\n"
1675 "Neighbor discovery\n"
1676 "Router Advertisement interval\n"
1677 "Router Advertisement interval in milliseconds\n"
1678 "Router Advertisement interval in milliseconds\n")
1681 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1683 struct zebra_if
*zif
= ifp
->info
;
1684 struct zebra_vrf
*zvrf
;
1685 struct adv_if
*adv_if
;
1687 zvrf
= rtadv_interface_get_zvrf(ifp
);
1689 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1690 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1691 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1693 "This ra-interval would conflict with configured ra-lifetime!\n");
1694 return CMD_WARNING_CONFIG_FAILED
;
1697 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1698 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1700 adv_if_free(adv_if
);
1703 if (interval
% 1000)
1704 (void)adv_msec_if_add(zvrf
, ifp
->name
);
1706 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1707 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1708 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1709 zif
->rtadv
.AdvIntervalTimer
= 0;
1714 DEFUN (ipv6_nd_ra_interval
,
1715 ipv6_nd_ra_interval_cmd
,
1716 "ipv6 nd ra-interval (1-1800)",
1717 "Interface IPv6 config commands\n"
1718 "Neighbor discovery\n"
1719 "Router Advertisement interval\n"
1720 "Router Advertisement interval in seconds\n")
1723 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1725 struct zebra_if
*zif
= ifp
->info
;
1726 struct zebra_vrf
*zvrf
;
1727 struct adv_if
*adv_if
;
1729 zvrf
= rtadv_interface_get_zvrf(ifp
);
1731 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1732 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1733 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1735 "This ra-interval would conflict with configured ra-lifetime!\n");
1736 return CMD_WARNING_CONFIG_FAILED
;
1739 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1740 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1742 adv_if_free(adv_if
);
1745 /* convert to milliseconds */
1746 interval
= interval
* 1000;
1748 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1749 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1750 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1751 zif
->rtadv
.AdvIntervalTimer
= 0;
1756 DEFUN (no_ipv6_nd_ra_interval
,
1757 no_ipv6_nd_ra_interval_cmd
,
1758 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1760 "Interface IPv6 config commands\n"
1761 "Neighbor discovery\n"
1762 "Router Advertisement interval\n"
1763 "Router Advertisement interval in seconds\n"
1764 "Specify millisecond router advertisement interval\n"
1765 "Router Advertisement interval in milliseconds\n")
1767 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1768 struct zebra_if
*zif
= ifp
->info
;
1769 struct zebra_vrf
*zvrf
= NULL
;
1770 struct adv_if
*adv_if
;
1772 zvrf
= rtadv_interface_get_zvrf(ifp
);
1774 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1775 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1777 adv_if_free(adv_if
);
1780 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1782 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1783 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1785 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1787 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1788 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1793 DEFUN (ipv6_nd_ra_lifetime
,
1794 ipv6_nd_ra_lifetime_cmd
,
1795 "ipv6 nd ra-lifetime (0-9000)",
1796 "Interface IPv6 config commands\n"
1797 "Neighbor discovery\n"
1799 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1802 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1803 struct zebra_if
*zif
= ifp
->info
;
1806 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1808 /* The value to be placed in the Router Lifetime field
1809 * of Router Advertisements sent from the interface,
1810 * in seconds. MUST be either zero or between
1811 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1812 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1814 "This ra-lifetime would conflict with configured ra-interval\n");
1815 return CMD_WARNING_CONFIG_FAILED
;
1818 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1823 DEFUN (no_ipv6_nd_ra_lifetime
,
1824 no_ipv6_nd_ra_lifetime_cmd
,
1825 "no ipv6 nd ra-lifetime [(0-9000)]",
1827 "Interface IPv6 config commands\n"
1828 "Neighbor discovery\n"
1830 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1832 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1833 struct zebra_if
*zif
= ifp
->info
;
1835 zif
->rtadv
.AdvDefaultLifetime
= -1;
1840 DEFUN (ipv6_nd_reachable_time
,
1841 ipv6_nd_reachable_time_cmd
,
1842 "ipv6 nd reachable-time (1-3600000)",
1843 "Interface IPv6 config commands\n"
1844 "Neighbor discovery\n"
1846 "Reachable time in milliseconds\n")
1849 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1850 struct zebra_if
*zif
= ifp
->info
;
1851 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1855 DEFUN (no_ipv6_nd_reachable_time
,
1856 no_ipv6_nd_reachable_time_cmd
,
1857 "no ipv6 nd reachable-time [(1-3600000)]",
1859 "Interface IPv6 config commands\n"
1860 "Neighbor discovery\n"
1862 "Reachable time in milliseconds\n")
1864 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1865 struct zebra_if
*zif
= ifp
->info
;
1867 zif
->rtadv
.AdvReachableTime
= 0;
1872 DEFUN (ipv6_nd_homeagent_preference
,
1873 ipv6_nd_homeagent_preference_cmd
,
1874 "ipv6 nd home-agent-preference (0-65535)",
1875 "Interface IPv6 config commands\n"
1876 "Neighbor discovery\n"
1877 "Home Agent preference\n"
1878 "preference value (default is 0, least preferred)\n")
1881 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1882 struct zebra_if
*zif
= ifp
->info
;
1883 zif
->rtadv
.HomeAgentPreference
=
1884 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1888 DEFUN (no_ipv6_nd_homeagent_preference
,
1889 no_ipv6_nd_homeagent_preference_cmd
,
1890 "no ipv6 nd home-agent-preference [(0-65535)]",
1892 "Interface IPv6 config commands\n"
1893 "Neighbor discovery\n"
1894 "Home Agent preference\n"
1895 "preference value (default is 0, least preferred)\n")
1897 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1898 struct zebra_if
*zif
= ifp
->info
;
1900 zif
->rtadv
.HomeAgentPreference
= 0;
1905 DEFUN (ipv6_nd_homeagent_lifetime
,
1906 ipv6_nd_homeagent_lifetime_cmd
,
1907 "ipv6 nd home-agent-lifetime (0-65520)",
1908 "Interface IPv6 config commands\n"
1909 "Neighbor discovery\n"
1910 "Home Agent lifetime\n"
1911 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1914 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1915 struct zebra_if
*zif
= ifp
->info
;
1916 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1920 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1921 no_ipv6_nd_homeagent_lifetime_cmd
,
1922 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1924 "Interface IPv6 config commands\n"
1925 "Neighbor discovery\n"
1926 "Home Agent lifetime\n"
1927 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1929 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1930 struct zebra_if
*zif
= ifp
->info
;
1932 zif
->rtadv
.HomeAgentLifetime
= -1;
1937 DEFUN (ipv6_nd_managed_config_flag
,
1938 ipv6_nd_managed_config_flag_cmd
,
1939 "ipv6 nd managed-config-flag",
1940 "Interface IPv6 config commands\n"
1941 "Neighbor discovery\n"
1942 "Managed address configuration flag\n")
1944 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1945 struct zebra_if
*zif
= ifp
->info
;
1947 zif
->rtadv
.AdvManagedFlag
= 1;
1952 DEFUN (no_ipv6_nd_managed_config_flag
,
1953 no_ipv6_nd_managed_config_flag_cmd
,
1954 "no ipv6 nd managed-config-flag",
1956 "Interface IPv6 config commands\n"
1957 "Neighbor discovery\n"
1958 "Managed address configuration flag\n")
1960 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1961 struct zebra_if
*zif
= ifp
->info
;
1963 zif
->rtadv
.AdvManagedFlag
= 0;
1968 DEFUN (ipv6_nd_homeagent_config_flag
,
1969 ipv6_nd_homeagent_config_flag_cmd
,
1970 "ipv6 nd home-agent-config-flag",
1971 "Interface IPv6 config commands\n"
1972 "Neighbor discovery\n"
1973 "Home Agent configuration flag\n")
1975 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1976 struct zebra_if
*zif
= ifp
->info
;
1978 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1983 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1984 no_ipv6_nd_homeagent_config_flag_cmd
,
1985 "no ipv6 nd home-agent-config-flag",
1987 "Interface IPv6 config commands\n"
1988 "Neighbor discovery\n"
1989 "Home Agent configuration flag\n")
1991 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1992 struct zebra_if
*zif
= ifp
->info
;
1994 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1999 DEFUN (ipv6_nd_adv_interval_config_option
,
2000 ipv6_nd_adv_interval_config_option_cmd
,
2001 "ipv6 nd adv-interval-option",
2002 "Interface IPv6 config commands\n"
2003 "Neighbor discovery\n"
2004 "Advertisement Interval Option\n")
2006 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2007 struct zebra_if
*zif
= ifp
->info
;
2009 zif
->rtadv
.AdvIntervalOption
= 1;
2014 DEFUN (no_ipv6_nd_adv_interval_config_option
,
2015 no_ipv6_nd_adv_interval_config_option_cmd
,
2016 "no ipv6 nd adv-interval-option",
2018 "Interface IPv6 config commands\n"
2019 "Neighbor discovery\n"
2020 "Advertisement Interval Option\n")
2022 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2023 struct zebra_if
*zif
= ifp
->info
;
2025 zif
->rtadv
.AdvIntervalOption
= 0;
2030 DEFUN (ipv6_nd_other_config_flag
,
2031 ipv6_nd_other_config_flag_cmd
,
2032 "ipv6 nd other-config-flag",
2033 "Interface IPv6 config commands\n"
2034 "Neighbor discovery\n"
2035 "Other statefull configuration flag\n")
2037 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2038 struct zebra_if
*zif
= ifp
->info
;
2040 zif
->rtadv
.AdvOtherConfigFlag
= 1;
2045 DEFUN (no_ipv6_nd_other_config_flag
,
2046 no_ipv6_nd_other_config_flag_cmd
,
2047 "no ipv6 nd other-config-flag",
2049 "Interface IPv6 config commands\n"
2050 "Neighbor discovery\n"
2051 "Other statefull configuration flag\n")
2053 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2054 struct zebra_if
*zif
= ifp
->info
;
2056 zif
->rtadv
.AdvOtherConfigFlag
= 0;
2061 DEFUN (ipv6_nd_prefix
,
2063 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2064 "Interface IPv6 config commands\n"
2065 "Neighbor discovery\n"
2066 "Prefix information\n"
2068 "Valid lifetime in seconds\n"
2069 "Infinite valid lifetime\n"
2070 "Preferred lifetime in seconds\n"
2071 "Infinite preferred lifetime\n"
2072 "Set Router Address flag\n"
2073 "Do not use prefix for onlink determination\n"
2074 "Do not use prefix for autoconfiguration\n"
2075 "Do not use prefix for autoconfiguration\n"
2076 "Do not use prefix for onlink determination\n")
2079 char *prefix
= argv
[3]->arg
;
2080 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
2081 || strmatch(argv
[4]->text
, "infinite"));
2082 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
2084 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
2086 char *lifetime
= NULL
, *preflifetime
= NULL
;
2087 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
2089 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2091 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
2096 strmatch(argv
[idx_routeropts
]->text
, "router-address");
2098 offlink
= (argc
> idx_routeropts
+ 1
2099 || strmatch(argv
[idx_routeropts
]->text
,
2101 noautoconf
= (argc
> idx_routeropts
+ 1
2102 || strmatch(argv
[idx_routeropts
]->text
,
2108 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2109 struct zebra_if
*zebra_if
= ifp
->info
;
2111 struct rtadv_prefix rp
;
2113 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2115 vty_out(vty
, "Malformed IPv6 prefix\n");
2116 return CMD_WARNING_CONFIG_FAILED
;
2118 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2119 rp
.AdvOnLinkFlag
= !offlink
;
2120 rp
.AdvAutonomousFlag
= !noautoconf
;
2121 rp
.AdvRouterAddressFlag
= routeraddr
;
2122 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
2123 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
2124 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2127 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
2129 : strtoll(lifetime
, NULL
, 10);
2130 rp
.AdvPreferredLifetime
=
2131 strmatch(preflifetime
, "infinite")
2133 : strtoll(preflifetime
, NULL
, 10);
2134 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
2135 vty_out(vty
, "Invalid preferred lifetime\n");
2136 return CMD_WARNING_CONFIG_FAILED
;
2140 rtadv_prefix_set(zebra_if
, &rp
);
2145 DEFUN (no_ipv6_nd_prefix
,
2146 no_ipv6_nd_prefix_cmd
,
2147 "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]>]",
2149 "Interface IPv6 config commands\n"
2150 "Neighbor discovery\n"
2151 "Prefix information\n"
2153 "Valid lifetime in seconds\n"
2154 "Infinite valid lifetime\n"
2155 "Preferred lifetime in seconds\n"
2156 "Infinite preferred lifetime\n"
2157 "Set Router Address flag\n"
2158 "Do not use prefix for onlink determination\n"
2159 "Do not use prefix for autoconfiguration\n"
2160 "Do not use prefix for autoconfiguration\n"
2161 "Do not use prefix for onlink determination\n")
2163 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2164 struct zebra_if
*zebra_if
= ifp
->info
;
2166 struct rtadv_prefix rp
;
2167 char *prefix
= argv
[4]->arg
;
2169 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2171 vty_out(vty
, "Malformed IPv6 prefix\n");
2172 return CMD_WARNING_CONFIG_FAILED
;
2174 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2175 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2177 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
2179 vty_out(vty
, "Non-existant IPv6 prefix\n");
2180 return CMD_WARNING_CONFIG_FAILED
;
2186 DEFUN (ipv6_nd_router_preference
,
2187 ipv6_nd_router_preference_cmd
,
2188 "ipv6 nd router-preference <high|medium|low>",
2189 "Interface IPv6 config commands\n"
2190 "Neighbor discovery\n"
2191 "Default router preference\n"
2192 "High default router preference\n"
2193 "Medium default router preference (default)\n"
2194 "Low default router preference\n")
2196 int idx_high_medium_low
= 3;
2197 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2198 struct zebra_if
*zif
= ifp
->info
;
2201 while (0 != rtadv_pref_strs
[i
]) {
2202 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
2205 zif
->rtadv
.DefaultPreference
= i
;
2211 return CMD_ERR_NO_MATCH
;
2214 DEFUN (no_ipv6_nd_router_preference
,
2215 no_ipv6_nd_router_preference_cmd
,
2216 "no ipv6 nd router-preference [<high|medium|low>]",
2218 "Interface IPv6 config commands\n"
2219 "Neighbor discovery\n"
2220 "Default router preference\n"
2221 "High default router preference\n"
2222 "Medium default router preference (default)\n"
2223 "Low default router preference\n")
2225 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2226 struct zebra_if
*zif
= ifp
->info
;
2228 zif
->rtadv
.DefaultPreference
=
2229 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
2236 "ipv6 nd mtu (1-65535)",
2237 "Interface IPv6 config commands\n"
2238 "Neighbor discovery\n"
2243 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2244 struct zebra_if
*zif
= ifp
->info
;
2245 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2249 DEFUN (no_ipv6_nd_mtu
,
2251 "no ipv6 nd mtu [(1-65535)]",
2253 "Interface IPv6 config commands\n"
2254 "Neighbor discovery\n"
2258 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2259 struct zebra_if
*zif
= ifp
->info
;
2260 zif
->rtadv
.AdvLinkMTU
= 0;
2264 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
2266 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
2269 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
2271 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
2274 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
2275 struct rtadv_rdnss
*rdnss
)
2277 struct listnode
*node
;
2278 struct rtadv_rdnss
*p
;
2280 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2281 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
2286 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
2287 struct rtadv_rdnss
*rdnss
)
2289 struct rtadv_rdnss
*p
;
2291 p
= rtadv_rdnss_lookup(list
, rdnss
);
2295 p
= rtadv_rdnss_new();
2296 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
2297 listnode_add(list
, p
);
2302 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2304 struct rtadv_rdnss
*p
;
2306 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2307 p
->lifetime
= rdnss
->lifetime
;
2308 p
->lifetime_set
= rdnss
->lifetime_set
;
2311 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2313 struct rtadv_rdnss
*p
;
2315 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2317 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
2318 rtadv_rdnss_free(p
);
2325 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
2327 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
2330 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
2332 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
2335 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
2336 struct rtadv_dnssl
*dnssl
)
2338 struct listnode
*node
;
2339 struct rtadv_dnssl
*p
;
2341 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2342 if (!strcasecmp(p
->name
, dnssl
->name
))
2347 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
2348 struct rtadv_dnssl
*dnssl
)
2350 struct rtadv_dnssl
*p
;
2352 p
= rtadv_dnssl_lookup(list
, dnssl
);
2356 p
= rtadv_dnssl_new();
2357 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2358 listnode_add(list
, p
);
2363 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2365 struct rtadv_dnssl
*p
;
2367 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2368 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2371 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2373 struct rtadv_dnssl
*p
;
2375 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2377 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
2378 rtadv_dnssl_free(p
);
2386 * Convert dotted domain name (with or without trailing root zone dot) to
2387 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2388 * to strlen(in) + 2 octets to out.
2390 * Returns the number of octets written to out or -1 if in does not constitute
2391 * a valid domain name.
2393 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
2395 const char *label_start
, *label_end
;
2401 while (*label_start
) {
2404 label_end
= strchr(label_start
, '.');
2405 if (label_end
== NULL
)
2406 label_end
= label_start
+ strlen(label_start
);
2408 label_len
= label_end
- label_start
;
2409 if (label_len
>= 64)
2410 return -1; /* labels must be 63 octets or less */
2412 out
[outp
++] = (uint8_t)label_len
;
2413 memcpy(out
+ outp
, label_start
, label_len
);
2415 label_start
+= label_len
;
2416 if (*label_start
== '.')
2424 DEFUN(ipv6_nd_rdnss
,
2426 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2427 "Interface IPv6 config commands\n"
2428 "Neighbor discovery\n"
2429 "Recursive DNS server information\n"
2431 "Valid lifetime in seconds\n"
2432 "Infinite valid lifetime\n")
2434 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2435 struct zebra_if
*zif
= ifp
->info
;
2436 struct rtadv_rdnss rdnss
= {};
2438 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
2439 vty_out(vty
, "Malformed IPv6 address\n");
2440 return CMD_WARNING_CONFIG_FAILED
;
2443 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2445 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
2447 : strtoll(lifetime
, NULL
, 10);
2448 rdnss
.lifetime_set
= 1;
2451 rtadv_rdnss_set(zif
, &rdnss
);
2456 DEFUN(no_ipv6_nd_rdnss
,
2457 no_ipv6_nd_rdnss_cmd
,
2458 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2460 "Interface IPv6 config commands\n"
2461 "Neighbor discovery\n"
2462 "Recursive DNS server information\n"
2464 "Valid lifetime in seconds\n"
2465 "Infinite valid lifetime\n")
2467 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2468 struct zebra_if
*zif
= ifp
->info
;
2469 struct rtadv_rdnss rdnss
= {};
2471 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
2472 vty_out(vty
, "Malformed IPv6 address\n");
2473 return CMD_WARNING_CONFIG_FAILED
;
2475 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
2476 vty_out(vty
, "Non-existant RDNSS address\n");
2477 return CMD_WARNING_CONFIG_FAILED
;
2483 DEFUN(ipv6_nd_dnssl
,
2485 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2486 "Interface IPv6 config commands\n"
2487 "Neighbor discovery\n"
2488 "DNS search list information\n"
2489 "Domain name suffix\n"
2490 "Valid lifetime in seconds\n"
2491 "Infinite valid lifetime\n")
2493 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2494 struct zebra_if
*zif
= ifp
->info
;
2495 struct rtadv_dnssl dnssl
= {};
2499 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
2500 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2501 vty_out(vty
, "Malformed DNS search domain\n");
2502 return CMD_WARNING_CONFIG_FAILED
;
2504 if (dnssl
.name
[len
- 1] == '.') {
2506 * Allow, but don't require, a trailing dot signifying the root
2507 * zone. Canonicalize by cutting it off if present.
2509 dnssl
.name
[len
- 1] = '\0';
2513 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2515 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
2517 : strtoll(lifetime
, NULL
, 10);
2518 dnssl
.lifetime_set
= 1;
2521 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2523 vty_out(vty
, "Malformed DNS search domain\n");
2524 return CMD_WARNING_CONFIG_FAILED
;
2526 dnssl
.encoded_len
= ret
;
2527 rtadv_dnssl_set(zif
, &dnssl
);
2532 DEFUN(no_ipv6_nd_dnssl
,
2533 no_ipv6_nd_dnssl_cmd
,
2534 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2536 "Interface IPv6 config commands\n"
2537 "Neighbor discovery\n"
2538 "DNS search list information\n"
2539 "Domain name suffix\n"
2540 "Valid lifetime in seconds\n"
2541 "Infinite valid lifetime\n")
2543 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2544 struct zebra_if
*zif
= ifp
->info
;
2545 struct rtadv_dnssl dnssl
= {};
2548 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2549 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2550 vty_out(vty
, "Malformed DNS search domain\n");
2551 return CMD_WARNING_CONFIG_FAILED
;
2553 if (dnssl
.name
[len
- 1] == '.') {
2554 dnssl
.name
[len
- 1] = '\0';
2557 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2558 vty_out(vty
, "Non-existant DNS search domain\n");
2559 return CMD_WARNING_CONFIG_FAILED
;
2566 /* Dump interface ND information to vty. */
2567 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2569 struct zebra_if
*zif
;
2570 struct rtadvconf
*rtadv
;
2573 zif
= (struct zebra_if
*)ifp
->info
;
2574 rtadv
= &zif
->rtadv
;
2576 if (rtadv
->AdvSendAdvertisements
) {
2578 " ND advertised reachable time is %d milliseconds\n",
2579 rtadv
->AdvReachableTime
);
2581 " ND advertised retransmit interval is %u milliseconds\n",
2582 rtadv
->AdvRetransTimer
);
2583 vty_out(vty
, " ND advertised hop-count limit is %d hops\n",
2584 rtadv
->AdvCurHopLimit
);
2585 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2586 zif
->ra_sent
, zif
->ra_rcvd
);
2587 interval
= rtadv
->MaxRtrAdvInterval
;
2588 if (interval
% 1000)
2590 " ND router advertisements are sent every %d milliseconds\n",
2594 " ND router advertisements are sent every %d seconds\n",
2596 if (!rtadv
->UseFastRexmit
)
2598 " ND router advertisements do not use fast retransmit\n");
2600 if (rtadv
->AdvDefaultLifetime
!= -1)
2602 " ND router advertisements live for %d seconds\n",
2603 rtadv
->AdvDefaultLifetime
);
2606 " ND router advertisements lifetime tracks ra-interval\n");
2608 " ND router advertisement default router preference is %s\n",
2609 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2610 if (rtadv
->AdvManagedFlag
)
2612 " Hosts use DHCP to obtain routable addresses.\n");
2615 " Hosts use stateless autoconfig for addresses.\n");
2616 if (rtadv
->AdvHomeAgentFlag
) {
2618 " ND router advertisements with Home Agent flag bit set.\n");
2619 if (rtadv
->HomeAgentLifetime
!= -1)
2621 " Home Agent lifetime is %u seconds\n",
2622 rtadv
->HomeAgentLifetime
);
2625 " Home Agent lifetime tracks ra-lifetime\n");
2626 vty_out(vty
, " Home Agent preference is %u\n",
2627 rtadv
->HomeAgentPreference
);
2629 if (rtadv
->AdvIntervalOption
)
2631 " ND router advertisements with Adv. Interval option.\n");
2637 /* Write configuration about router advertisement. */
2638 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2640 struct zebra_if
*zif
;
2641 struct listnode
*node
;
2642 struct rtadv_prefix
*rprefix
;
2643 struct rtadv_rdnss
*rdnss
;
2644 struct rtadv_dnssl
*dnssl
;
2649 if (!if_is_loopback(ifp
)) {
2650 if (zif
->rtadv
.AdvSendAdvertisements
2651 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2652 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2655 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2656 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2657 if (interval
% 1000)
2658 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2660 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2661 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2665 if (zif
->rtadv
.AdvIntervalOption
)
2666 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2668 if (!zif
->rtadv
.UseFastRexmit
)
2669 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2671 if (zif
->rtadv
.AdvRetransTimer
!= 0)
2672 vty_out(vty
, " ipv6 nd ra-retrans-interval %u\n",
2673 zif
->rtadv
.AdvRetransTimer
);
2675 if (zif
->rtadv
.AdvCurHopLimit
!= RTADV_DEFAULT_HOPLIMIT
)
2676 vty_out(vty
, " ipv6 nd ra-hop-limit %d\n",
2677 zif
->rtadv
.AdvCurHopLimit
);
2679 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2680 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2681 zif
->rtadv
.AdvDefaultLifetime
);
2683 if (zif
->rtadv
.HomeAgentPreference
)
2684 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2685 zif
->rtadv
.HomeAgentPreference
);
2687 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2688 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2689 zif
->rtadv
.HomeAgentLifetime
);
2691 if (zif
->rtadv
.AdvHomeAgentFlag
)
2692 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2694 if (zif
->rtadv
.AdvReachableTime
)
2695 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2696 zif
->rtadv
.AdvReachableTime
);
2698 if (zif
->rtadv
.AdvManagedFlag
)
2699 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2701 if (zif
->rtadv
.AdvOtherConfigFlag
)
2702 vty_out(vty
, " ipv6 nd other-config-flag\n");
2704 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2705 vty_out(vty
, " ipv6 nd router-preference %s\n",
2706 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2708 if (zif
->rtadv
.AdvLinkMTU
)
2709 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2711 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
2712 if ((rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
2713 || (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
)) {
2714 vty_out(vty
, " ipv6 nd prefix %pFX", &rprefix
->prefix
);
2715 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2716 || (rprefix
->AdvPreferredLifetime
2717 != RTADV_PREFERRED_LIFETIME
)) {
2718 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2719 vty_out(vty
, " infinite");
2722 rprefix
->AdvValidLifetime
);
2723 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2724 vty_out(vty
, " infinite");
2727 rprefix
->AdvPreferredLifetime
);
2729 if (!rprefix
->AdvOnLinkFlag
)
2730 vty_out(vty
, " off-link");
2731 if (!rprefix
->AdvAutonomousFlag
)
2732 vty_out(vty
, " no-autoconfig");
2733 if (rprefix
->AdvRouterAddressFlag
)
2734 vty_out(vty
, " router-address");
2739 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2740 char buf
[INET6_ADDRSTRLEN
];
2742 vty_out(vty
, " ipv6 nd rdnss %s",
2743 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2744 if (rdnss
->lifetime_set
) {
2745 if (rdnss
->lifetime
== UINT32_MAX
)
2746 vty_out(vty
, " infinite");
2748 vty_out(vty
, " %u", rdnss
->lifetime
);
2752 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2753 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2754 if (dnssl
->lifetime_set
) {
2755 if (dnssl
->lifetime
== UINT32_MAX
)
2756 vty_out(vty
, " infinite");
2758 vty_out(vty
, " %u", dnssl
->lifetime
);
2766 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2768 struct rtadv
*rtadv
;
2770 if (IS_ZEBRA_DEBUG_EVENT
) {
2771 struct vrf
*vrf
= zvrf
->vrf
;
2773 zlog_debug("%s(%s) with event: %d and val: %d", __func__
,
2774 VRF_LOGNAME(vrf
), event
, val
);
2777 rtadv
= &zvrf
->rtadv
;
2781 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2783 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2787 THREAD_OFF(rtadv
->ra_timer
);
2788 THREAD_OFF(rtadv
->ra_read
);
2791 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2794 case RTADV_TIMER_MSEC
:
2795 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2799 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2808 void rtadv_if_up(struct zebra_if
*zif
)
2810 struct zebra_vrf
*zvrf
= rtadv_interface_get_zvrf(zif
->ifp
);
2812 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
2813 if (zif
->rtadv
.AdvSendAdvertisements
&&
2814 (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) &&
2815 zif
->rtadv
.UseFastRexmit
) {
2816 zif
->rtadv
.inFastRexmit
= 1;
2817 zif
->rtadv
.NumFastReXmitsRemain
= RTADV_NUM_FAST_REXMITS
;
2821 * startup the state machine, if it hasn't been already
2822 * due to a delayed ifindex on startup ordering
2824 if (zif
->rtadv
.AdvSendAdvertisements
)
2825 rtadv_start_interface_events(zvrf
, zif
);
2828 void rtadv_if_init(struct zebra_if
*zif
)
2830 /* Set default router advertise values. */
2831 struct rtadvconf
*rtadv
;
2833 rtadv
= &zif
->rtadv
;
2835 rtadv
->AdvSendAdvertisements
= 0;
2836 rtadv
->MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
2837 rtadv
->MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
2838 rtadv
->AdvIntervalTimer
= 0;
2839 rtadv
->AdvManagedFlag
= 0;
2840 rtadv
->AdvOtherConfigFlag
= 0;
2841 rtadv
->AdvHomeAgentFlag
= 0;
2842 rtadv
->AdvLinkMTU
= 0;
2843 rtadv
->AdvReachableTime
= 0;
2844 rtadv
->AdvRetransTimer
= 0;
2845 rtadv
->AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
2846 memset(&rtadv
->lastadvcurhoplimit
, 0,
2847 sizeof(rtadv
->lastadvcurhoplimit
));
2848 memset(&rtadv
->lastadvmanagedflag
, 0,
2849 sizeof(rtadv
->lastadvmanagedflag
));
2850 memset(&rtadv
->lastadvotherconfigflag
, 0,
2851 sizeof(rtadv
->lastadvotherconfigflag
));
2852 memset(&rtadv
->lastadvreachabletime
, 0,
2853 sizeof(rtadv
->lastadvreachabletime
));
2854 memset(&rtadv
->lastadvretranstimer
, 0,
2855 sizeof(rtadv
->lastadvretranstimer
));
2856 rtadv
->AdvDefaultLifetime
= -1; /* derive from MaxRtrAdvInterval */
2857 rtadv
->HomeAgentPreference
= 0;
2858 rtadv
->HomeAgentLifetime
= -1; /* derive from AdvDefaultLifetime */
2859 rtadv
->AdvIntervalOption
= 0;
2860 rtadv
->UseFastRexmit
= true;
2861 rtadv
->DefaultPreference
= RTADV_PREF_MEDIUM
;
2863 rtadv_prefixes_init(rtadv
->prefixes
);
2865 rtadv
->AdvRDNSSList
= list_new();
2866 rtadv
->AdvDNSSLList
= list_new();
2869 void rtadv_if_fini(struct zebra_if
*zif
)
2871 struct rtadvconf
*rtadv
;
2872 struct rtadv_prefix
*rp
;
2874 rtadv
= &zif
->rtadv
;
2876 while ((rp
= rtadv_prefixes_pop(rtadv
->prefixes
)))
2877 rtadv_prefix_free(rp
);
2879 list_delete(&rtadv
->AdvRDNSSList
);
2880 list_delete(&rtadv
->AdvDNSSLList
);
2883 void rtadv_vrf_init(struct zebra_vrf
*zvrf
)
2885 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2888 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2891 void rtadv_vrf_terminate(struct zebra_vrf
*zvrf
)
2893 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2896 rtadv_event(zvrf
, RTADV_STOP
, 0);
2897 if (zvrf
->rtadv
.sock
>= 0) {
2898 close(zvrf
->rtadv
.sock
);
2899 zvrf
->rtadv
.sock
= -1;
2903 adv_msec_if_clean(zvrf
);
2906 void rtadv_cmd_init(void)
2908 interfaces_configured_for_ra_from_bgp
= 0;
2910 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2911 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2913 install_element(VIEW_NODE
, &show_ipv6_nd_ra_if_cmd
);
2915 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2916 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2917 install_element(INTERFACE_NODE
, &ipv6_nd_ra_retrans_interval_cmd
);
2918 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_retrans_interval_cmd
);
2919 install_element(INTERFACE_NODE
, &ipv6_nd_ra_hop_limit_cmd
);
2920 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_hop_limit_cmd
);
2921 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2922 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2923 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2924 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2925 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2926 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2927 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2928 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2929 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2930 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2931 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2932 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2933 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2934 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2935 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2936 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2937 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2938 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2939 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2940 install_element(INTERFACE_NODE
,
2941 &ipv6_nd_adv_interval_config_option_cmd
);
2942 install_element(INTERFACE_NODE
,
2943 &no_ipv6_nd_adv_interval_config_option_cmd
);
2944 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2945 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2946 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2947 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2948 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2949 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2950 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2951 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2952 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2953 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2956 static int if_join_all_router(int sock
, struct interface
*ifp
)
2960 struct ipv6_mreq mreq
;
2962 memset(&mreq
, 0, sizeof(mreq
));
2963 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2964 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2966 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2969 flog_err_sys(EC_LIB_SOCKET
,
2970 "%s(%u): Failed to join group, socket %u error %s",
2971 ifp
->name
, ifp
->ifindex
, sock
,
2972 safe_strerror(errno
));
2974 if (IS_ZEBRA_DEBUG_EVENT
)
2976 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2977 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
2982 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2986 struct ipv6_mreq mreq
;
2988 memset(&mreq
, 0, sizeof(mreq
));
2989 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2990 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2992 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2997 "%s(%s:%u): Failed to leave group, socket %u error %s",
2998 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
,
2999 safe_strerror(errno
));
3001 if (IS_ZEBRA_DEBUG_EVENT
)
3003 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
3004 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
3009 bool rtadv_compiled_in(void)
3014 #else /* !HAVE_RTADV */
3016 * If the end user does not have RADV enabled we should
3017 * handle this better
3019 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
3021 if (IS_ZEBRA_DEBUG_PACKET
)
3023 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3024 zserv_command_string(hdr
->command
));
3029 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
3031 if (IS_ZEBRA_DEBUG_PACKET
)
3033 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3034 zserv_command_string(hdr
->command
));
3039 bool rtadv_compiled_in(void)
3044 #endif /* HAVE_RTADV */
3046 uint32_t rtadv_get_interfaces_configured_from_bgp(void)
3048 return interfaces_configured_for_ra_from_bgp
;