1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Router advertisement
3 * Copyright (C) 2016 Cumulus Networks
4 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
5 * Copyright (C) 1999 Kunihiro Ishiguro
22 #include "lib_errors.h"
24 #include "zebra/interface.h"
25 #include "zebra/rtadv.h"
26 #include "zebra/debug.h"
27 #include "zebra/rib.h"
28 #include "zebra/zapi_msg.h"
29 #include "zebra/zebra_vrf.h"
30 #include "zebra/zebra_errors.h"
31 #include "zebra/zebra_router.h"
33 extern struct zebra_privs_t zserv_privs
;
35 static uint32_t interfaces_configured_for_ra_from_bgp
;
37 #if defined(HAVE_RTADV)
39 #include "zebra/rtadv_clippy.c"
41 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_PREFIX
, "Router Advertisement Prefix");
42 DEFINE_MTYPE_STATIC(ZEBRA
, ADV_IF
, "Advertised Interface");
45 #include <netinet/icmp6.h>
48 /* If RFC2133 definition is used. */
49 #ifndef IPV6_JOIN_GROUP
50 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
52 #ifndef IPV6_LEAVE_GROUP
53 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
56 #define ALLNODE "ff02::1"
57 #define ALLROUTER "ff02::2"
61 char name
[INTERFACE_NAMSIZ
];
62 struct adv_if_list_item list_item
;
65 static int adv_if_cmp(const struct adv_if
*a
, const struct adv_if
*b
)
67 return if_cmp_name_func(a
->name
, b
->name
);
70 DECLARE_SORTLIST_UNIQ(adv_if_list
, struct adv_if
, list_item
, adv_if_cmp
);
72 static int rtadv_prefix_cmp(const struct rtadv_prefix
*a
,
73 const struct rtadv_prefix
*b
)
75 return prefix_cmp(&a
->prefix
, &b
->prefix
);
78 DECLARE_RBTREE_UNIQ(rtadv_prefixes
, struct rtadv_prefix
, item
,
81 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS");
82 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL");
84 /* Order is intentional. Matches RFC4191. This array is also used for
85 command matching, so only modify with care. */
86 static const char *const rtadv_pref_strs
[] = {
87 "medium", "high", "INVALID", "low", 0
98 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
100 static int if_join_all_router(int, struct interface
*);
101 static int if_leave_all_router(int, struct interface
*);
103 static struct zebra_vrf
*rtadv_interface_get_zvrf(const struct interface
*ifp
)
105 /* We use the default vrf for rtadv handling except in netns */
106 if (!vrf_is_backend_netns())
107 return vrf_info_lookup(VRF_DEFAULT
);
109 return ifp
->vrf
->info
;
112 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
115 struct interface
*iface
;
116 struct zebra_if
*zif
;
118 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
119 if (iface
&& iface
->info
) {
127 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
128 int buflen
, struct sockaddr_in6
*from
,
129 ifindex_t
*ifindex
, int *hoplimit
)
134 struct cmsghdr
*cmsgptr
;
139 /* Fill in message and iovec. */
140 memset(&msg
, 0, sizeof(msg
));
141 msg
.msg_name
= (void *)from
;
142 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
145 msg
.msg_control
= (void *)adata
;
146 msg
.msg_controllen
= sizeof(adata
);
148 iov
.iov_len
= buflen
;
150 /* If recvmsg fail return minus value. */
151 ret
= recvmsg(sock
, &msg
, 0);
155 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
156 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
157 /* I want interface index which this packet comes from. */
158 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
159 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
160 struct in6_pktinfo
*ptr
;
162 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
163 *ifindex
= ptr
->ipi6_ifindex
;
164 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
167 /* Incoming packet's hop limit. */
168 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
169 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
170 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
175 rtadv_increment_received(zvrf
, ifindex
);
179 #define RTADV_MSG_SIZE 4096
181 /* Send router advertisement packet. */
182 static void rtadv_send_packet(int sock
, struct interface
*ifp
,
183 enum ipv6_nd_suppress_ra_status stop
)
187 struct cmsghdr
*cmsgptr
;
188 struct in6_pktinfo
*pkt
;
189 struct sockaddr_in6 addr
;
190 static void *adata
= NULL
;
191 unsigned char buf
[RTADV_MSG_SIZE
];
192 struct nd_router_advert
*rtadv
;
195 struct zebra_if
*zif
;
196 struct rtadv_prefix
*rprefix
;
197 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
198 0, 0, 0, 0, 0, 0, 0, 1};
199 struct listnode
*node
;
200 uint16_t pkt_RouterLifetime
;
203 * Allocate control message bufffer. This is dynamic because
204 * CMSG_SPACE is not guaranteed not to call a function. Note that
205 * the size will be different on different architectures due to
206 * differing alignment rules.
209 /* XXX Free on shutdown. */
210 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
213 zlog_debug("%s: can't malloc control data", __func__
);
218 /* Logging of packet. */
219 if (IS_ZEBRA_DEBUG_PACKET
)
220 zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp
->name
,
221 ifp
->vrf
->name
, ifp
->ifindex
, sock
);
223 /* Fill in sockaddr_in6. */
224 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
225 addr
.sin6_family
= AF_INET6
;
227 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
228 #endif /* SIN6_LEN */
229 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
230 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
232 /* Fetch interface information. */
235 /* Make router advertisement message. */
236 rtadv
= (struct nd_router_advert
*)buf
;
238 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
239 rtadv
->nd_ra_code
= 0;
240 rtadv
->nd_ra_cksum
= 0;
242 rtadv
->nd_ra_curhoplimit
= zif
->rtadv
.AdvCurHopLimit
;
244 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
245 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
247 : zif
->rtadv
.DefaultPreference
;
248 rtadv
->nd_ra_flags_reserved
<<= 3;
250 if (zif
->rtadv
.AdvManagedFlag
)
251 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
252 if (zif
->rtadv
.AdvOtherConfigFlag
)
253 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
254 if (zif
->rtadv
.AdvHomeAgentFlag
)
255 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
256 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
257 * AdvDefaultLifetime is by default based on the value of
258 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
259 * field of Router Advertisements. Given that this field is expressed
260 * in seconds, a small MaxRtrAdvInterval value can result in a zero
261 * value for this field. To prevent this, routers SHOULD keep
262 * AdvDefaultLifetime in at least one second, even if the use of
263 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
265 zif
->rtadv
.AdvDefaultLifetime
!= -1
266 ? zif
->rtadv
.AdvDefaultLifetime
267 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
269 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
270 rtadv
->nd_ra_router_lifetime
=
271 (stop
== RA_SUPPRESS
) ? htons(0) : htons(pkt_RouterLifetime
);
272 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
273 rtadv
->nd_ra_retransmit
= htonl(zif
->rtadv
.AdvRetransTimer
);
275 len
= sizeof(struct nd_router_advert
);
277 /* If both the Home Agent Preference and Home Agent Lifetime are set to
278 * their default values specified above, this option SHOULD NOT be
279 * included in the Router Advertisement messages sent by this home
280 * agent. -- RFC6275, 7.4 */
281 if (zif
->rtadv
.AdvHomeAgentFlag
282 && (zif
->rtadv
.HomeAgentPreference
283 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
284 struct nd_opt_homeagent_info
*ndopt_hai
=
285 (struct nd_opt_homeagent_info
*)(buf
+ len
);
286 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
287 ndopt_hai
->nd_opt_hai_len
= 1;
288 ndopt_hai
->nd_opt_hai_reserved
= 0;
289 ndopt_hai
->nd_opt_hai_preference
=
290 htons(zif
->rtadv
.HomeAgentPreference
);
291 /* 16-bit unsigned integer. The lifetime associated with the
293 * agent in units of seconds. The default value is the same as
295 * Router Lifetime, as specified in the main body of the Router
296 * Advertisement. The maximum value corresponds to 18.2 hours.
298 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
299 ndopt_hai
->nd_opt_hai_lifetime
=
300 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
301 ? zif
->rtadv
.HomeAgentLifetime
302 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
307 len
+= sizeof(struct nd_opt_homeagent_info
);
310 if (zif
->rtadv
.AdvIntervalOption
) {
311 struct nd_opt_adv_interval
*ndopt_adv
=
312 (struct nd_opt_adv_interval
*)(buf
+ len
);
313 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
314 ndopt_adv
->nd_opt_ai_len
= 1;
315 ndopt_adv
->nd_opt_ai_reserved
= 0;
316 ndopt_adv
->nd_opt_ai_interval
=
317 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
318 len
+= sizeof(struct nd_opt_adv_interval
);
321 /* Fill in prefix. */
322 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
323 struct nd_opt_prefix_info
*pinfo
;
325 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
327 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
328 pinfo
->nd_opt_pi_len
= 4;
329 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
331 pinfo
->nd_opt_pi_flags_reserved
= 0;
332 if (rprefix
->AdvOnLinkFlag
)
333 pinfo
->nd_opt_pi_flags_reserved
|=
334 ND_OPT_PI_FLAG_ONLINK
;
335 if (rprefix
->AdvAutonomousFlag
)
336 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
337 if (rprefix
->AdvRouterAddressFlag
)
338 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
340 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
341 pinfo
->nd_opt_pi_preferred_time
=
342 htonl(rprefix
->AdvPreferredLifetime
);
343 pinfo
->nd_opt_pi_reserved2
= 0;
345 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
346 &rprefix
->prefix
.prefix
);
348 len
+= sizeof(struct nd_opt_prefix_info
);
351 /* Hardware address. */
352 if (ifp
->hw_addr_len
!= 0) {
353 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
355 /* Option length should be rounded up to next octet if
356 the link address does not end on an octet boundary. */
357 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
359 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
360 len
+= ifp
->hw_addr_len
;
362 /* Pad option to end on an octet boundary. */
363 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
364 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
368 if (zif
->rtadv
.AdvLinkMTU
) {
369 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
370 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
371 opt
->nd_opt_mtu_len
= 1;
372 opt
->nd_opt_mtu_reserved
= 0;
373 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
374 len
+= sizeof(struct nd_opt_mtu
);
378 * There is no limit on the number of configurable recursive DNS
379 * servers or search list entries. We don't want the RA message
380 * to exceed the link's MTU (risking fragmentation) or even
381 * blow the stack buffer allocated for it.
383 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
385 /* Recursive DNS servers */
386 struct rtadv_rdnss
*rdnss
;
388 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
390 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
392 if (len
+ opt_len
> max_len
) {
394 "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
395 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
);
398 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
400 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
401 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
402 opt
->nd_opt_rdnss_reserved
= 0;
403 opt
->nd_opt_rdnss_lifetime
= htonl(
406 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
408 len
+= sizeof(struct nd_opt_rdnss
);
410 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
411 len
+= sizeof(struct in6_addr
);
414 /* DNS search list */
415 struct rtadv_dnssl
*dnssl
;
417 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
418 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
419 + ((dnssl
->encoded_len
+ 7) & ~7);
421 if (len
+ opt_len
> max_len
) {
423 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
424 ifp
->name
, ifp
->ifindex
);
427 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
429 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
430 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
431 opt
->nd_opt_dnssl_reserved
= 0;
432 opt
->nd_opt_dnssl_lifetime
= htonl(
435 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
437 len
+= sizeof(struct nd_opt_dnssl
);
439 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
440 len
+= dnssl
->encoded_len
;
442 /* Zero-pad to 8-octet boundary */
449 msg
.msg_name
= (void *)&addr
;
450 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
453 msg
.msg_control
= (void *)adata
;
454 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
459 cmsgptr
= CMSG_FIRSTHDR(&msg
);
460 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
461 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
462 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
464 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
465 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
466 pkt
->ipi6_ifindex
= ifp
->ifindex
;
468 ret
= sendmsg(sock
, &msg
, 0);
470 flog_err_sys(EC_LIB_SOCKET
,
471 "%s(%u): Tx RA failed, socket %u error %d (%s)",
472 ifp
->name
, ifp
->ifindex
, sock
, errno
,
473 safe_strerror(errno
));
478 static void rtadv_timer(struct event
*thread
)
480 struct zebra_vrf
*zvrf
= EVENT_ARG(thread
);
482 struct interface
*ifp
;
483 struct zebra_if
*zif
;
486 zvrf
->rtadv
.ra_timer
= NULL
;
487 if (adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
) == 0) {
488 period
= 1000; /* 1 s */
489 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
491 period
= 10; /* 10 ms */
492 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
495 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
496 FOR_ALL_INTERFACES (vrf
, ifp
) {
497 if (if_is_loopback(ifp
) || !if_is_operative(ifp
) ||
498 IS_ZEBRA_IF_BRIDGE_SLAVE(ifp
) ||
499 !connected_get_linklocal(ifp
) ||
500 (vrf_is_backend_netns() &&
501 ifp
->vrf
->vrf_id
!= zvrf
->vrf
->vrf_id
))
506 if (zif
->rtadv
.AdvSendAdvertisements
) {
507 if (zif
->rtadv
.inFastRexmit
508 && zif
->rtadv
.UseFastRexmit
) {
509 /* We assume we fast rexmit every sec so
512 if (--zif
->rtadv
.NumFastReXmitsRemain
514 zif
->rtadv
.inFastRexmit
= 0;
516 if (IS_ZEBRA_DEBUG_SEND
)
518 "Fast RA Rexmit on interface %s(%s:%u)",
523 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
,
526 zif
->rtadv
.AdvIntervalTimer
-= period
;
527 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
529 MaxRtrAdvInterval each
530 time isn't what section
531 6.2.4 of RFC4861 tells to do.
533 zif
->rtadv
.AdvIntervalTimer
=
537 zvrf
->rtadv
.sock
, ifp
,
545 static void rtadv_process_solicit(struct interface
*ifp
)
547 struct zebra_vrf
*zvrf
;
548 struct zebra_if
*zif
;
550 zvrf
= rtadv_interface_get_zvrf(ifp
);
555 * If FastRetransmit is enabled, send the RA immediately.
556 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
557 * (3 seconds) since the last RA was sent, send it now and reset
558 * the timer to start at the max (configured) again.
559 * If not enabled and it is less than 3 seconds since the last
560 * RA packet was sent, set the timer for 3 seconds so the next
561 * one will be sent with a minimum of 3 seconds between RAs.
564 if ((zif
->rtadv
.UseFastRexmit
)
565 || (zif
->rtadv
.AdvIntervalTimer
<=
566 (zif
->rtadv
.MaxRtrAdvInterval
- MIN_DELAY_BETWEEN_RAS
))) {
567 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_ENABLE
);
568 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
570 zif
->rtadv
.AdvIntervalTimer
= MIN_DELAY_BETWEEN_RAS
;
573 static const char *rtadv_optionalhdr2str(uint8_t opt_type
)
576 case ND_OPT_SOURCE_LINKADDR
:
577 return "Optional Source Link Address";
578 case ND_OPT_TARGET_LINKADDR
:
579 return "Optional Target Link Address";
580 case ND_OPT_PREFIX_INFORMATION
:
581 return "Optional Prefix Information";
582 case ND_OPT_REDIRECTED_HEADER
:
583 return "Optional Redirected Header";
585 return "Optional MTU";
586 case ND_OPT_RTR_ADV_INTERVAL
:
587 return "Optional Advertisement Interval";
588 case ND_OPT_HOME_AGENT_INFO
:
589 return "Optional Home Agent Information";
592 return "Unknown Optional Type";
596 * This function processes optional attributes off of
597 * end of a RA packet received. At this point in
598 * time we only care about this in one situation
599 * which is when a interface does not have a LL
600 * v6 address. We still need to be able to install
601 * the mac address for v4 to v6 resolution
603 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
604 struct interface
*ifp
,
605 struct sockaddr_in6
*addr
)
610 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
612 switch(opt_hdr
->nd_opt_type
) {
613 case ND_OPT_SOURCE_LINKADDR
:
614 mac
= (char *)(optional
+2);
615 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
616 &addr
->sin6_addr
, 1);
619 if (IS_ZEBRA_DEBUG_PACKET
)
621 "%s:Received Packet with optional Header type %s(%u) that is being ignored",
623 rtadv_optionalhdr2str(
624 opt_hdr
->nd_opt_type
),
625 opt_hdr
->nd_opt_type
);
629 len
-= 8 * opt_hdr
->nd_opt_len
;
630 optional
+= 8 * opt_hdr
->nd_opt_len
;
634 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
635 struct interface
*ifp
,
636 struct sockaddr_in6
*addr
)
638 struct nd_router_advert
*radvert
;
639 char addr_str
[INET6_ADDRSTRLEN
];
640 struct zebra_if
*zif
;
645 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
647 if (len
< sizeof(struct nd_router_advert
)) {
648 if (IS_ZEBRA_DEBUG_PACKET
)
650 "%s(%s:%u): Rx RA with invalid length %d from %s",
651 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, len
,
656 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
657 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
658 len
- sizeof(struct nd_router_advert
),
660 if (IS_ZEBRA_DEBUG_PACKET
)
662 "%s(%s:%u): Rx RA with non-linklocal source address from %s",
663 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
,
668 radvert
= (struct nd_router_advert
*)msg
;
670 #define SIXHOUR2USEC (int64_t)6 * 60 * 60 * 1000000
672 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
) &&
673 (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
) &&
674 (monotime_since(&zif
->rtadv
.lastadvcurhoplimit
, NULL
) >
676 zif
->rtadv
.lastadvcurhoplimit
.tv_sec
== 0)) {
678 EC_ZEBRA_RA_PARAM_MISMATCH
,
679 "%s(%u): Rx RA - our AdvCurHopLimit (%u) doesn't agree with %s (%u)",
680 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvCurHopLimit
,
681 addr_str
, radvert
->nd_ra_curhoplimit
);
682 monotime(&zif
->rtadv
.lastadvcurhoplimit
);
685 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
) &&
686 !zif
->rtadv
.AdvManagedFlag
&&
687 (monotime_since(&zif
->rtadv
.lastadvmanagedflag
, NULL
) >
689 zif
->rtadv
.lastadvmanagedflag
.tv_sec
== 0)) {
691 EC_ZEBRA_RA_PARAM_MISMATCH
,
692 "%s(%u): Rx RA - our AdvManagedFlag (%u) doesn't agree with %s (%u)",
693 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvManagedFlag
,
695 !!CHECK_FLAG(radvert
->nd_ra_flags_reserved
,
696 ND_RA_FLAG_MANAGED
));
697 monotime(&zif
->rtadv
.lastadvmanagedflag
);
700 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
) &&
701 !zif
->rtadv
.AdvOtherConfigFlag
&&
702 (monotime_since(&zif
->rtadv
.lastadvotherconfigflag
, NULL
) >
704 zif
->rtadv
.lastadvotherconfigflag
.tv_sec
== 0)) {
706 EC_ZEBRA_RA_PARAM_MISMATCH
,
707 "%s(%u): Rx RA - our AdvOtherConfigFlag (%u) doesn't agree with %s (%u)",
708 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvOtherConfigFlag
,
710 !!CHECK_FLAG(radvert
->nd_ra_flags_reserved
,
712 monotime(&zif
->rtadv
.lastadvotherconfigflag
);
715 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
) &&
716 (ntohl(radvert
->nd_ra_reachable
) != zif
->rtadv
.AdvReachableTime
) &&
717 (monotime_since(&zif
->rtadv
.lastadvreachabletime
, NULL
) >
719 zif
->rtadv
.lastadvreachabletime
.tv_sec
== 0)) {
721 EC_ZEBRA_RA_PARAM_MISMATCH
,
722 "%s(%u): Rx RA - our AdvReachableTime (%u) doesn't agree with %s (%u)",
723 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvReachableTime
,
724 addr_str
, ntohl(radvert
->nd_ra_reachable
));
725 monotime(&zif
->rtadv
.lastadvreachabletime
);
728 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
) &&
729 (ntohl(radvert
->nd_ra_retransmit
) !=
730 (unsigned int)zif
->rtadv
.AdvRetransTimer
) &&
731 (monotime_since(&zif
->rtadv
.lastadvretranstimer
, NULL
) >
733 zif
->rtadv
.lastadvretranstimer
.tv_sec
== 0)) {
735 EC_ZEBRA_RA_PARAM_MISMATCH
,
736 "%s(%u): Rx RA - our AdvRetransTimer (%u) doesn't agree with %s (%u)",
737 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvRetransTimer
,
738 addr_str
, ntohl(radvert
->nd_ra_retransmit
));
739 monotime(&zif
->rtadv
.lastadvretranstimer
);
742 /* Create entry for neighbor if not known. */
744 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
745 p
.prefixlen
= IPV6_MAX_BITLEN
;
747 if (!nbr_connected_check(ifp
, &p
))
748 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
752 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
753 ifindex_t ifindex
, int hoplimit
,
754 struct sockaddr_in6
*from
,
755 struct zebra_vrf
*zvrf
)
757 struct icmp6_hdr
*icmph
;
758 struct interface
*ifp
;
759 struct zebra_if
*zif
;
760 char addr_str
[INET6_ADDRSTRLEN
];
762 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
764 /* Interface search. */
765 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
767 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
768 "RA/RS received on unknown IF %u from %s", ifindex
,
773 if (IS_ZEBRA_DEBUG_PACKET
)
774 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp
->name
,
775 ifp
->vrf
->name
, ifp
->ifindex
, len
, addr_str
);
777 if (if_is_loopback(ifp
))
780 /* Check interface configuration. */
782 if (!zif
->rtadv
.AdvSendAdvertisements
)
785 /* ICMP message length check. */
786 if (len
< sizeof(struct icmp6_hdr
)) {
788 "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
789 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, len
);
793 icmph
= (struct icmp6_hdr
*)buf
;
795 /* ICMP message type check. */
796 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
797 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
798 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
799 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
,
804 /* Hoplimit check. */
805 if (hoplimit
>= 0 && hoplimit
!= 255) {
806 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
807 ifp
->vrf
->name
, ifp
->ifindex
, hoplimit
);
811 /* Check ICMP message type. */
812 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
813 rtadv_process_solicit(ifp
);
814 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
815 rtadv_process_advert(buf
, len
, ifp
, from
);
820 static void rtadv_read(struct event
*thread
)
824 uint8_t buf
[RTADV_MSG_SIZE
];
825 struct sockaddr_in6 from
;
826 ifindex_t ifindex
= 0;
828 struct zebra_vrf
*zvrf
= EVENT_ARG(thread
);
830 sock
= EVENT_FD(thread
);
831 zvrf
->rtadv
.ra_read
= NULL
;
833 /* Register myself. */
834 rtadv_event(zvrf
, RTADV_READ
, 0);
836 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
840 flog_err_sys(EC_LIB_SOCKET
,
841 "RA/RS recv failed, socket %u error %s", sock
,
842 safe_strerror(errno
));
846 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
849 static int rtadv_make_socket(ns_id_t ns_id
)
853 struct icmp6_filter filter
;
856 frr_with_privs(&zserv_privs
) {
858 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
860 * with privs might set errno too if it fails save
867 zlog_warn("RTADV socket for ns: %u failure to create: %s(%u)",
868 ns_id
, safe_strerror(error
), error
);
872 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
874 zlog_warn("RTADV failure to set Packet Information");
878 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
880 zlog_warn("RTADV failure to set multicast Loop detection");
884 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
886 zlog_warn("RTADV failure to set maximum unicast hops");
890 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
892 zlog_warn("RTADV failure to set maximum multicast hops");
896 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
898 zlog_warn("RTADV failure to set maximum incoming hop limit");
903 ICMP6_FILTER_SETBLOCKALL(&filter
);
904 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
905 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
907 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
908 sizeof(struct icmp6_filter
));
910 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
918 static struct adv_if
*adv_if_new(const char *name
)
922 new = XCALLOC(MTYPE_ADV_IF
, sizeof(struct adv_if
));
924 strlcpy(new->name
, name
, sizeof(new->name
));
929 static void adv_if_free(struct adv_if
*adv_if
)
931 XFREE(MTYPE_ADV_IF
, adv_if
);
934 static bool adv_if_is_empty_internal(const struct adv_if_list_head
*adv_if_head
)
936 return adv_if_list_count(adv_if_head
) ? false : true;
939 static struct adv_if
*adv_if_add_internal(struct adv_if_list_head
*adv_if_head
,
942 struct adv_if adv_if_lookup
= {};
943 struct adv_if
*adv_if
= NULL
;
945 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
946 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
951 adv_if
= adv_if_new(adv_if_lookup
.name
);
952 adv_if_list_add(adv_if_head
, adv_if
);
957 static struct adv_if
*adv_if_del_internal(struct adv_if_list_head
*adv_if_head
,
960 struct adv_if adv_if_lookup
= {};
961 struct adv_if
*adv_if
= NULL
;
963 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
964 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
969 adv_if_list_del(adv_if_head
, adv_if
);
974 static void adv_if_clean_internal(struct adv_if_list_head
*adv_if_head
)
976 struct adv_if
*node
= NULL
;
978 if (!adv_if_is_empty_internal(adv_if_head
)) {
979 frr_each_safe (adv_if_list
, adv_if_head
, node
) {
980 adv_if_list_del(adv_if_head
, node
);
985 adv_if_list_fini(adv_if_head
);
990 * Add to list. On Success, return NULL, otherwise return already existing
993 static struct adv_if
*adv_if_add(struct zebra_vrf
*zvrf
, const char *name
)
995 struct adv_if
*adv_if
= NULL
;
997 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_if
, name
);
1002 if (IS_ZEBRA_DEBUG_EVENT
) {
1003 struct vrf
*vrf
= zvrf
->vrf
;
1005 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1006 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1007 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1014 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1017 static struct adv_if
*adv_if_del(struct zebra_vrf
*zvrf
, const char *name
)
1019 struct adv_if
*adv_if
= NULL
;
1021 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_if
, name
);
1026 if (IS_ZEBRA_DEBUG_EVENT
) {
1027 struct vrf
*vrf
= zvrf
->vrf
;
1029 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1030 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1031 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1038 * Add to list. On Success, return NULL, otherwise return already existing
1041 static struct adv_if
*adv_msec_if_add(struct zebra_vrf
*zvrf
, const char *name
)
1043 struct adv_if
*adv_if
= NULL
;
1045 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1050 if (IS_ZEBRA_DEBUG_EVENT
) {
1051 struct vrf
*vrf
= zvrf
->vrf
;
1053 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1054 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1055 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1062 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1065 static struct adv_if
*adv_msec_if_del(struct zebra_vrf
*zvrf
, const char *name
)
1067 struct adv_if
*adv_if
= NULL
;
1069 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1074 if (IS_ZEBRA_DEBUG_EVENT
) {
1075 struct vrf
*vrf
= zvrf
->vrf
;
1077 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1078 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1079 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1085 /* Clean adv_if list, called on vrf terminate */
1086 static void adv_if_clean(struct zebra_vrf
*zvrf
)
1088 if (IS_ZEBRA_DEBUG_EVENT
) {
1089 struct vrf
*vrf
= zvrf
->vrf
;
1091 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1092 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1093 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1096 adv_if_clean_internal(&zvrf
->rtadv
.adv_if
);
1099 /* Clean adv_msec_if list, called on vrf terminate */
1100 static void adv_msec_if_clean(struct zebra_vrf
*zvrf
)
1102 if (IS_ZEBRA_DEBUG_EVENT
) {
1103 struct vrf
*vrf
= zvrf
->vrf
;
1105 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1106 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1107 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1110 adv_if_clean_internal(&zvrf
->rtadv
.adv_msec_if
);
1113 static struct rtadv_prefix
*rtadv_prefix_new(void)
1115 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
1118 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
1120 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
1123 static struct rtadv_prefix
*rtadv_prefix_get(struct rtadv_prefixes_head
*list
,
1124 struct prefix_ipv6
*p
)
1126 struct rtadv_prefix
*rprefix
, ref
;
1130 rprefix
= rtadv_prefixes_find(list
, &ref
);
1134 rprefix
= rtadv_prefix_new();
1135 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
1136 rtadv_prefixes_add(list
, rprefix
);
1141 static void rtadv_prefix_set_defaults(struct rtadv_prefix
*rp
)
1143 rp
->AdvAutonomousFlag
= 1;
1144 rp
->AdvOnLinkFlag
= 1;
1145 rp
->AdvRouterAddressFlag
= 0;
1146 rp
->AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1147 rp
->AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1150 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1152 struct rtadv_prefix
*rprefix
;
1154 rprefix
= rtadv_prefix_get(zif
->rtadv
.prefixes
, &rp
->prefix
);
1157 * Set parameters based on where the prefix is created.
1158 * If auto-created based on kernel address addition, set the
1159 * default values. If created from a manual "ipv6 nd prefix"
1160 * command, take the parameters from the manual command. Note
1161 * that if the manual command exists, the default values will
1162 * not overwrite the manual values.
1164 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1165 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_AUTO
)
1166 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1168 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1170 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
1171 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
1172 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
1173 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
1174 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
1175 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1176 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
1177 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1179 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1180 rtadv_prefix_set_defaults(rprefix
);
1185 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1187 struct rtadv_prefix
*rprefix
;
1189 rprefix
= rtadv_prefixes_find(zif
->rtadv
.prefixes
, rp
);
1190 if (rprefix
!= NULL
) {
1193 * When deleting an address from the list, need to take care
1194 * it wasn't defined both automatically via kernel
1195 * address addition as well as manually by vtysh cli. If both,
1196 * we don't actually delete but may change the parameters
1197 * back to default if a manually defined entry is deleted.
1199 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1200 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1201 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1202 rtadv_prefix_set_defaults(rprefix
);
1205 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1206 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1207 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1212 rtadv_prefixes_del(zif
->rtadv
.prefixes
, rprefix
);
1213 rtadv_prefix_free(rprefix
);
1219 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
1220 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
1222 struct rtadv_prefix rp
;
1225 apply_mask_ipv6(&rp
.prefix
);
1226 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1227 rtadv_prefix_set(zif
, &rp
);
1230 /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
1231 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
1233 struct rtadv_prefix rp
;
1235 rp
.prefix
= *((struct prefix_ipv6
*)p
);
1236 apply_mask_ipv6(&rp
.prefix
);
1237 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1238 rtadv_prefix_reset(zif
, &rp
);
1241 static void rtadv_start_interface_events(struct zebra_vrf
*zvrf
,
1242 struct zebra_if
*zif
)
1244 struct adv_if
*adv_if
= NULL
;
1246 if (zif
->ifp
->ifindex
== IFINDEX_INTERNAL
) {
1247 if (IS_ZEBRA_DEBUG_EVENT
)
1249 "%s(%s) has not configured an ifindex yet, delaying until we have one",
1250 zif
->ifp
->name
, zvrf
->vrf
->name
);
1254 adv_if
= adv_if_add(zvrf
, zif
->ifp
->name
);
1256 return; /* Already added */
1258 if_join_all_router(zvrf
->rtadv
.sock
, zif
->ifp
);
1260 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 1)
1261 rtadv_event(zvrf
, RTADV_START
, 0);
1264 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
1265 enum ipv6_nd_suppress_ra_status status
)
1267 struct zebra_if
*zif
;
1268 struct zebra_vrf
*zvrf
;
1269 struct adv_if
*adv_if
= NULL
;
1273 zvrf
= rtadv_interface_get_zvrf(ifp
);
1275 if (status
== RA_SUPPRESS
) {
1276 /* RA is currently enabled */
1277 if (zif
->rtadv
.AdvSendAdvertisements
) {
1278 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1279 zif
->rtadv
.AdvSendAdvertisements
= 0;
1280 zif
->rtadv
.AdvIntervalTimer
= 0;
1282 adv_if
= adv_if_del(zvrf
, ifp
->name
);
1284 return; /* Nothing to delete */
1286 adv_if_free(adv_if
);
1288 if_leave_all_router(zvrf
->rtadv
.sock
, ifp
);
1290 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 0)
1291 rtadv_event(zvrf
, RTADV_STOP
, 0);
1294 if (!zif
->rtadv
.AdvSendAdvertisements
) {
1295 zif
->rtadv
.AdvSendAdvertisements
= 1;
1296 zif
->rtadv
.AdvIntervalTimer
= 0;
1297 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
1298 && zif
->rtadv
.UseFastRexmit
) {
1300 * Enable Fast RA only when RA interval is in
1301 * secs and Fast RA retransmit is enabled
1303 zif
->rtadv
.inFastRexmit
= 1;
1304 zif
->rtadv
.NumFastReXmitsRemain
=
1305 RTADV_NUM_FAST_REXMITS
;
1308 rtadv_start_interface_events(zvrf
, zif
);
1314 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1315 * Note that while the client could request RA on an interface on which the
1316 * operator has not enabled RA, RA won't be disabled upon client request
1317 * if the operator has explicitly enabled RA. The enable request can also
1318 * specify a RA interval (in seconds).
1320 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
1324 struct interface
*ifp
;
1325 struct zebra_if
*zif
;
1326 uint32_t ra_interval
;
1330 /* Get interface index and RA interval. */
1331 STREAM_GETL(s
, ifindex
);
1332 STREAM_GETL(s
, ra_interval
);
1334 if (IS_ZEBRA_DEBUG_EVENT
) {
1335 struct vrf
*vrf
= zvrf
->vrf
;
1337 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1338 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1339 enable
? "enable" : "disable",
1340 zebra_route_string(client
->proto
), ra_interval
);
1343 /* Locate interface and check VRF match. */
1344 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
1346 struct vrf
*vrf
= zvrf
->vrf
;
1348 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
1349 "%s:%u: IF %u RA %s client %s - interface unknown",
1350 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1351 enable
? "enable" : "disable",
1352 zebra_route_string(client
->proto
));
1355 if (vrf_is_backend_netns() && ifp
->vrf
->vrf_id
!= zvrf_id(zvrf
)) {
1357 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1358 ifp
->vrf
->name
, zvrf_id(zvrf
), ifindex
,
1359 enable
? "enable" : "disable",
1360 zebra_route_string(client
->proto
), ifp
->vrf
->vrf_id
);
1366 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1367 interfaces_configured_for_ra_from_bgp
++;
1369 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1370 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1372 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1373 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1374 VTY_RA_INTERVAL_CONFIGURED
))
1375 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1377 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1378 interfaces_configured_for_ra_from_bgp
--;
1380 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1381 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1382 VTY_RA_INTERVAL_CONFIGURED
))
1383 zif
->rtadv
.MaxRtrAdvInterval
=
1384 RTADV_MAX_RTR_ADV_INTERVAL
;
1385 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1386 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1393 * send router lifetime value of zero in RAs on this interface since we're
1394 * ceasing to advertise and want to let our neighbors know.
1395 * RFC 4861 secion 6.2.5
1397 void rtadv_stop_ra(struct interface
*ifp
)
1399 struct zebra_if
*zif
;
1400 struct zebra_vrf
*zvrf
;
1403 zvrf
= rtadv_interface_get_zvrf(ifp
);
1405 if (zif
->rtadv
.AdvSendAdvertisements
)
1406 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1410 * Send router lifetime value of zero in RAs on all interfaces since we're
1411 * ceasing to advertise globally and want to let all of our neighbors know
1412 * RFC 4861 secion 6.2.5
1414 * Delete all ipv6 global prefixes added to the router advertisement prefix
1415 * lists prior to ceasing.
1417 void rtadv_stop_ra_all(void)
1420 struct interface
*ifp
;
1421 struct zebra_if
*zif
;
1422 struct rtadv_prefix
*rprefix
;
1424 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1425 FOR_ALL_INTERFACES (vrf
, ifp
) {
1428 frr_each_safe (rtadv_prefixes
, zif
->rtadv
.prefixes
,
1430 rtadv_prefix_reset(zif
, rprefix
);
1436 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1438 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1440 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1442 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1445 static void show_zvrf_rtadv_adv_if_helper(struct vty
*vty
,
1446 struct adv_if_list_head
*adv_if_head
)
1448 struct adv_if
*node
= NULL
;
1450 if (!adv_if_is_empty_internal(adv_if_head
)) {
1451 frr_each (adv_if_list
, adv_if_head
, node
) {
1452 vty_out(vty
, " %s\n", node
->name
);
1459 static void show_zvrf_rtadv_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
)
1461 vty_out(vty
, "VRF: %s\n", zvrf_name(zvrf
));
1462 vty_out(vty
, " Interfaces:\n");
1463 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_if
);
1465 vty_out(vty
, " Interfaces(msec):\n");
1466 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_msec_if
);
1469 DEFPY(show_ipv6_nd_ra_if
, show_ipv6_nd_ra_if_cmd
,
1470 "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
1472 "Neighbor discovery\n"
1473 "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR
)
1475 struct zebra_vrf
*zvrf
= NULL
;
1477 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1479 "%% VRF subcommand only applicable for netns-based vrfs.\n");
1486 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1487 struct zebra_vrf
*zvrf
;
1493 show_zvrf_rtadv_helper(vty
, zvrf
);
1500 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1502 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1505 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1510 show_zvrf_rtadv_helper(vty
, zvrf
);
1515 DEFUN (ipv6_nd_ra_fast_retrans
,
1516 ipv6_nd_ra_fast_retrans_cmd
,
1517 "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
= true;
1536 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1537 no_ipv6_nd_ra_fast_retrans_cmd
,
1538 "no ipv6 nd ra-fast-retrans",
1540 "Interface IPv6 config commands\n"
1541 "Neighbor discovery\n"
1542 "Fast retransmit of RA packets\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
.UseFastRexmit
= false;
1558 DEFPY (ipv6_nd_ra_hop_limit
,
1559 ipv6_nd_ra_hop_limit_cmd
,
1560 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1561 "Interface IPv6 config commands\n"
1562 "Neighbor discovery\n"
1563 "Advertisement Hop Limit\n"
1564 "Advertisement Hop Limit in hops (default:64)\n")
1566 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1567 struct zebra_if
*zif
= ifp
->info
;
1569 if (if_is_loopback(ifp
)) {
1571 "Cannot configure IPv6 Router Advertisements on this interface\n");
1572 return CMD_WARNING_CONFIG_FAILED
;
1575 zif
->rtadv
.AdvCurHopLimit
= hopcount
;
1580 DEFPY (no_ipv6_nd_ra_hop_limit
,
1581 no_ipv6_nd_ra_hop_limit_cmd
,
1582 "no ipv6 nd ra-hop-limit [(0-255)]",
1584 "Interface IPv6 config commands\n"
1585 "Neighbor discovery\n"
1586 "Advertisement Hop Limit\n"
1587 "Advertisement Hop Limit in hops\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 this interface\n");
1595 return CMD_WARNING_CONFIG_FAILED
;
1598 zif
->rtadv
.AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
1603 DEFPY (ipv6_nd_ra_retrans_interval
,
1604 ipv6_nd_ra_retrans_interval_cmd
,
1605 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1606 "Interface IPv6 config commands\n"
1607 "Neighbor discovery\n"
1608 "Advertisement Retransmit Interval\n"
1609 "Advertisement Retransmit Interval in msec\n")
1611 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1612 struct zebra_if
*zif
= ifp
->info
;
1614 if (if_is_loopback(ifp
)) {
1616 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1617 return CMD_WARNING_CONFIG_FAILED
;
1620 zif
->rtadv
.AdvRetransTimer
= interval
;
1625 DEFPY (no_ipv6_nd_ra_retrans_interval
,
1626 no_ipv6_nd_ra_retrans_interval_cmd
,
1627 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1629 "Interface IPv6 config commands\n"
1630 "Neighbor discovery\n"
1631 "Advertisement Retransmit Interval\n"
1632 "Advertisement Retransmit Interval in msec\n")
1634 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1635 struct zebra_if
*zif
= ifp
->info
;
1637 if (if_is_loopback(ifp
)) {
1639 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1640 return CMD_WARNING_CONFIG_FAILED
;
1643 zif
->rtadv
.AdvRetransTimer
= 0;
1648 DEFUN (ipv6_nd_suppress_ra
,
1649 ipv6_nd_suppress_ra_cmd
,
1650 "ipv6 nd suppress-ra",
1651 "Interface IPv6 config commands\n"
1652 "Neighbor discovery\n"
1653 "Suppress Router Advertisement\n")
1655 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1656 struct zebra_if
*zif
= ifp
->info
;
1658 if (if_is_loopback(ifp
)) {
1660 "Cannot configure IPv6 Router Advertisements on this interface\n");
1661 return CMD_WARNING_CONFIG_FAILED
;
1664 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1665 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1667 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1671 DEFUN (no_ipv6_nd_suppress_ra
,
1672 no_ipv6_nd_suppress_ra_cmd
,
1673 "no ipv6 nd suppress-ra",
1675 "Interface IPv6 config commands\n"
1676 "Neighbor discovery\n"
1677 "Suppress Router Advertisement\n")
1679 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1680 struct zebra_if
*zif
= ifp
->info
;
1682 if (if_is_loopback(ifp
)) {
1684 "Cannot configure IPv6 Router Advertisements on this interface\n");
1685 return CMD_WARNING_CONFIG_FAILED
;
1688 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1689 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1693 DEFUN (ipv6_nd_ra_interval_msec
,
1694 ipv6_nd_ra_interval_msec_cmd
,
1695 "ipv6 nd ra-interval msec (70-1800000)",
1696 "Interface IPv6 config commands\n"
1697 "Neighbor discovery\n"
1698 "Router Advertisement interval\n"
1699 "Router Advertisement interval in milliseconds\n"
1700 "Router Advertisement interval in milliseconds\n")
1703 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1705 struct zebra_if
*zif
= ifp
->info
;
1706 struct zebra_vrf
*zvrf
;
1707 struct adv_if
*adv_if
;
1709 zvrf
= rtadv_interface_get_zvrf(ifp
);
1711 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1712 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1713 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1715 "This ra-interval would conflict with configured ra-lifetime!\n");
1716 return CMD_WARNING_CONFIG_FAILED
;
1719 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1720 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1722 adv_if_free(adv_if
);
1725 if (interval
% 1000)
1726 (void)adv_msec_if_add(zvrf
, ifp
->name
);
1728 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1729 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1730 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1731 zif
->rtadv
.AdvIntervalTimer
= 0;
1736 DEFUN (ipv6_nd_ra_interval
,
1737 ipv6_nd_ra_interval_cmd
,
1738 "ipv6 nd ra-interval (1-1800)",
1739 "Interface IPv6 config commands\n"
1740 "Neighbor discovery\n"
1741 "Router Advertisement interval\n"
1742 "Router Advertisement interval in seconds\n")
1745 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1747 struct zebra_if
*zif
= ifp
->info
;
1748 struct zebra_vrf
*zvrf
;
1749 struct adv_if
*adv_if
;
1751 zvrf
= rtadv_interface_get_zvrf(ifp
);
1753 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1754 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1755 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1757 "This ra-interval would conflict with configured ra-lifetime!\n");
1758 return CMD_WARNING_CONFIG_FAILED
;
1761 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1762 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1764 adv_if_free(adv_if
);
1767 /* convert to milliseconds */
1768 interval
= interval
* 1000;
1770 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1771 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1772 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1773 zif
->rtadv
.AdvIntervalTimer
= 0;
1778 DEFUN (no_ipv6_nd_ra_interval
,
1779 no_ipv6_nd_ra_interval_cmd
,
1780 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1782 "Interface IPv6 config commands\n"
1783 "Neighbor discovery\n"
1784 "Router Advertisement interval\n"
1785 "Router Advertisement interval in seconds\n"
1786 "Specify millisecond router advertisement interval\n"
1787 "Router Advertisement interval in milliseconds\n")
1789 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1790 struct zebra_if
*zif
= ifp
->info
;
1791 struct zebra_vrf
*zvrf
= NULL
;
1792 struct adv_if
*adv_if
;
1794 zvrf
= rtadv_interface_get_zvrf(ifp
);
1796 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1797 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1799 adv_if_free(adv_if
);
1802 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1804 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1805 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1807 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1809 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1810 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1815 DEFUN (ipv6_nd_ra_lifetime
,
1816 ipv6_nd_ra_lifetime_cmd
,
1817 "ipv6 nd ra-lifetime (0-9000)",
1818 "Interface IPv6 config commands\n"
1819 "Neighbor discovery\n"
1821 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1824 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1825 struct zebra_if
*zif
= ifp
->info
;
1828 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1830 /* The value to be placed in the Router Lifetime field
1831 * of Router Advertisements sent from the interface,
1832 * in seconds. MUST be either zero or between
1833 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1834 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1836 "This ra-lifetime would conflict with configured ra-interval\n");
1837 return CMD_WARNING_CONFIG_FAILED
;
1840 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1845 DEFUN (no_ipv6_nd_ra_lifetime
,
1846 no_ipv6_nd_ra_lifetime_cmd
,
1847 "no ipv6 nd ra-lifetime [(0-9000)]",
1849 "Interface IPv6 config commands\n"
1850 "Neighbor discovery\n"
1852 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1854 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1855 struct zebra_if
*zif
= ifp
->info
;
1857 zif
->rtadv
.AdvDefaultLifetime
= -1;
1862 DEFUN (ipv6_nd_reachable_time
,
1863 ipv6_nd_reachable_time_cmd
,
1864 "ipv6 nd reachable-time (1-3600000)",
1865 "Interface IPv6 config commands\n"
1866 "Neighbor discovery\n"
1868 "Reachable time in milliseconds\n")
1871 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1872 struct zebra_if
*zif
= ifp
->info
;
1873 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1877 DEFUN (no_ipv6_nd_reachable_time
,
1878 no_ipv6_nd_reachable_time_cmd
,
1879 "no ipv6 nd reachable-time [(1-3600000)]",
1881 "Interface IPv6 config commands\n"
1882 "Neighbor discovery\n"
1884 "Reachable time in milliseconds\n")
1886 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1887 struct zebra_if
*zif
= ifp
->info
;
1889 zif
->rtadv
.AdvReachableTime
= 0;
1894 DEFUN (ipv6_nd_homeagent_preference
,
1895 ipv6_nd_homeagent_preference_cmd
,
1896 "ipv6 nd home-agent-preference (0-65535)",
1897 "Interface IPv6 config commands\n"
1898 "Neighbor discovery\n"
1899 "Home Agent preference\n"
1900 "preference value (default is 0, least preferred)\n")
1903 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1904 struct zebra_if
*zif
= ifp
->info
;
1905 zif
->rtadv
.HomeAgentPreference
=
1906 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1910 DEFUN (no_ipv6_nd_homeagent_preference
,
1911 no_ipv6_nd_homeagent_preference_cmd
,
1912 "no ipv6 nd home-agent-preference [(0-65535)]",
1914 "Interface IPv6 config commands\n"
1915 "Neighbor discovery\n"
1916 "Home Agent preference\n"
1917 "preference value (default is 0, least preferred)\n")
1919 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1920 struct zebra_if
*zif
= ifp
->info
;
1922 zif
->rtadv
.HomeAgentPreference
= 0;
1927 DEFUN (ipv6_nd_homeagent_lifetime
,
1928 ipv6_nd_homeagent_lifetime_cmd
,
1929 "ipv6 nd home-agent-lifetime (0-65520)",
1930 "Interface IPv6 config commands\n"
1931 "Neighbor discovery\n"
1932 "Home Agent lifetime\n"
1933 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1936 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1937 struct zebra_if
*zif
= ifp
->info
;
1938 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1942 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1943 no_ipv6_nd_homeagent_lifetime_cmd
,
1944 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1946 "Interface IPv6 config commands\n"
1947 "Neighbor discovery\n"
1948 "Home Agent lifetime\n"
1949 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1951 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1952 struct zebra_if
*zif
= ifp
->info
;
1954 zif
->rtadv
.HomeAgentLifetime
= -1;
1959 DEFUN (ipv6_nd_managed_config_flag
,
1960 ipv6_nd_managed_config_flag_cmd
,
1961 "ipv6 nd managed-config-flag",
1962 "Interface IPv6 config commands\n"
1963 "Neighbor discovery\n"
1964 "Managed address configuration flag\n")
1966 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1967 struct zebra_if
*zif
= ifp
->info
;
1969 zif
->rtadv
.AdvManagedFlag
= 1;
1974 DEFUN (no_ipv6_nd_managed_config_flag
,
1975 no_ipv6_nd_managed_config_flag_cmd
,
1976 "no ipv6 nd managed-config-flag",
1978 "Interface IPv6 config commands\n"
1979 "Neighbor discovery\n"
1980 "Managed address configuration flag\n")
1982 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1983 struct zebra_if
*zif
= ifp
->info
;
1985 zif
->rtadv
.AdvManagedFlag
= 0;
1990 DEFUN (ipv6_nd_homeagent_config_flag
,
1991 ipv6_nd_homeagent_config_flag_cmd
,
1992 "ipv6 nd home-agent-config-flag",
1993 "Interface IPv6 config commands\n"
1994 "Neighbor discovery\n"
1995 "Home Agent configuration flag\n")
1997 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1998 struct zebra_if
*zif
= ifp
->info
;
2000 zif
->rtadv
.AdvHomeAgentFlag
= 1;
2005 DEFUN (no_ipv6_nd_homeagent_config_flag
,
2006 no_ipv6_nd_homeagent_config_flag_cmd
,
2007 "no ipv6 nd home-agent-config-flag",
2009 "Interface IPv6 config commands\n"
2010 "Neighbor discovery\n"
2011 "Home Agent configuration flag\n")
2013 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2014 struct zebra_if
*zif
= ifp
->info
;
2016 zif
->rtadv
.AdvHomeAgentFlag
= 0;
2021 DEFUN (ipv6_nd_adv_interval_config_option
,
2022 ipv6_nd_adv_interval_config_option_cmd
,
2023 "ipv6 nd adv-interval-option",
2024 "Interface IPv6 config commands\n"
2025 "Neighbor discovery\n"
2026 "Advertisement Interval Option\n")
2028 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2029 struct zebra_if
*zif
= ifp
->info
;
2031 zif
->rtadv
.AdvIntervalOption
= 1;
2036 DEFUN (no_ipv6_nd_adv_interval_config_option
,
2037 no_ipv6_nd_adv_interval_config_option_cmd
,
2038 "no ipv6 nd adv-interval-option",
2040 "Interface IPv6 config commands\n"
2041 "Neighbor discovery\n"
2042 "Advertisement Interval Option\n")
2044 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2045 struct zebra_if
*zif
= ifp
->info
;
2047 zif
->rtadv
.AdvIntervalOption
= 0;
2052 DEFUN (ipv6_nd_other_config_flag
,
2053 ipv6_nd_other_config_flag_cmd
,
2054 "ipv6 nd other-config-flag",
2055 "Interface IPv6 config commands\n"
2056 "Neighbor discovery\n"
2057 "Other statefull configuration flag\n")
2059 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2060 struct zebra_if
*zif
= ifp
->info
;
2062 zif
->rtadv
.AdvOtherConfigFlag
= 1;
2067 DEFUN (no_ipv6_nd_other_config_flag
,
2068 no_ipv6_nd_other_config_flag_cmd
,
2069 "no ipv6 nd other-config-flag",
2071 "Interface IPv6 config commands\n"
2072 "Neighbor discovery\n"
2073 "Other statefull configuration flag\n")
2075 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2076 struct zebra_if
*zif
= ifp
->info
;
2078 zif
->rtadv
.AdvOtherConfigFlag
= 0;
2083 DEFUN (ipv6_nd_prefix
,
2085 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2086 "Interface IPv6 config commands\n"
2087 "Neighbor discovery\n"
2088 "Prefix information\n"
2090 "Valid lifetime in seconds\n"
2091 "Infinite valid lifetime\n"
2092 "Preferred lifetime in seconds\n"
2093 "Infinite preferred lifetime\n"
2094 "Set Router Address flag\n"
2095 "Do not use prefix for onlink determination\n"
2096 "Do not use prefix for autoconfiguration\n"
2097 "Do not use prefix for autoconfiguration\n"
2098 "Do not use prefix for onlink determination\n")
2101 char *prefix
= argv
[3]->arg
;
2102 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
2103 || strmatch(argv
[4]->text
, "infinite"));
2104 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
2106 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
2108 char *lifetime
= NULL
, *preflifetime
= NULL
;
2109 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
2111 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2113 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
2118 strmatch(argv
[idx_routeropts
]->text
, "router-address");
2120 offlink
= (argc
> idx_routeropts
+ 1
2121 || strmatch(argv
[idx_routeropts
]->text
,
2123 noautoconf
= (argc
> idx_routeropts
+ 1
2124 || strmatch(argv
[idx_routeropts
]->text
,
2130 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2131 struct zebra_if
*zebra_if
= ifp
->info
;
2133 struct rtadv_prefix rp
;
2135 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2137 vty_out(vty
, "Malformed IPv6 prefix\n");
2138 return CMD_WARNING_CONFIG_FAILED
;
2140 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2141 rp
.AdvOnLinkFlag
= !offlink
;
2142 rp
.AdvAutonomousFlag
= !noautoconf
;
2143 rp
.AdvRouterAddressFlag
= routeraddr
;
2144 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
2145 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
2146 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2149 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
2151 : strtoll(lifetime
, NULL
, 10);
2152 rp
.AdvPreferredLifetime
=
2153 strmatch(preflifetime
, "infinite")
2155 : strtoll(preflifetime
, NULL
, 10);
2156 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
2157 vty_out(vty
, "Invalid preferred lifetime\n");
2158 return CMD_WARNING_CONFIG_FAILED
;
2162 rtadv_prefix_set(zebra_if
, &rp
);
2167 DEFUN (no_ipv6_nd_prefix
,
2168 no_ipv6_nd_prefix_cmd
,
2169 "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]>]",
2171 "Interface IPv6 config commands\n"
2172 "Neighbor discovery\n"
2173 "Prefix information\n"
2175 "Valid lifetime in seconds\n"
2176 "Infinite valid lifetime\n"
2177 "Preferred lifetime in seconds\n"
2178 "Infinite preferred lifetime\n"
2179 "Set Router Address flag\n"
2180 "Do not use prefix for onlink determination\n"
2181 "Do not use prefix for autoconfiguration\n"
2182 "Do not use prefix for autoconfiguration\n"
2183 "Do not use prefix for onlink determination\n")
2185 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2186 struct zebra_if
*zebra_if
= ifp
->info
;
2188 struct rtadv_prefix rp
;
2189 char *prefix
= argv
[4]->arg
;
2191 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2193 vty_out(vty
, "Malformed IPv6 prefix\n");
2194 return CMD_WARNING_CONFIG_FAILED
;
2196 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2197 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2199 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
2201 vty_out(vty
, "Non-existant IPv6 prefix\n");
2202 return CMD_WARNING_CONFIG_FAILED
;
2208 DEFUN (ipv6_nd_router_preference
,
2209 ipv6_nd_router_preference_cmd
,
2210 "ipv6 nd router-preference <high|medium|low>",
2211 "Interface IPv6 config commands\n"
2212 "Neighbor discovery\n"
2213 "Default router preference\n"
2214 "High default router preference\n"
2215 "Medium default router preference (default)\n"
2216 "Low default router preference\n")
2218 int idx_high_medium_low
= 3;
2219 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2220 struct zebra_if
*zif
= ifp
->info
;
2223 while (0 != rtadv_pref_strs
[i
]) {
2224 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
2227 zif
->rtadv
.DefaultPreference
= i
;
2233 return CMD_ERR_NO_MATCH
;
2236 DEFUN (no_ipv6_nd_router_preference
,
2237 no_ipv6_nd_router_preference_cmd
,
2238 "no ipv6 nd router-preference [<high|medium|low>]",
2240 "Interface IPv6 config commands\n"
2241 "Neighbor discovery\n"
2242 "Default router preference\n"
2243 "High default router preference\n"
2244 "Medium default router preference (default)\n"
2245 "Low default router preference\n")
2247 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2248 struct zebra_if
*zif
= ifp
->info
;
2250 zif
->rtadv
.DefaultPreference
=
2251 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
2258 "ipv6 nd mtu (1-65535)",
2259 "Interface IPv6 config commands\n"
2260 "Neighbor discovery\n"
2265 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2266 struct zebra_if
*zif
= ifp
->info
;
2267 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2271 DEFUN (no_ipv6_nd_mtu
,
2273 "no ipv6 nd mtu [(1-65535)]",
2275 "Interface IPv6 config commands\n"
2276 "Neighbor discovery\n"
2280 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2281 struct zebra_if
*zif
= ifp
->info
;
2282 zif
->rtadv
.AdvLinkMTU
= 0;
2286 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
2288 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
2291 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
2293 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
2296 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
2297 struct rtadv_rdnss
*rdnss
)
2299 struct listnode
*node
;
2300 struct rtadv_rdnss
*p
;
2302 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2303 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
2308 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
2309 struct rtadv_rdnss
*rdnss
)
2311 struct rtadv_rdnss
*p
;
2313 p
= rtadv_rdnss_lookup(list
, rdnss
);
2317 p
= rtadv_rdnss_new();
2318 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
2319 listnode_add(list
, p
);
2324 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2326 struct rtadv_rdnss
*p
;
2328 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2329 p
->lifetime
= rdnss
->lifetime
;
2330 p
->lifetime_set
= rdnss
->lifetime_set
;
2333 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2335 struct rtadv_rdnss
*p
;
2337 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2339 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
2340 rtadv_rdnss_free(p
);
2347 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
2349 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
2352 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
2354 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
2357 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
2358 struct rtadv_dnssl
*dnssl
)
2360 struct listnode
*node
;
2361 struct rtadv_dnssl
*p
;
2363 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2364 if (!strcasecmp(p
->name
, dnssl
->name
))
2369 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
2370 struct rtadv_dnssl
*dnssl
)
2372 struct rtadv_dnssl
*p
;
2374 p
= rtadv_dnssl_lookup(list
, dnssl
);
2378 p
= rtadv_dnssl_new();
2379 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2380 listnode_add(list
, p
);
2385 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2387 struct rtadv_dnssl
*p
;
2389 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2390 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2393 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2395 struct rtadv_dnssl
*p
;
2397 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2399 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
2400 rtadv_dnssl_free(p
);
2408 * Convert dotted domain name (with or without trailing root zone dot) to
2409 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2410 * to strlen(in) + 2 octets to out.
2412 * Returns the number of octets written to out or -1 if in does not constitute
2413 * a valid domain name.
2415 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
2417 const char *label_start
, *label_end
;
2423 while (*label_start
) {
2426 label_end
= strchr(label_start
, '.');
2427 if (label_end
== NULL
)
2428 label_end
= label_start
+ strlen(label_start
);
2430 label_len
= label_end
- label_start
;
2431 if (label_len
>= 64)
2432 return -1; /* labels must be 63 octets or less */
2434 out
[outp
++] = (uint8_t)label_len
;
2435 memcpy(out
+ outp
, label_start
, label_len
);
2437 label_start
+= label_len
;
2438 if (*label_start
== '.')
2446 DEFUN(ipv6_nd_rdnss
,
2448 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2449 "Interface IPv6 config commands\n"
2450 "Neighbor discovery\n"
2451 "Recursive DNS server information\n"
2453 "Valid lifetime in seconds\n"
2454 "Infinite valid lifetime\n")
2456 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2457 struct zebra_if
*zif
= ifp
->info
;
2458 struct rtadv_rdnss rdnss
= {};
2460 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
2461 vty_out(vty
, "Malformed IPv6 address\n");
2462 return CMD_WARNING_CONFIG_FAILED
;
2465 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2467 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
2469 : strtoll(lifetime
, NULL
, 10);
2470 rdnss
.lifetime_set
= 1;
2473 rtadv_rdnss_set(zif
, &rdnss
);
2478 DEFUN(no_ipv6_nd_rdnss
,
2479 no_ipv6_nd_rdnss_cmd
,
2480 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2482 "Interface IPv6 config commands\n"
2483 "Neighbor discovery\n"
2484 "Recursive DNS server information\n"
2486 "Valid lifetime in seconds\n"
2487 "Infinite valid lifetime\n")
2489 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2490 struct zebra_if
*zif
= ifp
->info
;
2491 struct rtadv_rdnss rdnss
= {};
2493 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
2494 vty_out(vty
, "Malformed IPv6 address\n");
2495 return CMD_WARNING_CONFIG_FAILED
;
2497 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
2498 vty_out(vty
, "Non-existant RDNSS address\n");
2499 return CMD_WARNING_CONFIG_FAILED
;
2505 DEFUN(ipv6_nd_dnssl
,
2507 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2508 "Interface IPv6 config commands\n"
2509 "Neighbor discovery\n"
2510 "DNS search list information\n"
2511 "Domain name suffix\n"
2512 "Valid lifetime in seconds\n"
2513 "Infinite valid lifetime\n")
2515 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2516 struct zebra_if
*zif
= ifp
->info
;
2517 struct rtadv_dnssl dnssl
= {};
2521 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
2522 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2523 vty_out(vty
, "Malformed DNS search domain\n");
2524 return CMD_WARNING_CONFIG_FAILED
;
2526 if (dnssl
.name
[len
- 1] == '.') {
2528 * Allow, but don't require, a trailing dot signifying the root
2529 * zone. Canonicalize by cutting it off if present.
2531 dnssl
.name
[len
- 1] = '\0';
2535 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2537 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
2539 : strtoll(lifetime
, NULL
, 10);
2540 dnssl
.lifetime_set
= 1;
2543 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2545 vty_out(vty
, "Malformed DNS search domain\n");
2546 return CMD_WARNING_CONFIG_FAILED
;
2548 dnssl
.encoded_len
= ret
;
2549 rtadv_dnssl_set(zif
, &dnssl
);
2554 DEFUN(no_ipv6_nd_dnssl
,
2555 no_ipv6_nd_dnssl_cmd
,
2556 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2558 "Interface IPv6 config commands\n"
2559 "Neighbor discovery\n"
2560 "DNS search list information\n"
2561 "Domain name suffix\n"
2562 "Valid lifetime in seconds\n"
2563 "Infinite valid lifetime\n")
2565 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2566 struct zebra_if
*zif
= ifp
->info
;
2567 struct rtadv_dnssl dnssl
= {};
2570 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2571 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2572 vty_out(vty
, "Malformed DNS search domain\n");
2573 return CMD_WARNING_CONFIG_FAILED
;
2575 if (dnssl
.name
[len
- 1] == '.') {
2576 dnssl
.name
[len
- 1] = '\0';
2579 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2580 vty_out(vty
, "Non-existant DNS search domain\n");
2581 return CMD_WARNING_CONFIG_FAILED
;
2588 /* Dump interface ND information to vty. */
2589 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2591 struct zebra_if
*zif
;
2592 struct rtadvconf
*rtadv
;
2595 zif
= (struct zebra_if
*)ifp
->info
;
2596 rtadv
= &zif
->rtadv
;
2598 if (rtadv
->AdvSendAdvertisements
) {
2600 " ND advertised reachable time is %d milliseconds\n",
2601 rtadv
->AdvReachableTime
);
2603 " ND advertised retransmit interval is %u milliseconds\n",
2604 rtadv
->AdvRetransTimer
);
2605 vty_out(vty
, " ND advertised hop-count limit is %d hops\n",
2606 rtadv
->AdvCurHopLimit
);
2607 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2608 zif
->ra_sent
, zif
->ra_rcvd
);
2609 interval
= rtadv
->MaxRtrAdvInterval
;
2610 if (interval
% 1000)
2612 " ND router advertisements are sent every %d milliseconds\n",
2616 " ND router advertisements are sent every %d seconds\n",
2618 if (!rtadv
->UseFastRexmit
)
2620 " ND router advertisements do not use fast retransmit\n");
2622 if (rtadv
->AdvDefaultLifetime
!= -1)
2624 " ND router advertisements live for %d seconds\n",
2625 rtadv
->AdvDefaultLifetime
);
2628 " ND router advertisements lifetime tracks ra-interval\n");
2630 " ND router advertisement default router preference is %s\n",
2631 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2632 if (rtadv
->AdvManagedFlag
)
2634 " Hosts use DHCP to obtain routable addresses.\n");
2637 " Hosts use stateless autoconfig for addresses.\n");
2638 if (rtadv
->AdvHomeAgentFlag
) {
2640 " ND router advertisements with Home Agent flag bit set.\n");
2641 if (rtadv
->HomeAgentLifetime
!= -1)
2643 " Home Agent lifetime is %u seconds\n",
2644 rtadv
->HomeAgentLifetime
);
2647 " Home Agent lifetime tracks ra-lifetime\n");
2648 vty_out(vty
, " Home Agent preference is %u\n",
2649 rtadv
->HomeAgentPreference
);
2651 if (rtadv
->AdvIntervalOption
)
2653 " ND router advertisements with Adv. Interval option.\n");
2659 /* Write configuration about router advertisement. */
2660 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2662 struct zebra_if
*zif
;
2663 struct listnode
*node
;
2664 struct rtadv_prefix
*rprefix
;
2665 struct rtadv_rdnss
*rdnss
;
2666 struct rtadv_dnssl
*dnssl
;
2671 if (!if_is_loopback(ifp
)) {
2672 if (zif
->rtadv
.AdvSendAdvertisements
2673 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2674 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2677 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2678 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2679 if (interval
% 1000)
2680 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2682 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2683 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2687 if (zif
->rtadv
.AdvIntervalOption
)
2688 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2690 if (!zif
->rtadv
.UseFastRexmit
)
2691 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2693 if (zif
->rtadv
.AdvRetransTimer
!= 0)
2694 vty_out(vty
, " ipv6 nd ra-retrans-interval %u\n",
2695 zif
->rtadv
.AdvRetransTimer
);
2697 if (zif
->rtadv
.AdvCurHopLimit
!= RTADV_DEFAULT_HOPLIMIT
)
2698 vty_out(vty
, " ipv6 nd ra-hop-limit %d\n",
2699 zif
->rtadv
.AdvCurHopLimit
);
2701 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2702 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2703 zif
->rtadv
.AdvDefaultLifetime
);
2705 if (zif
->rtadv
.HomeAgentPreference
)
2706 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2707 zif
->rtadv
.HomeAgentPreference
);
2709 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2710 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2711 zif
->rtadv
.HomeAgentLifetime
);
2713 if (zif
->rtadv
.AdvHomeAgentFlag
)
2714 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2716 if (zif
->rtadv
.AdvReachableTime
)
2717 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2718 zif
->rtadv
.AdvReachableTime
);
2720 if (zif
->rtadv
.AdvManagedFlag
)
2721 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2723 if (zif
->rtadv
.AdvOtherConfigFlag
)
2724 vty_out(vty
, " ipv6 nd other-config-flag\n");
2726 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2727 vty_out(vty
, " ipv6 nd router-preference %s\n",
2728 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2730 if (zif
->rtadv
.AdvLinkMTU
)
2731 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2733 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
2734 if ((rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
2735 || (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
)) {
2736 vty_out(vty
, " ipv6 nd prefix %pFX", &rprefix
->prefix
);
2737 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2738 || (rprefix
->AdvPreferredLifetime
2739 != RTADV_PREFERRED_LIFETIME
)) {
2740 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2741 vty_out(vty
, " infinite");
2744 rprefix
->AdvValidLifetime
);
2745 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2746 vty_out(vty
, " infinite");
2749 rprefix
->AdvPreferredLifetime
);
2751 if (!rprefix
->AdvOnLinkFlag
)
2752 vty_out(vty
, " off-link");
2753 if (!rprefix
->AdvAutonomousFlag
)
2754 vty_out(vty
, " no-autoconfig");
2755 if (rprefix
->AdvRouterAddressFlag
)
2756 vty_out(vty
, " router-address");
2761 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2762 char buf
[INET6_ADDRSTRLEN
];
2764 vty_out(vty
, " ipv6 nd rdnss %s",
2765 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2766 if (rdnss
->lifetime_set
) {
2767 if (rdnss
->lifetime
== UINT32_MAX
)
2768 vty_out(vty
, " infinite");
2770 vty_out(vty
, " %u", rdnss
->lifetime
);
2774 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2775 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2776 if (dnssl
->lifetime_set
) {
2777 if (dnssl
->lifetime
== UINT32_MAX
)
2778 vty_out(vty
, " infinite");
2780 vty_out(vty
, " %u", dnssl
->lifetime
);
2788 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2790 struct rtadv
*rtadv
;
2792 if (IS_ZEBRA_DEBUG_EVENT
) {
2793 struct vrf
*vrf
= zvrf
->vrf
;
2795 zlog_debug("%s(%s) with event: %d and val: %d", __func__
,
2796 VRF_LOGNAME(vrf
), event
, val
);
2799 rtadv
= &zvrf
->rtadv
;
2803 event_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2805 event_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2809 EVENT_OFF(rtadv
->ra_timer
);
2810 EVENT_OFF(rtadv
->ra_read
);
2813 event_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2816 case RTADV_TIMER_MSEC
:
2817 event_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2821 event_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2830 void rtadv_if_up(struct zebra_if
*zif
)
2832 struct zebra_vrf
*zvrf
= rtadv_interface_get_zvrf(zif
->ifp
);
2834 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
2835 if (zif
->rtadv
.AdvSendAdvertisements
&&
2836 (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) &&
2837 zif
->rtadv
.UseFastRexmit
) {
2838 zif
->rtadv
.inFastRexmit
= 1;
2839 zif
->rtadv
.NumFastReXmitsRemain
= RTADV_NUM_FAST_REXMITS
;
2843 * startup the state machine, if it hasn't been already
2844 * due to a delayed ifindex on startup ordering
2846 if (zif
->rtadv
.AdvSendAdvertisements
)
2847 rtadv_start_interface_events(zvrf
, zif
);
2850 void rtadv_if_init(struct zebra_if
*zif
)
2852 /* Set default router advertise values. */
2853 struct rtadvconf
*rtadv
;
2855 rtadv
= &zif
->rtadv
;
2857 rtadv
->AdvSendAdvertisements
= 0;
2858 rtadv
->MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
2859 rtadv
->MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
2860 rtadv
->AdvIntervalTimer
= 0;
2861 rtadv
->AdvManagedFlag
= 0;
2862 rtadv
->AdvOtherConfigFlag
= 0;
2863 rtadv
->AdvHomeAgentFlag
= 0;
2864 rtadv
->AdvLinkMTU
= 0;
2865 rtadv
->AdvReachableTime
= 0;
2866 rtadv
->AdvRetransTimer
= 0;
2867 rtadv
->AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
2868 memset(&rtadv
->lastadvcurhoplimit
, 0,
2869 sizeof(rtadv
->lastadvcurhoplimit
));
2870 memset(&rtadv
->lastadvmanagedflag
, 0,
2871 sizeof(rtadv
->lastadvmanagedflag
));
2872 memset(&rtadv
->lastadvotherconfigflag
, 0,
2873 sizeof(rtadv
->lastadvotherconfigflag
));
2874 memset(&rtadv
->lastadvreachabletime
, 0,
2875 sizeof(rtadv
->lastadvreachabletime
));
2876 memset(&rtadv
->lastadvretranstimer
, 0,
2877 sizeof(rtadv
->lastadvretranstimer
));
2878 rtadv
->AdvDefaultLifetime
= -1; /* derive from MaxRtrAdvInterval */
2879 rtadv
->HomeAgentPreference
= 0;
2880 rtadv
->HomeAgentLifetime
= -1; /* derive from AdvDefaultLifetime */
2881 rtadv
->AdvIntervalOption
= 0;
2882 rtadv
->UseFastRexmit
= true;
2883 rtadv
->DefaultPreference
= RTADV_PREF_MEDIUM
;
2885 rtadv_prefixes_init(rtadv
->prefixes
);
2887 rtadv
->AdvRDNSSList
= list_new();
2888 rtadv
->AdvDNSSLList
= list_new();
2891 void rtadv_if_fini(struct zebra_if
*zif
)
2893 struct rtadvconf
*rtadv
;
2894 struct rtadv_prefix
*rp
;
2896 rtadv
= &zif
->rtadv
;
2898 while ((rp
= rtadv_prefixes_pop(rtadv
->prefixes
)))
2899 rtadv_prefix_free(rp
);
2901 list_delete(&rtadv
->AdvRDNSSList
);
2902 list_delete(&rtadv
->AdvDNSSLList
);
2905 void rtadv_vrf_init(struct zebra_vrf
*zvrf
)
2907 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2910 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2913 void rtadv_vrf_terminate(struct zebra_vrf
*zvrf
)
2915 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2918 rtadv_event(zvrf
, RTADV_STOP
, 0);
2919 if (zvrf
->rtadv
.sock
>= 0) {
2920 close(zvrf
->rtadv
.sock
);
2921 zvrf
->rtadv
.sock
= -1;
2925 adv_msec_if_clean(zvrf
);
2928 void rtadv_cmd_init(void)
2930 interfaces_configured_for_ra_from_bgp
= 0;
2932 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2933 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2935 install_element(VIEW_NODE
, &show_ipv6_nd_ra_if_cmd
);
2937 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2938 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2939 install_element(INTERFACE_NODE
, &ipv6_nd_ra_retrans_interval_cmd
);
2940 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_retrans_interval_cmd
);
2941 install_element(INTERFACE_NODE
, &ipv6_nd_ra_hop_limit_cmd
);
2942 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_hop_limit_cmd
);
2943 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2944 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2945 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2946 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2947 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2948 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2949 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2950 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2951 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2952 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2953 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2954 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2955 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2956 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2957 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2958 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2959 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2960 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2961 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2962 install_element(INTERFACE_NODE
,
2963 &ipv6_nd_adv_interval_config_option_cmd
);
2964 install_element(INTERFACE_NODE
,
2965 &no_ipv6_nd_adv_interval_config_option_cmd
);
2966 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2967 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2968 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2969 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2970 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2971 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2972 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2973 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2974 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2975 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2978 static int if_join_all_router(int sock
, struct interface
*ifp
)
2982 struct ipv6_mreq mreq
;
2984 memset(&mreq
, 0, sizeof(mreq
));
2985 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2986 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2988 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2991 flog_err_sys(EC_LIB_SOCKET
,
2992 "%s(%u): Failed to join group, socket %u error %s",
2993 ifp
->name
, ifp
->ifindex
, sock
,
2994 safe_strerror(errno
));
2996 if (IS_ZEBRA_DEBUG_EVENT
)
2998 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2999 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
3004 static int if_leave_all_router(int sock
, struct interface
*ifp
)
3008 struct ipv6_mreq mreq
;
3010 memset(&mreq
, 0, sizeof(mreq
));
3011 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
3012 mreq
.ipv6mr_interface
= ifp
->ifindex
;
3014 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
3019 "%s(%s:%u): Failed to leave group, socket %u error %s",
3020 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
,
3021 safe_strerror(errno
));
3023 if (IS_ZEBRA_DEBUG_EVENT
)
3025 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
3026 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
3031 bool rtadv_compiled_in(void)
3036 #else /* !HAVE_RTADV */
3038 * If the end user does not have RADV enabled we should
3039 * handle this better
3041 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
3043 if (IS_ZEBRA_DEBUG_PACKET
)
3045 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3046 zserv_command_string(hdr
->command
));
3051 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
3053 if (IS_ZEBRA_DEBUG_PACKET
)
3055 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3056 zserv_command_string(hdr
->command
));
3061 bool rtadv_compiled_in(void)
3066 #endif /* HAVE_RTADV */
3068 uint32_t rtadv_get_interfaces_configured_from_bgp(void)
3070 return interfaces_configured_for_ra_from_bgp
;