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 (%u) doesn't agree with %s (%u)",
668 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvCurHopLimit
,
669 addr_str
, radvert
->nd_ra_curhoplimit
);
670 monotime(&zif
->rtadv
.lastadvcurhoplimit
);
673 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
) &&
674 !zif
->rtadv
.AdvManagedFlag
&&
675 (monotime_since(&zif
->rtadv
.lastadvmanagedflag
, NULL
) >
677 zif
->rtadv
.lastadvmanagedflag
.tv_sec
== 0)) {
679 EC_ZEBRA_RA_PARAM_MISMATCH
,
680 "%s(%u): Rx RA - our AdvManagedFlag (%u) doesn't agree with %s (%u)",
681 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvManagedFlag
,
683 !!CHECK_FLAG(radvert
->nd_ra_flags_reserved
,
684 ND_RA_FLAG_MANAGED
));
685 monotime(&zif
->rtadv
.lastadvmanagedflag
);
688 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
) &&
689 !zif
->rtadv
.AdvOtherConfigFlag
&&
690 (monotime_since(&zif
->rtadv
.lastadvotherconfigflag
, NULL
) >
692 zif
->rtadv
.lastadvotherconfigflag
.tv_sec
== 0)) {
694 EC_ZEBRA_RA_PARAM_MISMATCH
,
695 "%s(%u): Rx RA - our AdvOtherConfigFlag (%u) doesn't agree with %s (%u)",
696 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvOtherConfigFlag
,
698 !!CHECK_FLAG(radvert
->nd_ra_flags_reserved
,
700 monotime(&zif
->rtadv
.lastadvotherconfigflag
);
703 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
) &&
704 (ntohl(radvert
->nd_ra_reachable
) != zif
->rtadv
.AdvReachableTime
) &&
705 (monotime_since(&zif
->rtadv
.lastadvreachabletime
, NULL
) >
707 zif
->rtadv
.lastadvreachabletime
.tv_sec
== 0)) {
709 EC_ZEBRA_RA_PARAM_MISMATCH
,
710 "%s(%u): Rx RA - our AdvReachableTime (%u) doesn't agree with %s (%u)",
711 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvReachableTime
,
712 addr_str
, ntohl(radvert
->nd_ra_reachable
));
713 monotime(&zif
->rtadv
.lastadvreachabletime
);
716 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
) &&
717 (ntohl(radvert
->nd_ra_retransmit
) !=
718 (unsigned int)zif
->rtadv
.AdvRetransTimer
) &&
719 (monotime_since(&zif
->rtadv
.lastadvretranstimer
, NULL
) >
721 zif
->rtadv
.lastadvretranstimer
.tv_sec
== 0)) {
723 EC_ZEBRA_RA_PARAM_MISMATCH
,
724 "%s(%u): Rx RA - our AdvRetransTimer (%u) doesn't agree with %s (%u)",
725 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvRetransTimer
,
726 addr_str
, ntohl(radvert
->nd_ra_retransmit
));
727 monotime(&zif
->rtadv
.lastadvretranstimer
);
730 /* Create entry for neighbor if not known. */
732 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
733 p
.prefixlen
= IPV6_MAX_BITLEN
;
735 if (!nbr_connected_check(ifp
, &p
))
736 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
740 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
741 ifindex_t ifindex
, int hoplimit
,
742 struct sockaddr_in6
*from
,
743 struct zebra_vrf
*zvrf
)
745 struct icmp6_hdr
*icmph
;
746 struct interface
*ifp
;
747 struct zebra_if
*zif
;
748 char addr_str
[INET6_ADDRSTRLEN
];
750 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
752 /* Interface search. */
753 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
755 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
756 "RA/RS received on unknown IF %u from %s", ifindex
,
761 if (IS_ZEBRA_DEBUG_PACKET
)
762 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp
->name
,
763 ifp
->vrf
->name
, ifp
->ifindex
, len
, addr_str
);
765 if (if_is_loopback(ifp
))
768 /* Check interface configuration. */
770 if (!zif
->rtadv
.AdvSendAdvertisements
)
773 /* ICMP message length check. */
774 if (len
< sizeof(struct icmp6_hdr
)) {
776 "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
777 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, len
);
781 icmph
= (struct icmp6_hdr
*)buf
;
783 /* ICMP message type check. */
784 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
785 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
786 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
787 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
,
792 /* Hoplimit check. */
793 if (hoplimit
>= 0 && hoplimit
!= 255) {
794 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
795 ifp
->vrf
->name
, ifp
->ifindex
, hoplimit
);
799 /* Check ICMP message type. */
800 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
801 rtadv_process_solicit(ifp
);
802 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
803 rtadv_process_advert(buf
, len
, ifp
, from
);
808 static void rtadv_read(struct thread
*thread
)
812 uint8_t buf
[RTADV_MSG_SIZE
];
813 struct sockaddr_in6 from
;
814 ifindex_t ifindex
= 0;
816 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
818 sock
= THREAD_FD(thread
);
819 zvrf
->rtadv
.ra_read
= NULL
;
821 /* Register myself. */
822 rtadv_event(zvrf
, RTADV_READ
, 0);
824 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
828 flog_err_sys(EC_LIB_SOCKET
,
829 "RA/RS recv failed, socket %u error %s", sock
,
830 safe_strerror(errno
));
834 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
837 static int rtadv_make_socket(ns_id_t ns_id
)
841 struct icmp6_filter filter
;
844 frr_with_privs(&zserv_privs
) {
846 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
848 * with privs might set errno too if it fails save
855 zlog_warn("RTADV socket for ns: %u failure to create: %s(%u)",
856 ns_id
, safe_strerror(error
), error
);
860 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
862 zlog_warn("RTADV failure to set Packet Information");
866 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
868 zlog_warn("RTADV failure to set multicast Loop detection");
872 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
874 zlog_warn("RTADV failure to set maximum unicast hops");
878 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
880 zlog_warn("RTADV failure to set maximum multicast hops");
884 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
886 zlog_warn("RTADV failure to set maximum incoming hop limit");
891 ICMP6_FILTER_SETBLOCKALL(&filter
);
892 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
893 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
895 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
896 sizeof(struct icmp6_filter
));
898 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
906 static struct adv_if
*adv_if_new(const char *name
)
910 new = XCALLOC(MTYPE_ADV_IF
, sizeof(struct adv_if
));
912 strlcpy(new->name
, name
, sizeof(new->name
));
917 static void adv_if_free(struct adv_if
*adv_if
)
919 XFREE(MTYPE_ADV_IF
, adv_if
);
922 static bool adv_if_is_empty_internal(const struct adv_if_list_head
*adv_if_head
)
924 return adv_if_list_count(adv_if_head
) ? false : true;
927 static struct adv_if
*adv_if_add_internal(struct adv_if_list_head
*adv_if_head
,
930 struct adv_if adv_if_lookup
= {};
931 struct adv_if
*adv_if
= NULL
;
933 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
934 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
939 adv_if
= adv_if_new(adv_if_lookup
.name
);
940 adv_if_list_add(adv_if_head
, adv_if
);
945 static struct adv_if
*adv_if_del_internal(struct adv_if_list_head
*adv_if_head
,
948 struct adv_if adv_if_lookup
= {};
949 struct adv_if
*adv_if
= NULL
;
951 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
952 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
957 adv_if_list_del(adv_if_head
, adv_if
);
962 static void adv_if_clean_internal(struct adv_if_list_head
*adv_if_head
)
964 struct adv_if
*node
= NULL
;
966 if (!adv_if_is_empty_internal(adv_if_head
)) {
967 frr_each_safe (adv_if_list
, adv_if_head
, node
) {
968 adv_if_list_del(adv_if_head
, node
);
973 adv_if_list_fini(adv_if_head
);
978 * Add to list. On Success, return NULL, otherwise return already existing
981 static struct adv_if
*adv_if_add(struct zebra_vrf
*zvrf
, const char *name
)
983 struct adv_if
*adv_if
= NULL
;
985 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_if
, name
);
990 if (IS_ZEBRA_DEBUG_EVENT
) {
991 struct vrf
*vrf
= zvrf
->vrf
;
993 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
994 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
995 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1002 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1005 static struct adv_if
*adv_if_del(struct zebra_vrf
*zvrf
, const char *name
)
1007 struct adv_if
*adv_if
= NULL
;
1009 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_if
, name
);
1014 if (IS_ZEBRA_DEBUG_EVENT
) {
1015 struct vrf
*vrf
= zvrf
->vrf
;
1017 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1018 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1019 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1026 * Add to list. On Success, return NULL, otherwise return already existing
1029 static struct adv_if
*adv_msec_if_add(struct zebra_vrf
*zvrf
, const char *name
)
1031 struct adv_if
*adv_if
= NULL
;
1033 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1038 if (IS_ZEBRA_DEBUG_EVENT
) {
1039 struct vrf
*vrf
= zvrf
->vrf
;
1041 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1042 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1043 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1050 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1053 static struct adv_if
*adv_msec_if_del(struct zebra_vrf
*zvrf
, const char *name
)
1055 struct adv_if
*adv_if
= NULL
;
1057 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1062 if (IS_ZEBRA_DEBUG_EVENT
) {
1063 struct vrf
*vrf
= zvrf
->vrf
;
1065 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1066 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1067 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1073 /* Clean adv_if list, called on vrf terminate */
1074 static void adv_if_clean(struct zebra_vrf
*zvrf
)
1076 if (IS_ZEBRA_DEBUG_EVENT
) {
1077 struct vrf
*vrf
= zvrf
->vrf
;
1079 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1080 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1081 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1084 adv_if_clean_internal(&zvrf
->rtadv
.adv_if
);
1087 /* Clean adv_msec_if list, called on vrf terminate */
1088 static void adv_msec_if_clean(struct zebra_vrf
*zvrf
)
1090 if (IS_ZEBRA_DEBUG_EVENT
) {
1091 struct vrf
*vrf
= zvrf
->vrf
;
1093 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1094 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1095 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1098 adv_if_clean_internal(&zvrf
->rtadv
.adv_msec_if
);
1101 static struct rtadv_prefix
*rtadv_prefix_new(void)
1103 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
1106 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
1108 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
1111 static struct rtadv_prefix
*rtadv_prefix_get(struct rtadv_prefixes_head
*list
,
1112 struct prefix_ipv6
*p
)
1114 struct rtadv_prefix
*rprefix
, ref
;
1118 rprefix
= rtadv_prefixes_find(list
, &ref
);
1122 rprefix
= rtadv_prefix_new();
1123 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
1124 rtadv_prefixes_add(list
, rprefix
);
1129 static void rtadv_prefix_set_defaults(struct rtadv_prefix
*rp
)
1131 rp
->AdvAutonomousFlag
= 1;
1132 rp
->AdvOnLinkFlag
= 1;
1133 rp
->AdvRouterAddressFlag
= 0;
1134 rp
->AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1135 rp
->AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1138 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1140 struct rtadv_prefix
*rprefix
;
1142 rprefix
= rtadv_prefix_get(zif
->rtadv
.prefixes
, &rp
->prefix
);
1145 * Set parameters based on where the prefix is created.
1146 * If auto-created based on kernel address addition, set the
1147 * default values. If created from a manual "ipv6 nd prefix"
1148 * command, take the parameters from the manual command. Note
1149 * that if the manual command exists, the default values will
1150 * not overwrite the manual values.
1152 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1153 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_AUTO
)
1154 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1156 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1158 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
1159 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
1160 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
1161 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
1162 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
1163 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1164 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
1165 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1167 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1168 rtadv_prefix_set_defaults(rprefix
);
1173 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1175 struct rtadv_prefix
*rprefix
;
1177 rprefix
= rtadv_prefixes_find(zif
->rtadv
.prefixes
, rp
);
1178 if (rprefix
!= NULL
) {
1181 * When deleting an address from the list, need to take care
1182 * it wasn't defined both automatically via kernel
1183 * address addition as well as manually by vtysh cli. If both,
1184 * we don't actually delete but may change the parameters
1185 * back to default if a manually defined entry is deleted.
1187 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1188 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1189 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1190 rtadv_prefix_set_defaults(rprefix
);
1193 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1194 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1195 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1200 rtadv_prefixes_del(zif
->rtadv
.prefixes
, rprefix
);
1201 rtadv_prefix_free(rprefix
);
1207 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
1208 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
1210 struct rtadv_prefix rp
;
1213 apply_mask_ipv6(&rp
.prefix
);
1214 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1215 rtadv_prefix_set(zif
, &rp
);
1218 /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
1219 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
1221 struct rtadv_prefix rp
;
1223 rp
.prefix
= *((struct prefix_ipv6
*)p
);
1224 apply_mask_ipv6(&rp
.prefix
);
1225 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1226 rtadv_prefix_reset(zif
, &rp
);
1229 static void rtadv_start_interface_events(struct zebra_vrf
*zvrf
,
1230 struct zebra_if
*zif
)
1232 struct adv_if
*adv_if
= NULL
;
1234 if (zif
->ifp
->ifindex
== IFINDEX_INTERNAL
) {
1235 if (IS_ZEBRA_DEBUG_EVENT
)
1237 "%s(%s) has not configured an ifindex yet, delaying until we have one",
1238 zif
->ifp
->name
, zvrf
->vrf
->name
);
1242 adv_if
= adv_if_add(zvrf
, zif
->ifp
->name
);
1244 return; /* Already added */
1246 if_join_all_router(zvrf
->rtadv
.sock
, zif
->ifp
);
1248 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 1)
1249 rtadv_event(zvrf
, RTADV_START
, 0);
1252 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
1253 enum ipv6_nd_suppress_ra_status status
)
1255 struct zebra_if
*zif
;
1256 struct zebra_vrf
*zvrf
;
1257 struct adv_if
*adv_if
= NULL
;
1261 zvrf
= rtadv_interface_get_zvrf(ifp
);
1263 if (status
== RA_SUPPRESS
) {
1264 /* RA is currently enabled */
1265 if (zif
->rtadv
.AdvSendAdvertisements
) {
1266 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1267 zif
->rtadv
.AdvSendAdvertisements
= 0;
1268 zif
->rtadv
.AdvIntervalTimer
= 0;
1270 adv_if
= adv_if_del(zvrf
, ifp
->name
);
1272 return; /* Nothing to delete */
1274 adv_if_free(adv_if
);
1276 if_leave_all_router(zvrf
->rtadv
.sock
, ifp
);
1278 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 0)
1279 rtadv_event(zvrf
, RTADV_STOP
, 0);
1282 if (!zif
->rtadv
.AdvSendAdvertisements
) {
1283 zif
->rtadv
.AdvSendAdvertisements
= 1;
1284 zif
->rtadv
.AdvIntervalTimer
= 0;
1285 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
1286 && zif
->rtadv
.UseFastRexmit
) {
1288 * Enable Fast RA only when RA interval is in
1289 * secs and Fast RA retransmit is enabled
1291 zif
->rtadv
.inFastRexmit
= 1;
1292 zif
->rtadv
.NumFastReXmitsRemain
=
1293 RTADV_NUM_FAST_REXMITS
;
1296 rtadv_start_interface_events(zvrf
, zif
);
1302 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1303 * Note that while the client could request RA on an interface on which the
1304 * operator has not enabled RA, RA won't be disabled upon client request
1305 * if the operator has explicitly enabled RA. The enable request can also
1306 * specify a RA interval (in seconds).
1308 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
1312 struct interface
*ifp
;
1313 struct zebra_if
*zif
;
1314 uint32_t ra_interval
;
1318 /* Get interface index and RA interval. */
1319 STREAM_GETL(s
, ifindex
);
1320 STREAM_GETL(s
, ra_interval
);
1322 if (IS_ZEBRA_DEBUG_EVENT
) {
1323 struct vrf
*vrf
= zvrf
->vrf
;
1325 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1326 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1327 enable
? "enable" : "disable",
1328 zebra_route_string(client
->proto
), ra_interval
);
1331 /* Locate interface and check VRF match. */
1332 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
1334 struct vrf
*vrf
= zvrf
->vrf
;
1336 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
1337 "%s:%u: IF %u RA %s client %s - interface unknown",
1338 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1339 enable
? "enable" : "disable",
1340 zebra_route_string(client
->proto
));
1343 if (vrf_is_backend_netns() && ifp
->vrf
->vrf_id
!= zvrf_id(zvrf
)) {
1345 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1346 ifp
->vrf
->name
, zvrf_id(zvrf
), ifindex
,
1347 enable
? "enable" : "disable",
1348 zebra_route_string(client
->proto
), ifp
->vrf
->vrf_id
);
1354 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1355 interfaces_configured_for_ra_from_bgp
++;
1357 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1358 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1360 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1361 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1362 VTY_RA_INTERVAL_CONFIGURED
))
1363 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1365 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1366 interfaces_configured_for_ra_from_bgp
--;
1368 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1369 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1370 VTY_RA_INTERVAL_CONFIGURED
))
1371 zif
->rtadv
.MaxRtrAdvInterval
=
1372 RTADV_MAX_RTR_ADV_INTERVAL
;
1373 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1374 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1381 * send router lifetime value of zero in RAs on this interface since we're
1382 * ceasing to advertise and want to let our neighbors know.
1383 * RFC 4861 secion 6.2.5
1385 void rtadv_stop_ra(struct interface
*ifp
)
1387 struct zebra_if
*zif
;
1388 struct zebra_vrf
*zvrf
;
1391 zvrf
= rtadv_interface_get_zvrf(ifp
);
1393 if (zif
->rtadv
.AdvSendAdvertisements
)
1394 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1398 * Send router lifetime value of zero in RAs on all interfaces since we're
1399 * ceasing to advertise globally and want to let all of our neighbors know
1400 * RFC 4861 secion 6.2.5
1402 * Delete all ipv6 global prefixes added to the router advertisement prefix
1403 * lists prior to ceasing.
1405 void rtadv_stop_ra_all(void)
1408 struct interface
*ifp
;
1409 struct zebra_if
*zif
;
1410 struct rtadv_prefix
*rprefix
;
1412 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1413 FOR_ALL_INTERFACES (vrf
, ifp
) {
1416 frr_each_safe (rtadv_prefixes
, zif
->rtadv
.prefixes
,
1418 rtadv_prefix_reset(zif
, rprefix
);
1424 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1426 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1428 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1430 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1433 static void show_zvrf_rtadv_adv_if_helper(struct vty
*vty
,
1434 struct adv_if_list_head
*adv_if_head
)
1436 struct adv_if
*node
= NULL
;
1438 if (!adv_if_is_empty_internal(adv_if_head
)) {
1439 frr_each (adv_if_list
, adv_if_head
, node
) {
1440 vty_out(vty
, " %s\n", node
->name
);
1447 static void show_zvrf_rtadv_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
)
1449 vty_out(vty
, "VRF: %s\n", zvrf_name(zvrf
));
1450 vty_out(vty
, " Interfaces:\n");
1451 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_if
);
1453 vty_out(vty
, " Interfaces(msec):\n");
1454 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_msec_if
);
1457 DEFPY(show_ipv6_nd_ra_if
, show_ipv6_nd_ra_if_cmd
,
1458 "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
1460 "Neighbor discovery\n"
1461 "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR
)
1463 struct zebra_vrf
*zvrf
= NULL
;
1465 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1467 "%% VRF subcommand only applicable for netns-based vrfs.\n");
1474 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1475 struct zebra_vrf
*zvrf
;
1481 show_zvrf_rtadv_helper(vty
, zvrf
);
1488 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1490 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1493 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1498 show_zvrf_rtadv_helper(vty
, zvrf
);
1503 DEFUN (ipv6_nd_ra_fast_retrans
,
1504 ipv6_nd_ra_fast_retrans_cmd
,
1505 "ipv6 nd ra-fast-retrans",
1506 "Interface IPv6 config commands\n"
1507 "Neighbor discovery\n"
1508 "Fast retransmit of RA packets\n")
1510 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1511 struct zebra_if
*zif
= ifp
->info
;
1513 if (if_is_loopback(ifp
)) {
1515 "Cannot configure IPv6 Router Advertisements on this interface\n");
1516 return CMD_WARNING_CONFIG_FAILED
;
1519 zif
->rtadv
.UseFastRexmit
= true;
1524 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1525 no_ipv6_nd_ra_fast_retrans_cmd
,
1526 "no ipv6 nd ra-fast-retrans",
1528 "Interface IPv6 config commands\n"
1529 "Neighbor discovery\n"
1530 "Fast retransmit of RA packets\n")
1532 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1533 struct zebra_if
*zif
= ifp
->info
;
1535 if (if_is_loopback(ifp
)) {
1537 "Cannot configure IPv6 Router Advertisements on this interface\n");
1538 return CMD_WARNING_CONFIG_FAILED
;
1541 zif
->rtadv
.UseFastRexmit
= false;
1546 DEFPY (ipv6_nd_ra_hop_limit
,
1547 ipv6_nd_ra_hop_limit_cmd
,
1548 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1549 "Interface IPv6 config commands\n"
1550 "Neighbor discovery\n"
1551 "Advertisement Hop Limit\n"
1552 "Advertisement Hop Limit in hops (default:64)\n")
1554 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1555 struct zebra_if
*zif
= ifp
->info
;
1557 if (if_is_loopback(ifp
)) {
1559 "Cannot configure IPv6 Router Advertisements on this interface\n");
1560 return CMD_WARNING_CONFIG_FAILED
;
1563 zif
->rtadv
.AdvCurHopLimit
= hopcount
;
1568 DEFPY (no_ipv6_nd_ra_hop_limit
,
1569 no_ipv6_nd_ra_hop_limit_cmd
,
1570 "no ipv6 nd ra-hop-limit [(0-255)]",
1572 "Interface IPv6 config commands\n"
1573 "Neighbor discovery\n"
1574 "Advertisement Hop Limit\n"
1575 "Advertisement Hop Limit in hops\n")
1577 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1578 struct zebra_if
*zif
= ifp
->info
;
1580 if (if_is_loopback(ifp
)) {
1582 "Cannot configure IPv6 Router Advertisements on this interface\n");
1583 return CMD_WARNING_CONFIG_FAILED
;
1586 zif
->rtadv
.AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
1591 DEFPY (ipv6_nd_ra_retrans_interval
,
1592 ipv6_nd_ra_retrans_interval_cmd
,
1593 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1594 "Interface IPv6 config commands\n"
1595 "Neighbor discovery\n"
1596 "Advertisement Retransmit Interval\n"
1597 "Advertisement Retransmit Interval in msec\n")
1599 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1600 struct zebra_if
*zif
= ifp
->info
;
1602 if (if_is_loopback(ifp
)) {
1604 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1605 return CMD_WARNING_CONFIG_FAILED
;
1608 zif
->rtadv
.AdvRetransTimer
= interval
;
1613 DEFPY (no_ipv6_nd_ra_retrans_interval
,
1614 no_ipv6_nd_ra_retrans_interval_cmd
,
1615 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1617 "Interface IPv6 config commands\n"
1618 "Neighbor discovery\n"
1619 "Advertisement Retransmit Interval\n"
1620 "Advertisement Retransmit Interval in msec\n")
1622 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1623 struct zebra_if
*zif
= ifp
->info
;
1625 if (if_is_loopback(ifp
)) {
1627 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1628 return CMD_WARNING_CONFIG_FAILED
;
1631 zif
->rtadv
.AdvRetransTimer
= 0;
1636 DEFUN (ipv6_nd_suppress_ra
,
1637 ipv6_nd_suppress_ra_cmd
,
1638 "ipv6 nd suppress-ra",
1639 "Interface IPv6 config commands\n"
1640 "Neighbor discovery\n"
1641 "Suppress Router Advertisement\n")
1643 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1644 struct zebra_if
*zif
= ifp
->info
;
1646 if (if_is_loopback(ifp
)) {
1648 "Cannot configure IPv6 Router Advertisements on this interface\n");
1649 return CMD_WARNING_CONFIG_FAILED
;
1652 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1653 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1655 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1659 DEFUN (no_ipv6_nd_suppress_ra
,
1660 no_ipv6_nd_suppress_ra_cmd
,
1661 "no ipv6 nd suppress-ra",
1663 "Interface IPv6 config commands\n"
1664 "Neighbor discovery\n"
1665 "Suppress Router Advertisement\n")
1667 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1668 struct zebra_if
*zif
= ifp
->info
;
1670 if (if_is_loopback(ifp
)) {
1672 "Cannot configure IPv6 Router Advertisements on this interface\n");
1673 return CMD_WARNING_CONFIG_FAILED
;
1676 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1677 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1681 DEFUN (ipv6_nd_ra_interval_msec
,
1682 ipv6_nd_ra_interval_msec_cmd
,
1683 "ipv6 nd ra-interval msec (70-1800000)",
1684 "Interface IPv6 config commands\n"
1685 "Neighbor discovery\n"
1686 "Router Advertisement interval\n"
1687 "Router Advertisement interval in milliseconds\n"
1688 "Router Advertisement interval in milliseconds\n")
1691 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1693 struct zebra_if
*zif
= ifp
->info
;
1694 struct zebra_vrf
*zvrf
;
1695 struct adv_if
*adv_if
;
1697 zvrf
= rtadv_interface_get_zvrf(ifp
);
1699 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1700 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1701 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1703 "This ra-interval would conflict with configured ra-lifetime!\n");
1704 return CMD_WARNING_CONFIG_FAILED
;
1707 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1708 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1710 adv_if_free(adv_if
);
1713 if (interval
% 1000)
1714 (void)adv_msec_if_add(zvrf
, ifp
->name
);
1716 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1717 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1718 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1719 zif
->rtadv
.AdvIntervalTimer
= 0;
1724 DEFUN (ipv6_nd_ra_interval
,
1725 ipv6_nd_ra_interval_cmd
,
1726 "ipv6 nd ra-interval (1-1800)",
1727 "Interface IPv6 config commands\n"
1728 "Neighbor discovery\n"
1729 "Router Advertisement interval\n"
1730 "Router Advertisement interval in seconds\n")
1733 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1735 struct zebra_if
*zif
= ifp
->info
;
1736 struct zebra_vrf
*zvrf
;
1737 struct adv_if
*adv_if
;
1739 zvrf
= rtadv_interface_get_zvrf(ifp
);
1741 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1742 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1743 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1745 "This ra-interval would conflict with configured ra-lifetime!\n");
1746 return CMD_WARNING_CONFIG_FAILED
;
1749 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1750 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1752 adv_if_free(adv_if
);
1755 /* convert to milliseconds */
1756 interval
= interval
* 1000;
1758 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1759 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1760 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1761 zif
->rtadv
.AdvIntervalTimer
= 0;
1766 DEFUN (no_ipv6_nd_ra_interval
,
1767 no_ipv6_nd_ra_interval_cmd
,
1768 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1770 "Interface IPv6 config commands\n"
1771 "Neighbor discovery\n"
1772 "Router Advertisement interval\n"
1773 "Router Advertisement interval in seconds\n"
1774 "Specify millisecond router advertisement interval\n"
1775 "Router Advertisement interval in milliseconds\n")
1777 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1778 struct zebra_if
*zif
= ifp
->info
;
1779 struct zebra_vrf
*zvrf
= NULL
;
1780 struct adv_if
*adv_if
;
1782 zvrf
= rtadv_interface_get_zvrf(ifp
);
1784 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1785 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1787 adv_if_free(adv_if
);
1790 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1792 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1793 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1795 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1797 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1798 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1803 DEFUN (ipv6_nd_ra_lifetime
,
1804 ipv6_nd_ra_lifetime_cmd
,
1805 "ipv6 nd ra-lifetime (0-9000)",
1806 "Interface IPv6 config commands\n"
1807 "Neighbor discovery\n"
1809 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1812 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1813 struct zebra_if
*zif
= ifp
->info
;
1816 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1818 /* The value to be placed in the Router Lifetime field
1819 * of Router Advertisements sent from the interface,
1820 * in seconds. MUST be either zero or between
1821 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1822 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1824 "This ra-lifetime would conflict with configured ra-interval\n");
1825 return CMD_WARNING_CONFIG_FAILED
;
1828 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1833 DEFUN (no_ipv6_nd_ra_lifetime
,
1834 no_ipv6_nd_ra_lifetime_cmd
,
1835 "no ipv6 nd ra-lifetime [(0-9000)]",
1837 "Interface IPv6 config commands\n"
1838 "Neighbor discovery\n"
1840 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1842 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1843 struct zebra_if
*zif
= ifp
->info
;
1845 zif
->rtadv
.AdvDefaultLifetime
= -1;
1850 DEFUN (ipv6_nd_reachable_time
,
1851 ipv6_nd_reachable_time_cmd
,
1852 "ipv6 nd reachable-time (1-3600000)",
1853 "Interface IPv6 config commands\n"
1854 "Neighbor discovery\n"
1856 "Reachable time in milliseconds\n")
1859 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1860 struct zebra_if
*zif
= ifp
->info
;
1861 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1865 DEFUN (no_ipv6_nd_reachable_time
,
1866 no_ipv6_nd_reachable_time_cmd
,
1867 "no ipv6 nd reachable-time [(1-3600000)]",
1869 "Interface IPv6 config commands\n"
1870 "Neighbor discovery\n"
1872 "Reachable time in milliseconds\n")
1874 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1875 struct zebra_if
*zif
= ifp
->info
;
1877 zif
->rtadv
.AdvReachableTime
= 0;
1882 DEFUN (ipv6_nd_homeagent_preference
,
1883 ipv6_nd_homeagent_preference_cmd
,
1884 "ipv6 nd home-agent-preference (0-65535)",
1885 "Interface IPv6 config commands\n"
1886 "Neighbor discovery\n"
1887 "Home Agent preference\n"
1888 "preference value (default is 0, least preferred)\n")
1891 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1892 struct zebra_if
*zif
= ifp
->info
;
1893 zif
->rtadv
.HomeAgentPreference
=
1894 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1898 DEFUN (no_ipv6_nd_homeagent_preference
,
1899 no_ipv6_nd_homeagent_preference_cmd
,
1900 "no ipv6 nd home-agent-preference [(0-65535)]",
1902 "Interface IPv6 config commands\n"
1903 "Neighbor discovery\n"
1904 "Home Agent preference\n"
1905 "preference value (default is 0, least preferred)\n")
1907 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1908 struct zebra_if
*zif
= ifp
->info
;
1910 zif
->rtadv
.HomeAgentPreference
= 0;
1915 DEFUN (ipv6_nd_homeagent_lifetime
,
1916 ipv6_nd_homeagent_lifetime_cmd
,
1917 "ipv6 nd home-agent-lifetime (0-65520)",
1918 "Interface IPv6 config commands\n"
1919 "Neighbor discovery\n"
1920 "Home Agent lifetime\n"
1921 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1924 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1925 struct zebra_if
*zif
= ifp
->info
;
1926 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1930 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1931 no_ipv6_nd_homeagent_lifetime_cmd
,
1932 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1934 "Interface IPv6 config commands\n"
1935 "Neighbor discovery\n"
1936 "Home Agent lifetime\n"
1937 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1939 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1940 struct zebra_if
*zif
= ifp
->info
;
1942 zif
->rtadv
.HomeAgentLifetime
= -1;
1947 DEFUN (ipv6_nd_managed_config_flag
,
1948 ipv6_nd_managed_config_flag_cmd
,
1949 "ipv6 nd managed-config-flag",
1950 "Interface IPv6 config commands\n"
1951 "Neighbor discovery\n"
1952 "Managed address configuration flag\n")
1954 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1955 struct zebra_if
*zif
= ifp
->info
;
1957 zif
->rtadv
.AdvManagedFlag
= 1;
1962 DEFUN (no_ipv6_nd_managed_config_flag
,
1963 no_ipv6_nd_managed_config_flag_cmd
,
1964 "no ipv6 nd managed-config-flag",
1966 "Interface IPv6 config commands\n"
1967 "Neighbor discovery\n"
1968 "Managed address configuration flag\n")
1970 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1971 struct zebra_if
*zif
= ifp
->info
;
1973 zif
->rtadv
.AdvManagedFlag
= 0;
1978 DEFUN (ipv6_nd_homeagent_config_flag
,
1979 ipv6_nd_homeagent_config_flag_cmd
,
1980 "ipv6 nd home-agent-config-flag",
1981 "Interface IPv6 config commands\n"
1982 "Neighbor discovery\n"
1983 "Home Agent configuration flag\n")
1985 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1986 struct zebra_if
*zif
= ifp
->info
;
1988 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1993 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1994 no_ipv6_nd_homeagent_config_flag_cmd
,
1995 "no ipv6 nd home-agent-config-flag",
1997 "Interface IPv6 config commands\n"
1998 "Neighbor discovery\n"
1999 "Home Agent configuration flag\n")
2001 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2002 struct zebra_if
*zif
= ifp
->info
;
2004 zif
->rtadv
.AdvHomeAgentFlag
= 0;
2009 DEFUN (ipv6_nd_adv_interval_config_option
,
2010 ipv6_nd_adv_interval_config_option_cmd
,
2011 "ipv6 nd adv-interval-option",
2012 "Interface IPv6 config commands\n"
2013 "Neighbor discovery\n"
2014 "Advertisement Interval Option\n")
2016 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2017 struct zebra_if
*zif
= ifp
->info
;
2019 zif
->rtadv
.AdvIntervalOption
= 1;
2024 DEFUN (no_ipv6_nd_adv_interval_config_option
,
2025 no_ipv6_nd_adv_interval_config_option_cmd
,
2026 "no ipv6 nd adv-interval-option",
2028 "Interface IPv6 config commands\n"
2029 "Neighbor discovery\n"
2030 "Advertisement Interval Option\n")
2032 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2033 struct zebra_if
*zif
= ifp
->info
;
2035 zif
->rtadv
.AdvIntervalOption
= 0;
2040 DEFUN (ipv6_nd_other_config_flag
,
2041 ipv6_nd_other_config_flag_cmd
,
2042 "ipv6 nd other-config-flag",
2043 "Interface IPv6 config commands\n"
2044 "Neighbor discovery\n"
2045 "Other statefull configuration flag\n")
2047 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2048 struct zebra_if
*zif
= ifp
->info
;
2050 zif
->rtadv
.AdvOtherConfigFlag
= 1;
2055 DEFUN (no_ipv6_nd_other_config_flag
,
2056 no_ipv6_nd_other_config_flag_cmd
,
2057 "no ipv6 nd other-config-flag",
2059 "Interface IPv6 config commands\n"
2060 "Neighbor discovery\n"
2061 "Other statefull configuration flag\n")
2063 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2064 struct zebra_if
*zif
= ifp
->info
;
2066 zif
->rtadv
.AdvOtherConfigFlag
= 0;
2071 DEFUN (ipv6_nd_prefix
,
2073 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2074 "Interface IPv6 config commands\n"
2075 "Neighbor discovery\n"
2076 "Prefix information\n"
2078 "Valid lifetime in seconds\n"
2079 "Infinite valid lifetime\n"
2080 "Preferred lifetime in seconds\n"
2081 "Infinite preferred lifetime\n"
2082 "Set Router Address flag\n"
2083 "Do not use prefix for onlink determination\n"
2084 "Do not use prefix for autoconfiguration\n"
2085 "Do not use prefix for autoconfiguration\n"
2086 "Do not use prefix for onlink determination\n")
2089 char *prefix
= argv
[3]->arg
;
2090 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
2091 || strmatch(argv
[4]->text
, "infinite"));
2092 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
2094 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
2096 char *lifetime
= NULL
, *preflifetime
= NULL
;
2097 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
2099 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2101 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
2106 strmatch(argv
[idx_routeropts
]->text
, "router-address");
2108 offlink
= (argc
> idx_routeropts
+ 1
2109 || strmatch(argv
[idx_routeropts
]->text
,
2111 noautoconf
= (argc
> idx_routeropts
+ 1
2112 || strmatch(argv
[idx_routeropts
]->text
,
2118 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2119 struct zebra_if
*zebra_if
= ifp
->info
;
2121 struct rtadv_prefix rp
;
2123 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2125 vty_out(vty
, "Malformed IPv6 prefix\n");
2126 return CMD_WARNING_CONFIG_FAILED
;
2128 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2129 rp
.AdvOnLinkFlag
= !offlink
;
2130 rp
.AdvAutonomousFlag
= !noautoconf
;
2131 rp
.AdvRouterAddressFlag
= routeraddr
;
2132 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
2133 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
2134 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2137 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
2139 : strtoll(lifetime
, NULL
, 10);
2140 rp
.AdvPreferredLifetime
=
2141 strmatch(preflifetime
, "infinite")
2143 : strtoll(preflifetime
, NULL
, 10);
2144 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
2145 vty_out(vty
, "Invalid preferred lifetime\n");
2146 return CMD_WARNING_CONFIG_FAILED
;
2150 rtadv_prefix_set(zebra_if
, &rp
);
2155 DEFUN (no_ipv6_nd_prefix
,
2156 no_ipv6_nd_prefix_cmd
,
2157 "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]>]",
2159 "Interface IPv6 config commands\n"
2160 "Neighbor discovery\n"
2161 "Prefix information\n"
2163 "Valid lifetime in seconds\n"
2164 "Infinite valid lifetime\n"
2165 "Preferred lifetime in seconds\n"
2166 "Infinite preferred lifetime\n"
2167 "Set Router Address flag\n"
2168 "Do not use prefix for onlink determination\n"
2169 "Do not use prefix for autoconfiguration\n"
2170 "Do not use prefix for autoconfiguration\n"
2171 "Do not use prefix for onlink determination\n")
2173 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2174 struct zebra_if
*zebra_if
= ifp
->info
;
2176 struct rtadv_prefix rp
;
2177 char *prefix
= argv
[4]->arg
;
2179 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2181 vty_out(vty
, "Malformed IPv6 prefix\n");
2182 return CMD_WARNING_CONFIG_FAILED
;
2184 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2185 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2187 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
2189 vty_out(vty
, "Non-existant IPv6 prefix\n");
2190 return CMD_WARNING_CONFIG_FAILED
;
2196 DEFUN (ipv6_nd_router_preference
,
2197 ipv6_nd_router_preference_cmd
,
2198 "ipv6 nd router-preference <high|medium|low>",
2199 "Interface IPv6 config commands\n"
2200 "Neighbor discovery\n"
2201 "Default router preference\n"
2202 "High default router preference\n"
2203 "Medium default router preference (default)\n"
2204 "Low default router preference\n")
2206 int idx_high_medium_low
= 3;
2207 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2208 struct zebra_if
*zif
= ifp
->info
;
2211 while (0 != rtadv_pref_strs
[i
]) {
2212 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
2215 zif
->rtadv
.DefaultPreference
= i
;
2221 return CMD_ERR_NO_MATCH
;
2224 DEFUN (no_ipv6_nd_router_preference
,
2225 no_ipv6_nd_router_preference_cmd
,
2226 "no ipv6 nd router-preference [<high|medium|low>]",
2228 "Interface IPv6 config commands\n"
2229 "Neighbor discovery\n"
2230 "Default router preference\n"
2231 "High default router preference\n"
2232 "Medium default router preference (default)\n"
2233 "Low default router preference\n")
2235 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2236 struct zebra_if
*zif
= ifp
->info
;
2238 zif
->rtadv
.DefaultPreference
=
2239 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
2246 "ipv6 nd mtu (1-65535)",
2247 "Interface IPv6 config commands\n"
2248 "Neighbor discovery\n"
2253 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2254 struct zebra_if
*zif
= ifp
->info
;
2255 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2259 DEFUN (no_ipv6_nd_mtu
,
2261 "no ipv6 nd mtu [(1-65535)]",
2263 "Interface IPv6 config commands\n"
2264 "Neighbor discovery\n"
2268 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2269 struct zebra_if
*zif
= ifp
->info
;
2270 zif
->rtadv
.AdvLinkMTU
= 0;
2274 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
2276 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
2279 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
2281 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
2284 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
2285 struct rtadv_rdnss
*rdnss
)
2287 struct listnode
*node
;
2288 struct rtadv_rdnss
*p
;
2290 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2291 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
2296 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
2297 struct rtadv_rdnss
*rdnss
)
2299 struct rtadv_rdnss
*p
;
2301 p
= rtadv_rdnss_lookup(list
, rdnss
);
2305 p
= rtadv_rdnss_new();
2306 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
2307 listnode_add(list
, p
);
2312 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2314 struct rtadv_rdnss
*p
;
2316 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2317 p
->lifetime
= rdnss
->lifetime
;
2318 p
->lifetime_set
= rdnss
->lifetime_set
;
2321 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2323 struct rtadv_rdnss
*p
;
2325 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2327 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
2328 rtadv_rdnss_free(p
);
2335 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
2337 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
2340 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
2342 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
2345 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
2346 struct rtadv_dnssl
*dnssl
)
2348 struct listnode
*node
;
2349 struct rtadv_dnssl
*p
;
2351 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2352 if (!strcasecmp(p
->name
, dnssl
->name
))
2357 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
2358 struct rtadv_dnssl
*dnssl
)
2360 struct rtadv_dnssl
*p
;
2362 p
= rtadv_dnssl_lookup(list
, dnssl
);
2366 p
= rtadv_dnssl_new();
2367 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2368 listnode_add(list
, p
);
2373 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2375 struct rtadv_dnssl
*p
;
2377 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2378 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2381 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2383 struct rtadv_dnssl
*p
;
2385 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2387 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
2388 rtadv_dnssl_free(p
);
2396 * Convert dotted domain name (with or without trailing root zone dot) to
2397 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2398 * to strlen(in) + 2 octets to out.
2400 * Returns the number of octets written to out or -1 if in does not constitute
2401 * a valid domain name.
2403 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
2405 const char *label_start
, *label_end
;
2411 while (*label_start
) {
2414 label_end
= strchr(label_start
, '.');
2415 if (label_end
== NULL
)
2416 label_end
= label_start
+ strlen(label_start
);
2418 label_len
= label_end
- label_start
;
2419 if (label_len
>= 64)
2420 return -1; /* labels must be 63 octets or less */
2422 out
[outp
++] = (uint8_t)label_len
;
2423 memcpy(out
+ outp
, label_start
, label_len
);
2425 label_start
+= label_len
;
2426 if (*label_start
== '.')
2434 DEFUN(ipv6_nd_rdnss
,
2436 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2437 "Interface IPv6 config commands\n"
2438 "Neighbor discovery\n"
2439 "Recursive DNS server information\n"
2441 "Valid lifetime in seconds\n"
2442 "Infinite valid lifetime\n")
2444 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2445 struct zebra_if
*zif
= ifp
->info
;
2446 struct rtadv_rdnss rdnss
= {};
2448 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
2449 vty_out(vty
, "Malformed IPv6 address\n");
2450 return CMD_WARNING_CONFIG_FAILED
;
2453 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2455 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
2457 : strtoll(lifetime
, NULL
, 10);
2458 rdnss
.lifetime_set
= 1;
2461 rtadv_rdnss_set(zif
, &rdnss
);
2466 DEFUN(no_ipv6_nd_rdnss
,
2467 no_ipv6_nd_rdnss_cmd
,
2468 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2470 "Interface IPv6 config commands\n"
2471 "Neighbor discovery\n"
2472 "Recursive DNS server information\n"
2474 "Valid lifetime in seconds\n"
2475 "Infinite valid lifetime\n")
2477 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2478 struct zebra_if
*zif
= ifp
->info
;
2479 struct rtadv_rdnss rdnss
= {};
2481 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
2482 vty_out(vty
, "Malformed IPv6 address\n");
2483 return CMD_WARNING_CONFIG_FAILED
;
2485 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
2486 vty_out(vty
, "Non-existant RDNSS address\n");
2487 return CMD_WARNING_CONFIG_FAILED
;
2493 DEFUN(ipv6_nd_dnssl
,
2495 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2496 "Interface IPv6 config commands\n"
2497 "Neighbor discovery\n"
2498 "DNS search list information\n"
2499 "Domain name suffix\n"
2500 "Valid lifetime in seconds\n"
2501 "Infinite valid lifetime\n")
2503 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2504 struct zebra_if
*zif
= ifp
->info
;
2505 struct rtadv_dnssl dnssl
= {};
2509 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
2510 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2511 vty_out(vty
, "Malformed DNS search domain\n");
2512 return CMD_WARNING_CONFIG_FAILED
;
2514 if (dnssl
.name
[len
- 1] == '.') {
2516 * Allow, but don't require, a trailing dot signifying the root
2517 * zone. Canonicalize by cutting it off if present.
2519 dnssl
.name
[len
- 1] = '\0';
2523 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2525 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
2527 : strtoll(lifetime
, NULL
, 10);
2528 dnssl
.lifetime_set
= 1;
2531 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2533 vty_out(vty
, "Malformed DNS search domain\n");
2534 return CMD_WARNING_CONFIG_FAILED
;
2536 dnssl
.encoded_len
= ret
;
2537 rtadv_dnssl_set(zif
, &dnssl
);
2542 DEFUN(no_ipv6_nd_dnssl
,
2543 no_ipv6_nd_dnssl_cmd
,
2544 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2546 "Interface IPv6 config commands\n"
2547 "Neighbor discovery\n"
2548 "DNS search list information\n"
2549 "Domain name suffix\n"
2550 "Valid lifetime in seconds\n"
2551 "Infinite valid lifetime\n")
2553 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2554 struct zebra_if
*zif
= ifp
->info
;
2555 struct rtadv_dnssl dnssl
= {};
2558 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2559 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2560 vty_out(vty
, "Malformed DNS search domain\n");
2561 return CMD_WARNING_CONFIG_FAILED
;
2563 if (dnssl
.name
[len
- 1] == '.') {
2564 dnssl
.name
[len
- 1] = '\0';
2567 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2568 vty_out(vty
, "Non-existant DNS search domain\n");
2569 return CMD_WARNING_CONFIG_FAILED
;
2576 /* Dump interface ND information to vty. */
2577 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2579 struct zebra_if
*zif
;
2580 struct rtadvconf
*rtadv
;
2583 zif
= (struct zebra_if
*)ifp
->info
;
2584 rtadv
= &zif
->rtadv
;
2586 if (rtadv
->AdvSendAdvertisements
) {
2588 " ND advertised reachable time is %d milliseconds\n",
2589 rtadv
->AdvReachableTime
);
2591 " ND advertised retransmit interval is %u milliseconds\n",
2592 rtadv
->AdvRetransTimer
);
2593 vty_out(vty
, " ND advertised hop-count limit is %d hops\n",
2594 rtadv
->AdvCurHopLimit
);
2595 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2596 zif
->ra_sent
, zif
->ra_rcvd
);
2597 interval
= rtadv
->MaxRtrAdvInterval
;
2598 if (interval
% 1000)
2600 " ND router advertisements are sent every %d milliseconds\n",
2604 " ND router advertisements are sent every %d seconds\n",
2606 if (!rtadv
->UseFastRexmit
)
2608 " ND router advertisements do not use fast retransmit\n");
2610 if (rtadv
->AdvDefaultLifetime
!= -1)
2612 " ND router advertisements live for %d seconds\n",
2613 rtadv
->AdvDefaultLifetime
);
2616 " ND router advertisements lifetime tracks ra-interval\n");
2618 " ND router advertisement default router preference is %s\n",
2619 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2620 if (rtadv
->AdvManagedFlag
)
2622 " Hosts use DHCP to obtain routable addresses.\n");
2625 " Hosts use stateless autoconfig for addresses.\n");
2626 if (rtadv
->AdvHomeAgentFlag
) {
2628 " ND router advertisements with Home Agent flag bit set.\n");
2629 if (rtadv
->HomeAgentLifetime
!= -1)
2631 " Home Agent lifetime is %u seconds\n",
2632 rtadv
->HomeAgentLifetime
);
2635 " Home Agent lifetime tracks ra-lifetime\n");
2636 vty_out(vty
, " Home Agent preference is %u\n",
2637 rtadv
->HomeAgentPreference
);
2639 if (rtadv
->AdvIntervalOption
)
2641 " ND router advertisements with Adv. Interval option.\n");
2647 /* Write configuration about router advertisement. */
2648 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2650 struct zebra_if
*zif
;
2651 struct listnode
*node
;
2652 struct rtadv_prefix
*rprefix
;
2653 struct rtadv_rdnss
*rdnss
;
2654 struct rtadv_dnssl
*dnssl
;
2659 if (!if_is_loopback(ifp
)) {
2660 if (zif
->rtadv
.AdvSendAdvertisements
2661 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2662 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2665 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2666 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2667 if (interval
% 1000)
2668 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2670 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2671 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2675 if (zif
->rtadv
.AdvIntervalOption
)
2676 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2678 if (!zif
->rtadv
.UseFastRexmit
)
2679 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2681 if (zif
->rtadv
.AdvRetransTimer
!= 0)
2682 vty_out(vty
, " ipv6 nd ra-retrans-interval %u\n",
2683 zif
->rtadv
.AdvRetransTimer
);
2685 if (zif
->rtadv
.AdvCurHopLimit
!= RTADV_DEFAULT_HOPLIMIT
)
2686 vty_out(vty
, " ipv6 nd ra-hop-limit %d\n",
2687 zif
->rtadv
.AdvCurHopLimit
);
2689 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2690 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2691 zif
->rtadv
.AdvDefaultLifetime
);
2693 if (zif
->rtadv
.HomeAgentPreference
)
2694 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2695 zif
->rtadv
.HomeAgentPreference
);
2697 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2698 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2699 zif
->rtadv
.HomeAgentLifetime
);
2701 if (zif
->rtadv
.AdvHomeAgentFlag
)
2702 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2704 if (zif
->rtadv
.AdvReachableTime
)
2705 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2706 zif
->rtadv
.AdvReachableTime
);
2708 if (zif
->rtadv
.AdvManagedFlag
)
2709 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2711 if (zif
->rtadv
.AdvOtherConfigFlag
)
2712 vty_out(vty
, " ipv6 nd other-config-flag\n");
2714 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2715 vty_out(vty
, " ipv6 nd router-preference %s\n",
2716 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2718 if (zif
->rtadv
.AdvLinkMTU
)
2719 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2721 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
2722 if ((rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
2723 || (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
)) {
2724 vty_out(vty
, " ipv6 nd prefix %pFX", &rprefix
->prefix
);
2725 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2726 || (rprefix
->AdvPreferredLifetime
2727 != RTADV_PREFERRED_LIFETIME
)) {
2728 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2729 vty_out(vty
, " infinite");
2732 rprefix
->AdvValidLifetime
);
2733 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2734 vty_out(vty
, " infinite");
2737 rprefix
->AdvPreferredLifetime
);
2739 if (!rprefix
->AdvOnLinkFlag
)
2740 vty_out(vty
, " off-link");
2741 if (!rprefix
->AdvAutonomousFlag
)
2742 vty_out(vty
, " no-autoconfig");
2743 if (rprefix
->AdvRouterAddressFlag
)
2744 vty_out(vty
, " router-address");
2749 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2750 char buf
[INET6_ADDRSTRLEN
];
2752 vty_out(vty
, " ipv6 nd rdnss %s",
2753 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2754 if (rdnss
->lifetime_set
) {
2755 if (rdnss
->lifetime
== UINT32_MAX
)
2756 vty_out(vty
, " infinite");
2758 vty_out(vty
, " %u", rdnss
->lifetime
);
2762 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2763 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2764 if (dnssl
->lifetime_set
) {
2765 if (dnssl
->lifetime
== UINT32_MAX
)
2766 vty_out(vty
, " infinite");
2768 vty_out(vty
, " %u", dnssl
->lifetime
);
2776 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2778 struct rtadv
*rtadv
;
2780 if (IS_ZEBRA_DEBUG_EVENT
) {
2781 struct vrf
*vrf
= zvrf
->vrf
;
2783 zlog_debug("%s(%s) with event: %d and val: %d", __func__
,
2784 VRF_LOGNAME(vrf
), event
, val
);
2787 rtadv
= &zvrf
->rtadv
;
2791 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2793 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2797 THREAD_OFF(rtadv
->ra_timer
);
2798 THREAD_OFF(rtadv
->ra_read
);
2801 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2804 case RTADV_TIMER_MSEC
:
2805 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2809 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2818 void rtadv_if_up(struct zebra_if
*zif
)
2820 struct zebra_vrf
*zvrf
= rtadv_interface_get_zvrf(zif
->ifp
);
2822 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
2823 if (zif
->rtadv
.AdvSendAdvertisements
&&
2824 (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) &&
2825 zif
->rtadv
.UseFastRexmit
) {
2826 zif
->rtadv
.inFastRexmit
= 1;
2827 zif
->rtadv
.NumFastReXmitsRemain
= RTADV_NUM_FAST_REXMITS
;
2831 * startup the state machine, if it hasn't been already
2832 * due to a delayed ifindex on startup ordering
2834 if (zif
->rtadv
.AdvSendAdvertisements
)
2835 rtadv_start_interface_events(zvrf
, zif
);
2838 void rtadv_if_init(struct zebra_if
*zif
)
2840 /* Set default router advertise values. */
2841 struct rtadvconf
*rtadv
;
2843 rtadv
= &zif
->rtadv
;
2845 rtadv
->AdvSendAdvertisements
= 0;
2846 rtadv
->MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
2847 rtadv
->MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
2848 rtadv
->AdvIntervalTimer
= 0;
2849 rtadv
->AdvManagedFlag
= 0;
2850 rtadv
->AdvOtherConfigFlag
= 0;
2851 rtadv
->AdvHomeAgentFlag
= 0;
2852 rtadv
->AdvLinkMTU
= 0;
2853 rtadv
->AdvReachableTime
= 0;
2854 rtadv
->AdvRetransTimer
= 0;
2855 rtadv
->AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
2856 memset(&rtadv
->lastadvcurhoplimit
, 0,
2857 sizeof(rtadv
->lastadvcurhoplimit
));
2858 memset(&rtadv
->lastadvmanagedflag
, 0,
2859 sizeof(rtadv
->lastadvmanagedflag
));
2860 memset(&rtadv
->lastadvotherconfigflag
, 0,
2861 sizeof(rtadv
->lastadvotherconfigflag
));
2862 memset(&rtadv
->lastadvreachabletime
, 0,
2863 sizeof(rtadv
->lastadvreachabletime
));
2864 memset(&rtadv
->lastadvretranstimer
, 0,
2865 sizeof(rtadv
->lastadvretranstimer
));
2866 rtadv
->AdvDefaultLifetime
= -1; /* derive from MaxRtrAdvInterval */
2867 rtadv
->HomeAgentPreference
= 0;
2868 rtadv
->HomeAgentLifetime
= -1; /* derive from AdvDefaultLifetime */
2869 rtadv
->AdvIntervalOption
= 0;
2870 rtadv
->UseFastRexmit
= true;
2871 rtadv
->DefaultPreference
= RTADV_PREF_MEDIUM
;
2873 rtadv_prefixes_init(rtadv
->prefixes
);
2875 rtadv
->AdvRDNSSList
= list_new();
2876 rtadv
->AdvDNSSLList
= list_new();
2879 void rtadv_if_fini(struct zebra_if
*zif
)
2881 struct rtadvconf
*rtadv
;
2882 struct rtadv_prefix
*rp
;
2884 rtadv
= &zif
->rtadv
;
2886 while ((rp
= rtadv_prefixes_pop(rtadv
->prefixes
)))
2887 rtadv_prefix_free(rp
);
2889 list_delete(&rtadv
->AdvRDNSSList
);
2890 list_delete(&rtadv
->AdvDNSSLList
);
2893 void rtadv_vrf_init(struct zebra_vrf
*zvrf
)
2895 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2898 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2901 void rtadv_vrf_terminate(struct zebra_vrf
*zvrf
)
2903 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2906 rtadv_event(zvrf
, RTADV_STOP
, 0);
2907 if (zvrf
->rtadv
.sock
>= 0) {
2908 close(zvrf
->rtadv
.sock
);
2909 zvrf
->rtadv
.sock
= -1;
2913 adv_msec_if_clean(zvrf
);
2916 void rtadv_cmd_init(void)
2918 interfaces_configured_for_ra_from_bgp
= 0;
2920 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2921 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2923 install_element(VIEW_NODE
, &show_ipv6_nd_ra_if_cmd
);
2925 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2926 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2927 install_element(INTERFACE_NODE
, &ipv6_nd_ra_retrans_interval_cmd
);
2928 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_retrans_interval_cmd
);
2929 install_element(INTERFACE_NODE
, &ipv6_nd_ra_hop_limit_cmd
);
2930 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_hop_limit_cmd
);
2931 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2932 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2933 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2934 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2935 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2936 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2937 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2938 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2939 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2940 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2941 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2942 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2943 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2944 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2945 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2946 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2947 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2948 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2949 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2950 install_element(INTERFACE_NODE
,
2951 &ipv6_nd_adv_interval_config_option_cmd
);
2952 install_element(INTERFACE_NODE
,
2953 &no_ipv6_nd_adv_interval_config_option_cmd
);
2954 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2955 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2956 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2957 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2958 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2959 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2960 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2961 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2962 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2963 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2966 static int if_join_all_router(int sock
, struct interface
*ifp
)
2970 struct ipv6_mreq mreq
;
2972 memset(&mreq
, 0, sizeof(mreq
));
2973 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2974 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2976 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2979 flog_err_sys(EC_LIB_SOCKET
,
2980 "%s(%u): Failed to join group, socket %u error %s",
2981 ifp
->name
, ifp
->ifindex
, sock
,
2982 safe_strerror(errno
));
2984 if (IS_ZEBRA_DEBUG_EVENT
)
2986 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2987 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
2992 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2996 struct ipv6_mreq mreq
;
2998 memset(&mreq
, 0, sizeof(mreq
));
2999 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
3000 mreq
.ipv6mr_interface
= ifp
->ifindex
;
3002 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
3007 "%s(%s:%u): Failed to leave group, socket %u error %s",
3008 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
,
3009 safe_strerror(errno
));
3011 if (IS_ZEBRA_DEBUG_EVENT
)
3013 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
3014 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
3019 bool rtadv_compiled_in(void)
3024 #else /* !HAVE_RTADV */
3026 * If the end user does not have RADV enabled we should
3027 * handle this better
3029 void zebra_interface_radv_disable(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 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
3041 if (IS_ZEBRA_DEBUG_PACKET
)
3043 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3044 zserv_command_string(hdr
->command
));
3049 bool rtadv_compiled_in(void)
3054 #endif /* HAVE_RTADV */
3056 uint32_t rtadv_get_interfaces_configured_from_bgp(void)
3058 return interfaces_configured_for_ra_from_bgp
;