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 #include "zebra/rtadv_clippy.c"
56 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_PREFIX
, "Router Advertisement Prefix");
57 DEFINE_MTYPE_STATIC(ZEBRA
, ADV_IF
, "Advertised Interface");
60 #include <netinet/icmp6.h>
63 /* If RFC2133 definition is used. */
64 #ifndef IPV6_JOIN_GROUP
65 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
67 #ifndef IPV6_LEAVE_GROUP
68 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
71 #define ALLNODE "ff02::1"
72 #define ALLROUTER "ff02::2"
76 char name
[INTERFACE_NAMSIZ
];
77 struct adv_if_list_item list_item
;
80 static int adv_if_cmp(const struct adv_if
*a
, const struct adv_if
*b
)
82 return if_cmp_name_func(a
->name
, b
->name
);
85 DECLARE_SORTLIST_UNIQ(adv_if_list
, struct adv_if
, list_item
, adv_if_cmp
);
87 static int rtadv_prefix_cmp(const struct rtadv_prefix
*a
,
88 const struct rtadv_prefix
*b
)
90 return prefix_cmp(&a
->prefix
, &b
->prefix
);
93 DECLARE_RBTREE_UNIQ(rtadv_prefixes
, struct rtadv_prefix
, item
,
96 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS");
97 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL");
99 /* Order is intentional. Matches RFC4191. This array is also used for
100 command matching, so only modify with care. */
101 static const char *const rtadv_pref_strs
[] = {
102 "medium", "high", "INVALID", "low", 0
113 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
115 static int if_join_all_router(int, struct interface
*);
116 static int if_leave_all_router(int, struct interface
*);
118 static struct zebra_vrf
*rtadv_interface_get_zvrf(const struct interface
*ifp
)
120 /* We use the default vrf for rtadv handling except in netns */
121 if (!vrf_is_backend_netns())
122 return vrf_info_lookup(VRF_DEFAULT
);
124 return ifp
->vrf
->info
;
127 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
130 struct interface
*iface
;
131 struct zebra_if
*zif
;
133 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
134 if (iface
&& iface
->info
) {
142 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
143 int buflen
, struct sockaddr_in6
*from
,
144 ifindex_t
*ifindex
, int *hoplimit
)
149 struct cmsghdr
*cmsgptr
;
154 /* Fill in message and iovec. */
155 memset(&msg
, 0, sizeof(msg
));
156 msg
.msg_name
= (void *)from
;
157 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
160 msg
.msg_control
= (void *)adata
;
161 msg
.msg_controllen
= sizeof(adata
);
163 iov
.iov_len
= buflen
;
165 /* If recvmsg fail return minus value. */
166 ret
= recvmsg(sock
, &msg
, 0);
170 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
171 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
172 /* I want interface index which this packet comes from. */
173 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
174 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
175 struct in6_pktinfo
*ptr
;
177 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
178 *ifindex
= ptr
->ipi6_ifindex
;
179 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
182 /* Incoming packet's hop limit. */
183 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
184 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
185 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
190 rtadv_increment_received(zvrf
, ifindex
);
194 #define RTADV_MSG_SIZE 4096
196 /* Send router advertisement packet. */
197 static void rtadv_send_packet(int sock
, struct interface
*ifp
,
198 enum ipv6_nd_suppress_ra_status stop
)
202 struct cmsghdr
*cmsgptr
;
203 struct in6_pktinfo
*pkt
;
204 struct sockaddr_in6 addr
;
205 static void *adata
= NULL
;
206 unsigned char buf
[RTADV_MSG_SIZE
];
207 struct nd_router_advert
*rtadv
;
210 struct zebra_if
*zif
;
211 struct rtadv_prefix
*rprefix
;
212 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
213 0, 0, 0, 0, 0, 0, 0, 1};
214 struct listnode
*node
;
215 uint16_t pkt_RouterLifetime
;
218 * Allocate control message bufffer. This is dynamic because
219 * CMSG_SPACE is not guaranteed not to call a function. Note that
220 * the size will be different on different architectures due to
221 * differing alignment rules.
224 /* XXX Free on shutdown. */
225 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
228 zlog_debug("%s: can't malloc control data", __func__
);
233 /* Logging of packet. */
234 if (IS_ZEBRA_DEBUG_PACKET
)
235 zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp
->name
,
236 ifp
->vrf
->name
, ifp
->ifindex
, sock
);
238 /* Fill in sockaddr_in6. */
239 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
240 addr
.sin6_family
= AF_INET6
;
242 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
243 #endif /* SIN6_LEN */
244 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
245 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
247 /* Fetch interface information. */
250 /* Make router advertisement message. */
251 rtadv
= (struct nd_router_advert
*)buf
;
253 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
254 rtadv
->nd_ra_code
= 0;
255 rtadv
->nd_ra_cksum
= 0;
257 rtadv
->nd_ra_curhoplimit
= zif
->rtadv
.AdvCurHopLimit
;
259 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
260 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
262 : zif
->rtadv
.DefaultPreference
;
263 rtadv
->nd_ra_flags_reserved
<<= 3;
265 if (zif
->rtadv
.AdvManagedFlag
)
266 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
267 if (zif
->rtadv
.AdvOtherConfigFlag
)
268 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
269 if (zif
->rtadv
.AdvHomeAgentFlag
)
270 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
271 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
272 * AdvDefaultLifetime is by default based on the value of
273 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
274 * field of Router Advertisements. Given that this field is expressed
275 * in seconds, a small MaxRtrAdvInterval value can result in a zero
276 * value for this field. To prevent this, routers SHOULD keep
277 * AdvDefaultLifetime in at least one second, even if the use of
278 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
280 zif
->rtadv
.AdvDefaultLifetime
!= -1
281 ? zif
->rtadv
.AdvDefaultLifetime
282 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
284 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
285 rtadv
->nd_ra_router_lifetime
=
286 (stop
== RA_SUPPRESS
) ? htons(0) : htons(pkt_RouterLifetime
);
287 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
288 rtadv
->nd_ra_retransmit
= htonl(zif
->rtadv
.AdvRetransTimer
);
290 len
= sizeof(struct nd_router_advert
);
292 /* If both the Home Agent Preference and Home Agent Lifetime are set to
293 * their default values specified above, this option SHOULD NOT be
294 * included in the Router Advertisement messages sent by this home
295 * agent. -- RFC6275, 7.4 */
296 if (zif
->rtadv
.AdvHomeAgentFlag
297 && (zif
->rtadv
.HomeAgentPreference
298 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
299 struct nd_opt_homeagent_info
*ndopt_hai
=
300 (struct nd_opt_homeagent_info
*)(buf
+ len
);
301 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
302 ndopt_hai
->nd_opt_hai_len
= 1;
303 ndopt_hai
->nd_opt_hai_reserved
= 0;
304 ndopt_hai
->nd_opt_hai_preference
=
305 htons(zif
->rtadv
.HomeAgentPreference
);
306 /* 16-bit unsigned integer. The lifetime associated with the
308 * agent in units of seconds. The default value is the same as
310 * Router Lifetime, as specified in the main body of the Router
311 * Advertisement. The maximum value corresponds to 18.2 hours.
313 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
314 ndopt_hai
->nd_opt_hai_lifetime
=
315 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
316 ? zif
->rtadv
.HomeAgentLifetime
317 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
322 len
+= sizeof(struct nd_opt_homeagent_info
);
325 if (zif
->rtadv
.AdvIntervalOption
) {
326 struct nd_opt_adv_interval
*ndopt_adv
=
327 (struct nd_opt_adv_interval
*)(buf
+ len
);
328 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
329 ndopt_adv
->nd_opt_ai_len
= 1;
330 ndopt_adv
->nd_opt_ai_reserved
= 0;
331 ndopt_adv
->nd_opt_ai_interval
=
332 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
333 len
+= sizeof(struct nd_opt_adv_interval
);
336 /* Fill in prefix. */
337 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
338 struct nd_opt_prefix_info
*pinfo
;
340 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
342 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
343 pinfo
->nd_opt_pi_len
= 4;
344 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
346 pinfo
->nd_opt_pi_flags_reserved
= 0;
347 if (rprefix
->AdvOnLinkFlag
)
348 pinfo
->nd_opt_pi_flags_reserved
|=
349 ND_OPT_PI_FLAG_ONLINK
;
350 if (rprefix
->AdvAutonomousFlag
)
351 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
352 if (rprefix
->AdvRouterAddressFlag
)
353 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
355 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
356 pinfo
->nd_opt_pi_preferred_time
=
357 htonl(rprefix
->AdvPreferredLifetime
);
358 pinfo
->nd_opt_pi_reserved2
= 0;
360 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
361 &rprefix
->prefix
.prefix
);
363 len
+= sizeof(struct nd_opt_prefix_info
);
366 /* Hardware address. */
367 if (ifp
->hw_addr_len
!= 0) {
368 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
370 /* Option length should be rounded up to next octet if
371 the link address does not end on an octet boundary. */
372 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
374 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
375 len
+= ifp
->hw_addr_len
;
377 /* Pad option to end on an octet boundary. */
378 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
379 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
383 if (zif
->rtadv
.AdvLinkMTU
) {
384 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
385 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
386 opt
->nd_opt_mtu_len
= 1;
387 opt
->nd_opt_mtu_reserved
= 0;
388 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
389 len
+= sizeof(struct nd_opt_mtu
);
393 * There is no limit on the number of configurable recursive DNS
394 * servers or search list entries. We don't want the RA message
395 * to exceed the link's MTU (risking fragmentation) or even
396 * blow the stack buffer allocated for it.
398 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
400 /* Recursive DNS servers */
401 struct rtadv_rdnss
*rdnss
;
403 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
405 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
407 if (len
+ opt_len
> max_len
) {
409 "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
410 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
);
413 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
415 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
416 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
417 opt
->nd_opt_rdnss_reserved
= 0;
418 opt
->nd_opt_rdnss_lifetime
= htonl(
421 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
423 len
+= sizeof(struct nd_opt_rdnss
);
425 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
426 len
+= sizeof(struct in6_addr
);
429 /* DNS search list */
430 struct rtadv_dnssl
*dnssl
;
432 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
433 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
434 + ((dnssl
->encoded_len
+ 7) & ~7);
436 if (len
+ opt_len
> max_len
) {
438 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
439 ifp
->name
, ifp
->ifindex
);
442 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
444 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
445 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
446 opt
->nd_opt_dnssl_reserved
= 0;
447 opt
->nd_opt_dnssl_lifetime
= htonl(
450 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
452 len
+= sizeof(struct nd_opt_dnssl
);
454 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
455 len
+= dnssl
->encoded_len
;
457 /* Zero-pad to 8-octet boundary */
464 msg
.msg_name
= (void *)&addr
;
465 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
468 msg
.msg_control
= (void *)adata
;
469 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
474 cmsgptr
= CMSG_FIRSTHDR(&msg
);
475 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
476 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
477 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
479 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
480 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
481 pkt
->ipi6_ifindex
= ifp
->ifindex
;
483 ret
= sendmsg(sock
, &msg
, 0);
485 flog_err_sys(EC_LIB_SOCKET
,
486 "%s(%u): Tx RA failed, socket %u error %d (%s)",
487 ifp
->name
, ifp
->ifindex
, sock
, errno
,
488 safe_strerror(errno
));
493 static void rtadv_timer(struct thread
*thread
)
495 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
497 struct interface
*ifp
;
498 struct zebra_if
*zif
;
501 zvrf
->rtadv
.ra_timer
= NULL
;
502 if (adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
) == 0) {
503 period
= 1000; /* 1 s */
504 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
506 period
= 10; /* 10 ms */
507 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
510 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
511 FOR_ALL_INTERFACES (vrf
, ifp
) {
512 if (if_is_loopback(ifp
) || !if_is_operative(ifp
) ||
513 IS_ZEBRA_IF_BRIDGE_SLAVE(ifp
) ||
514 !connected_get_linklocal(ifp
) ||
515 (vrf_is_backend_netns() &&
516 ifp
->vrf
->vrf_id
!= zvrf
->vrf
->vrf_id
))
521 if (zif
->rtadv
.AdvSendAdvertisements
) {
522 if (zif
->rtadv
.inFastRexmit
523 && zif
->rtadv
.UseFastRexmit
) {
524 /* We assume we fast rexmit every sec so
527 if (--zif
->rtadv
.NumFastReXmitsRemain
529 zif
->rtadv
.inFastRexmit
= 0;
531 if (IS_ZEBRA_DEBUG_SEND
)
533 "Fast RA Rexmit on interface %s(%s:%u)",
538 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
,
541 zif
->rtadv
.AdvIntervalTimer
-= period
;
542 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
544 MaxRtrAdvInterval each
545 time isn't what section
546 6.2.4 of RFC4861 tells to do.
548 zif
->rtadv
.AdvIntervalTimer
=
552 zvrf
->rtadv
.sock
, ifp
,
560 static void rtadv_process_solicit(struct interface
*ifp
)
562 struct zebra_vrf
*zvrf
;
563 struct zebra_if
*zif
;
565 zvrf
= rtadv_interface_get_zvrf(ifp
);
570 * If FastRetransmit is enabled, send the RA immediately.
571 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
572 * (3 seconds) since the last RA was sent, send it now and reset
573 * the timer to start at the max (configured) again.
574 * If not enabled and it is less than 3 seconds since the last
575 * RA packet was sent, set the timer for 3 seconds so the next
576 * one will be sent with a minimum of 3 seconds between RAs.
579 if ((zif
->rtadv
.UseFastRexmit
)
580 || (zif
->rtadv
.AdvIntervalTimer
<=
581 (zif
->rtadv
.MaxRtrAdvInterval
- MIN_DELAY_BETWEEN_RAS
))) {
582 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_ENABLE
);
583 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
585 zif
->rtadv
.AdvIntervalTimer
= MIN_DELAY_BETWEEN_RAS
;
588 static const char *rtadv_optionalhdr2str(uint8_t opt_type
)
591 case ND_OPT_SOURCE_LINKADDR
:
592 return "Optional Source Link Address";
593 case ND_OPT_TARGET_LINKADDR
:
594 return "Optional Target Link Address";
595 case ND_OPT_PREFIX_INFORMATION
:
596 return "Optional Prefix Information";
597 case ND_OPT_REDIRECTED_HEADER
:
598 return "Optional Redirected Header";
600 return "Optional MTU";
601 case ND_OPT_RTR_ADV_INTERVAL
:
602 return "Optional Advertisement Interval";
603 case ND_OPT_HOME_AGENT_INFO
:
604 return "Optional Home Agent Information";
607 return "Unknown Optional Type";
611 * This function processes optional attributes off of
612 * end of a RA packet received. At this point in
613 * time we only care about this in one situation
614 * which is when a interface does not have a LL
615 * v6 address. We still need to be able to install
616 * the mac address for v4 to v6 resolution
618 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
619 struct interface
*ifp
,
620 struct sockaddr_in6
*addr
)
625 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
627 switch(opt_hdr
->nd_opt_type
) {
628 case ND_OPT_SOURCE_LINKADDR
:
629 mac
= (char *)(optional
+2);
630 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
631 &addr
->sin6_addr
, 1);
634 if (IS_ZEBRA_DEBUG_PACKET
)
636 "%s:Received Packet with optional Header type %s(%u) that is being ignored",
638 rtadv_optionalhdr2str(
639 opt_hdr
->nd_opt_type
),
640 opt_hdr
->nd_opt_type
);
644 len
-= 8 * opt_hdr
->nd_opt_len
;
645 optional
+= 8 * opt_hdr
->nd_opt_len
;
649 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
650 struct interface
*ifp
,
651 struct sockaddr_in6
*addr
)
653 struct nd_router_advert
*radvert
;
654 char addr_str
[INET6_ADDRSTRLEN
];
655 struct zebra_if
*zif
;
660 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
662 if (len
< sizeof(struct nd_router_advert
)) {
663 if (IS_ZEBRA_DEBUG_PACKET
)
665 "%s(%s:%u): Rx RA with invalid length %d from %s",
666 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, len
,
671 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
672 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
673 len
- sizeof(struct nd_router_advert
),
675 if (IS_ZEBRA_DEBUG_PACKET
)
677 "%s(%s:%u): Rx RA with non-linklocal source address from %s",
678 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
,
683 radvert
= (struct nd_router_advert
*)msg
;
685 #define SIXHOUR2USEC (int64_t)6 * 60 * 60 * 1000000
687 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
) &&
688 (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
) &&
689 (monotime_since(&zif
->rtadv
.lastadvcurhoplimit
, NULL
) >
691 zif
->rtadv
.lastadvcurhoplimit
.tv_sec
== 0)) {
693 EC_ZEBRA_RA_PARAM_MISMATCH
,
694 "%s(%u): Rx RA - our AdvCurHopLimit (%u) doesn't agree with %s (%u)",
695 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvCurHopLimit
,
696 addr_str
, radvert
->nd_ra_curhoplimit
);
697 monotime(&zif
->rtadv
.lastadvcurhoplimit
);
700 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
) &&
701 !zif
->rtadv
.AdvManagedFlag
&&
702 (monotime_since(&zif
->rtadv
.lastadvmanagedflag
, NULL
) >
704 zif
->rtadv
.lastadvmanagedflag
.tv_sec
== 0)) {
706 EC_ZEBRA_RA_PARAM_MISMATCH
,
707 "%s(%u): Rx RA - our AdvManagedFlag (%u) doesn't agree with %s (%u)",
708 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvManagedFlag
,
710 !!CHECK_FLAG(radvert
->nd_ra_flags_reserved
,
711 ND_RA_FLAG_MANAGED
));
712 monotime(&zif
->rtadv
.lastadvmanagedflag
);
715 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
) &&
716 !zif
->rtadv
.AdvOtherConfigFlag
&&
717 (monotime_since(&zif
->rtadv
.lastadvotherconfigflag
, NULL
) >
719 zif
->rtadv
.lastadvotherconfigflag
.tv_sec
== 0)) {
721 EC_ZEBRA_RA_PARAM_MISMATCH
,
722 "%s(%u): Rx RA - our AdvOtherConfigFlag (%u) doesn't agree with %s (%u)",
723 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvOtherConfigFlag
,
725 !!CHECK_FLAG(radvert
->nd_ra_flags_reserved
,
727 monotime(&zif
->rtadv
.lastadvotherconfigflag
);
730 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
) &&
731 (ntohl(radvert
->nd_ra_reachable
) != zif
->rtadv
.AdvReachableTime
) &&
732 (monotime_since(&zif
->rtadv
.lastadvreachabletime
, NULL
) >
734 zif
->rtadv
.lastadvreachabletime
.tv_sec
== 0)) {
736 EC_ZEBRA_RA_PARAM_MISMATCH
,
737 "%s(%u): Rx RA - our AdvReachableTime (%u) doesn't agree with %s (%u)",
738 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvReachableTime
,
739 addr_str
, ntohl(radvert
->nd_ra_reachable
));
740 monotime(&zif
->rtadv
.lastadvreachabletime
);
743 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
) &&
744 (ntohl(radvert
->nd_ra_retransmit
) !=
745 (unsigned int)zif
->rtadv
.AdvRetransTimer
) &&
746 (monotime_since(&zif
->rtadv
.lastadvretranstimer
, NULL
) >
748 zif
->rtadv
.lastadvretranstimer
.tv_sec
== 0)) {
750 EC_ZEBRA_RA_PARAM_MISMATCH
,
751 "%s(%u): Rx RA - our AdvRetransTimer (%u) doesn't agree with %s (%u)",
752 ifp
->name
, ifp
->ifindex
, zif
->rtadv
.AdvRetransTimer
,
753 addr_str
, ntohl(radvert
->nd_ra_retransmit
));
754 monotime(&zif
->rtadv
.lastadvretranstimer
);
757 /* Create entry for neighbor if not known. */
759 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
760 p
.prefixlen
= IPV6_MAX_BITLEN
;
762 if (!nbr_connected_check(ifp
, &p
))
763 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
767 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
768 ifindex_t ifindex
, int hoplimit
,
769 struct sockaddr_in6
*from
,
770 struct zebra_vrf
*zvrf
)
772 struct icmp6_hdr
*icmph
;
773 struct interface
*ifp
;
774 struct zebra_if
*zif
;
775 char addr_str
[INET6_ADDRSTRLEN
];
777 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
779 /* Interface search. */
780 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
782 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
783 "RA/RS received on unknown IF %u from %s", ifindex
,
788 if (IS_ZEBRA_DEBUG_PACKET
)
789 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp
->name
,
790 ifp
->vrf
->name
, ifp
->ifindex
, len
, addr_str
);
792 if (if_is_loopback(ifp
))
795 /* Check interface configuration. */
797 if (!zif
->rtadv
.AdvSendAdvertisements
)
800 /* ICMP message length check. */
801 if (len
< sizeof(struct icmp6_hdr
)) {
803 "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
804 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, len
);
808 icmph
= (struct icmp6_hdr
*)buf
;
810 /* ICMP message type check. */
811 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
812 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
813 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
814 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
,
819 /* Hoplimit check. */
820 if (hoplimit
>= 0 && hoplimit
!= 255) {
821 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
822 ifp
->vrf
->name
, ifp
->ifindex
, hoplimit
);
826 /* Check ICMP message type. */
827 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
828 rtadv_process_solicit(ifp
);
829 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
830 rtadv_process_advert(buf
, len
, ifp
, from
);
835 static void rtadv_read(struct thread
*thread
)
839 uint8_t buf
[RTADV_MSG_SIZE
];
840 struct sockaddr_in6 from
;
841 ifindex_t ifindex
= 0;
843 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
845 sock
= THREAD_FD(thread
);
846 zvrf
->rtadv
.ra_read
= NULL
;
848 /* Register myself. */
849 rtadv_event(zvrf
, RTADV_READ
, 0);
851 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
855 flog_err_sys(EC_LIB_SOCKET
,
856 "RA/RS recv failed, socket %u error %s", sock
,
857 safe_strerror(errno
));
861 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
864 static int rtadv_make_socket(ns_id_t ns_id
)
868 struct icmp6_filter filter
;
871 frr_with_privs(&zserv_privs
) {
873 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
875 * with privs might set errno too if it fails save
882 zlog_warn("RTADV socket for ns: %u failure to create: %s(%u)",
883 ns_id
, safe_strerror(error
), error
);
887 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
889 zlog_warn("RTADV failure to set Packet Information");
893 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
895 zlog_warn("RTADV failure to set multicast Loop detection");
899 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
901 zlog_warn("RTADV failure to set maximum unicast hops");
905 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
907 zlog_warn("RTADV failure to set maximum multicast hops");
911 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
913 zlog_warn("RTADV failure to set maximum incoming hop limit");
918 ICMP6_FILTER_SETBLOCKALL(&filter
);
919 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
920 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
922 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
923 sizeof(struct icmp6_filter
));
925 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
933 static struct adv_if
*adv_if_new(const char *name
)
937 new = XCALLOC(MTYPE_ADV_IF
, sizeof(struct adv_if
));
939 strlcpy(new->name
, name
, sizeof(new->name
));
944 static void adv_if_free(struct adv_if
*adv_if
)
946 XFREE(MTYPE_ADV_IF
, adv_if
);
949 static bool adv_if_is_empty_internal(const struct adv_if_list_head
*adv_if_head
)
951 return adv_if_list_count(adv_if_head
) ? false : true;
954 static struct adv_if
*adv_if_add_internal(struct adv_if_list_head
*adv_if_head
,
957 struct adv_if adv_if_lookup
= {};
958 struct adv_if
*adv_if
= NULL
;
960 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
961 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
966 adv_if
= adv_if_new(adv_if_lookup
.name
);
967 adv_if_list_add(adv_if_head
, adv_if
);
972 static struct adv_if
*adv_if_del_internal(struct adv_if_list_head
*adv_if_head
,
975 struct adv_if adv_if_lookup
= {};
976 struct adv_if
*adv_if
= NULL
;
978 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
979 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
984 adv_if_list_del(adv_if_head
, adv_if
);
989 static void adv_if_clean_internal(struct adv_if_list_head
*adv_if_head
)
991 struct adv_if
*node
= NULL
;
993 if (!adv_if_is_empty_internal(adv_if_head
)) {
994 frr_each_safe (adv_if_list
, adv_if_head
, node
) {
995 adv_if_list_del(adv_if_head
, node
);
1000 adv_if_list_fini(adv_if_head
);
1005 * Add to list. On Success, return NULL, otherwise return already existing
1008 static struct adv_if
*adv_if_add(struct zebra_vrf
*zvrf
, const char *name
)
1010 struct adv_if
*adv_if
= NULL
;
1012 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_if
, name
);
1017 if (IS_ZEBRA_DEBUG_EVENT
) {
1018 struct vrf
*vrf
= zvrf
->vrf
;
1020 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1021 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1022 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1029 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1032 static struct adv_if
*adv_if_del(struct zebra_vrf
*zvrf
, const char *name
)
1034 struct adv_if
*adv_if
= NULL
;
1036 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_if
, name
);
1041 if (IS_ZEBRA_DEBUG_EVENT
) {
1042 struct vrf
*vrf
= zvrf
->vrf
;
1044 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1045 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1046 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1053 * Add to list. On Success, return NULL, otherwise return already existing
1056 static struct adv_if
*adv_msec_if_add(struct zebra_vrf
*zvrf
, const char *name
)
1058 struct adv_if
*adv_if
= NULL
;
1060 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1065 if (IS_ZEBRA_DEBUG_EVENT
) {
1066 struct vrf
*vrf
= zvrf
->vrf
;
1068 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1069 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1070 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1077 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1080 static struct adv_if
*adv_msec_if_del(struct zebra_vrf
*zvrf
, const char *name
)
1082 struct adv_if
*adv_if
= NULL
;
1084 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1089 if (IS_ZEBRA_DEBUG_EVENT
) {
1090 struct vrf
*vrf
= zvrf
->vrf
;
1092 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1093 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1094 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1100 /* Clean adv_if list, called on vrf terminate */
1101 static void adv_if_clean(struct zebra_vrf
*zvrf
)
1103 if (IS_ZEBRA_DEBUG_EVENT
) {
1104 struct vrf
*vrf
= zvrf
->vrf
;
1106 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1107 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1108 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1111 adv_if_clean_internal(&zvrf
->rtadv
.adv_if
);
1114 /* Clean adv_msec_if list, called on vrf terminate */
1115 static void adv_msec_if_clean(struct zebra_vrf
*zvrf
)
1117 if (IS_ZEBRA_DEBUG_EVENT
) {
1118 struct vrf
*vrf
= zvrf
->vrf
;
1120 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1121 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1122 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1125 adv_if_clean_internal(&zvrf
->rtadv
.adv_msec_if
);
1128 static struct rtadv_prefix
*rtadv_prefix_new(void)
1130 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
1133 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
1135 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
1138 static struct rtadv_prefix
*rtadv_prefix_get(struct rtadv_prefixes_head
*list
,
1139 struct prefix_ipv6
*p
)
1141 struct rtadv_prefix
*rprefix
, ref
;
1145 rprefix
= rtadv_prefixes_find(list
, &ref
);
1149 rprefix
= rtadv_prefix_new();
1150 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
1151 rtadv_prefixes_add(list
, rprefix
);
1156 static void rtadv_prefix_set_defaults(struct rtadv_prefix
*rp
)
1158 rp
->AdvAutonomousFlag
= 1;
1159 rp
->AdvOnLinkFlag
= 1;
1160 rp
->AdvRouterAddressFlag
= 0;
1161 rp
->AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1162 rp
->AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1165 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1167 struct rtadv_prefix
*rprefix
;
1169 rprefix
= rtadv_prefix_get(zif
->rtadv
.prefixes
, &rp
->prefix
);
1172 * Set parameters based on where the prefix is created.
1173 * If auto-created based on kernel address addition, set the
1174 * default values. If created from a manual "ipv6 nd prefix"
1175 * command, take the parameters from the manual command. Note
1176 * that if the manual command exists, the default values will
1177 * not overwrite the manual values.
1179 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1180 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_AUTO
)
1181 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1183 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1185 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
1186 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
1187 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
1188 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
1189 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
1190 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1191 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
1192 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1194 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1195 rtadv_prefix_set_defaults(rprefix
);
1200 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1202 struct rtadv_prefix
*rprefix
;
1204 rprefix
= rtadv_prefixes_find(zif
->rtadv
.prefixes
, rp
);
1205 if (rprefix
!= NULL
) {
1208 * When deleting an address from the list, need to take care
1209 * it wasn't defined both automatically via kernel
1210 * address addition as well as manually by vtysh cli. If both,
1211 * we don't actually delete but may change the parameters
1212 * back to default if a manually defined entry is deleted.
1214 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1215 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1216 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1217 rtadv_prefix_set_defaults(rprefix
);
1220 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1221 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1222 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1227 rtadv_prefixes_del(zif
->rtadv
.prefixes
, rprefix
);
1228 rtadv_prefix_free(rprefix
);
1234 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
1235 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
1237 struct rtadv_prefix rp
;
1240 apply_mask_ipv6(&rp
.prefix
);
1241 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1242 rtadv_prefix_set(zif
, &rp
);
1245 /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
1246 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
1248 struct rtadv_prefix rp
;
1250 rp
.prefix
= *((struct prefix_ipv6
*)p
);
1251 apply_mask_ipv6(&rp
.prefix
);
1252 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1253 rtadv_prefix_reset(zif
, &rp
);
1256 static void rtadv_start_interface_events(struct zebra_vrf
*zvrf
,
1257 struct zebra_if
*zif
)
1259 struct adv_if
*adv_if
= NULL
;
1261 if (zif
->ifp
->ifindex
== IFINDEX_INTERNAL
) {
1262 if (IS_ZEBRA_DEBUG_EVENT
)
1264 "%s(%s) has not configured an ifindex yet, delaying until we have one",
1265 zif
->ifp
->name
, zvrf
->vrf
->name
);
1269 adv_if
= adv_if_add(zvrf
, zif
->ifp
->name
);
1271 return; /* Already added */
1273 if_join_all_router(zvrf
->rtadv
.sock
, zif
->ifp
);
1275 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 1)
1276 rtadv_event(zvrf
, RTADV_START
, 0);
1279 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
1280 enum ipv6_nd_suppress_ra_status status
)
1282 struct zebra_if
*zif
;
1283 struct zebra_vrf
*zvrf
;
1284 struct adv_if
*adv_if
= NULL
;
1288 zvrf
= rtadv_interface_get_zvrf(ifp
);
1290 if (status
== RA_SUPPRESS
) {
1291 /* RA is currently enabled */
1292 if (zif
->rtadv
.AdvSendAdvertisements
) {
1293 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1294 zif
->rtadv
.AdvSendAdvertisements
= 0;
1295 zif
->rtadv
.AdvIntervalTimer
= 0;
1297 adv_if
= adv_if_del(zvrf
, ifp
->name
);
1299 return; /* Nothing to delete */
1301 adv_if_free(adv_if
);
1303 if_leave_all_router(zvrf
->rtadv
.sock
, ifp
);
1305 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 0)
1306 rtadv_event(zvrf
, RTADV_STOP
, 0);
1309 if (!zif
->rtadv
.AdvSendAdvertisements
) {
1310 zif
->rtadv
.AdvSendAdvertisements
= 1;
1311 zif
->rtadv
.AdvIntervalTimer
= 0;
1312 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
1313 && zif
->rtadv
.UseFastRexmit
) {
1315 * Enable Fast RA only when RA interval is in
1316 * secs and Fast RA retransmit is enabled
1318 zif
->rtadv
.inFastRexmit
= 1;
1319 zif
->rtadv
.NumFastReXmitsRemain
=
1320 RTADV_NUM_FAST_REXMITS
;
1323 rtadv_start_interface_events(zvrf
, zif
);
1329 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1330 * Note that while the client could request RA on an interface on which the
1331 * operator has not enabled RA, RA won't be disabled upon client request
1332 * if the operator has explicitly enabled RA. The enable request can also
1333 * specify a RA interval (in seconds).
1335 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
1339 struct interface
*ifp
;
1340 struct zebra_if
*zif
;
1341 uint32_t ra_interval
;
1345 /* Get interface index and RA interval. */
1346 STREAM_GETL(s
, ifindex
);
1347 STREAM_GETL(s
, ra_interval
);
1349 if (IS_ZEBRA_DEBUG_EVENT
) {
1350 struct vrf
*vrf
= zvrf
->vrf
;
1352 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1353 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1354 enable
? "enable" : "disable",
1355 zebra_route_string(client
->proto
), ra_interval
);
1358 /* Locate interface and check VRF match. */
1359 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
1361 struct vrf
*vrf
= zvrf
->vrf
;
1363 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
1364 "%s:%u: IF %u RA %s client %s - interface unknown",
1365 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1366 enable
? "enable" : "disable",
1367 zebra_route_string(client
->proto
));
1370 if (vrf_is_backend_netns() && ifp
->vrf
->vrf_id
!= zvrf_id(zvrf
)) {
1372 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1373 ifp
->vrf
->name
, zvrf_id(zvrf
), ifindex
,
1374 enable
? "enable" : "disable",
1375 zebra_route_string(client
->proto
), ifp
->vrf
->vrf_id
);
1381 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1382 interfaces_configured_for_ra_from_bgp
++;
1384 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1385 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1387 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1388 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1389 VTY_RA_INTERVAL_CONFIGURED
))
1390 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1392 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1393 interfaces_configured_for_ra_from_bgp
--;
1395 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1396 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1397 VTY_RA_INTERVAL_CONFIGURED
))
1398 zif
->rtadv
.MaxRtrAdvInterval
=
1399 RTADV_MAX_RTR_ADV_INTERVAL
;
1400 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1401 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1408 * send router lifetime value of zero in RAs on this interface since we're
1409 * ceasing to advertise and want to let our neighbors know.
1410 * RFC 4861 secion 6.2.5
1412 void rtadv_stop_ra(struct interface
*ifp
)
1414 struct zebra_if
*zif
;
1415 struct zebra_vrf
*zvrf
;
1418 zvrf
= rtadv_interface_get_zvrf(ifp
);
1420 if (zif
->rtadv
.AdvSendAdvertisements
)
1421 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1425 * Send router lifetime value of zero in RAs on all interfaces since we're
1426 * ceasing to advertise globally and want to let all of our neighbors know
1427 * RFC 4861 secion 6.2.5
1429 * Delete all ipv6 global prefixes added to the router advertisement prefix
1430 * lists prior to ceasing.
1432 void rtadv_stop_ra_all(void)
1435 struct interface
*ifp
;
1436 struct zebra_if
*zif
;
1437 struct rtadv_prefix
*rprefix
;
1439 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1440 FOR_ALL_INTERFACES (vrf
, ifp
) {
1443 frr_each_safe (rtadv_prefixes
, zif
->rtadv
.prefixes
,
1445 rtadv_prefix_reset(zif
, rprefix
);
1451 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1453 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1455 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1457 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1460 static void show_zvrf_rtadv_adv_if_helper(struct vty
*vty
,
1461 struct adv_if_list_head
*adv_if_head
)
1463 struct adv_if
*node
= NULL
;
1465 if (!adv_if_is_empty_internal(adv_if_head
)) {
1466 frr_each (adv_if_list
, adv_if_head
, node
) {
1467 vty_out(vty
, " %s\n", node
->name
);
1474 static void show_zvrf_rtadv_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
)
1476 vty_out(vty
, "VRF: %s\n", zvrf_name(zvrf
));
1477 vty_out(vty
, " Interfaces:\n");
1478 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_if
);
1480 vty_out(vty
, " Interfaces(msec):\n");
1481 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_msec_if
);
1484 DEFPY(show_ipv6_nd_ra_if
, show_ipv6_nd_ra_if_cmd
,
1485 "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
1487 "Neighbor discovery\n"
1488 "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR
)
1490 struct zebra_vrf
*zvrf
= NULL
;
1492 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1494 "%% VRF subcommand only applicable for netns-based vrfs.\n");
1501 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1502 struct zebra_vrf
*zvrf
;
1508 show_zvrf_rtadv_helper(vty
, zvrf
);
1515 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1517 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1520 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1525 show_zvrf_rtadv_helper(vty
, zvrf
);
1530 DEFUN (ipv6_nd_ra_fast_retrans
,
1531 ipv6_nd_ra_fast_retrans_cmd
,
1532 "ipv6 nd ra-fast-retrans",
1533 "Interface IPv6 config commands\n"
1534 "Neighbor discovery\n"
1535 "Fast retransmit of RA packets\n")
1537 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1538 struct zebra_if
*zif
= ifp
->info
;
1540 if (if_is_loopback(ifp
)) {
1542 "Cannot configure IPv6 Router Advertisements on this interface\n");
1543 return CMD_WARNING_CONFIG_FAILED
;
1546 zif
->rtadv
.UseFastRexmit
= true;
1551 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1552 no_ipv6_nd_ra_fast_retrans_cmd
,
1553 "no ipv6 nd ra-fast-retrans",
1555 "Interface IPv6 config commands\n"
1556 "Neighbor discovery\n"
1557 "Fast retransmit of RA packets\n")
1559 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1560 struct zebra_if
*zif
= ifp
->info
;
1562 if (if_is_loopback(ifp
)) {
1564 "Cannot configure IPv6 Router Advertisements on this interface\n");
1565 return CMD_WARNING_CONFIG_FAILED
;
1568 zif
->rtadv
.UseFastRexmit
= false;
1573 DEFPY (ipv6_nd_ra_hop_limit
,
1574 ipv6_nd_ra_hop_limit_cmd
,
1575 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1576 "Interface IPv6 config commands\n"
1577 "Neighbor discovery\n"
1578 "Advertisement Hop Limit\n"
1579 "Advertisement Hop Limit in hops (default:64)\n")
1581 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1582 struct zebra_if
*zif
= ifp
->info
;
1584 if (if_is_loopback(ifp
)) {
1586 "Cannot configure IPv6 Router Advertisements on this interface\n");
1587 return CMD_WARNING_CONFIG_FAILED
;
1590 zif
->rtadv
.AdvCurHopLimit
= hopcount
;
1595 DEFPY (no_ipv6_nd_ra_hop_limit
,
1596 no_ipv6_nd_ra_hop_limit_cmd
,
1597 "no ipv6 nd ra-hop-limit [(0-255)]",
1599 "Interface IPv6 config commands\n"
1600 "Neighbor discovery\n"
1601 "Advertisement Hop Limit\n"
1602 "Advertisement Hop Limit in hops\n")
1604 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1605 struct zebra_if
*zif
= ifp
->info
;
1607 if (if_is_loopback(ifp
)) {
1609 "Cannot configure IPv6 Router Advertisements on this interface\n");
1610 return CMD_WARNING_CONFIG_FAILED
;
1613 zif
->rtadv
.AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
1618 DEFPY (ipv6_nd_ra_retrans_interval
,
1619 ipv6_nd_ra_retrans_interval_cmd
,
1620 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1621 "Interface IPv6 config commands\n"
1622 "Neighbor discovery\n"
1623 "Advertisement Retransmit Interval\n"
1624 "Advertisement Retransmit Interval in msec\n")
1626 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1627 struct zebra_if
*zif
= ifp
->info
;
1629 if (if_is_loopback(ifp
)) {
1631 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1632 return CMD_WARNING_CONFIG_FAILED
;
1635 zif
->rtadv
.AdvRetransTimer
= interval
;
1640 DEFPY (no_ipv6_nd_ra_retrans_interval
,
1641 no_ipv6_nd_ra_retrans_interval_cmd
,
1642 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1644 "Interface IPv6 config commands\n"
1645 "Neighbor discovery\n"
1646 "Advertisement Retransmit Interval\n"
1647 "Advertisement Retransmit Interval in msec\n")
1649 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1650 struct zebra_if
*zif
= ifp
->info
;
1652 if (if_is_loopback(ifp
)) {
1654 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1655 return CMD_WARNING_CONFIG_FAILED
;
1658 zif
->rtadv
.AdvRetransTimer
= 0;
1663 DEFUN (ipv6_nd_suppress_ra
,
1664 ipv6_nd_suppress_ra_cmd
,
1665 "ipv6 nd suppress-ra",
1666 "Interface IPv6 config commands\n"
1667 "Neighbor discovery\n"
1668 "Suppress Router Advertisement\n")
1670 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1671 struct zebra_if
*zif
= ifp
->info
;
1673 if (if_is_loopback(ifp
)) {
1675 "Cannot configure IPv6 Router Advertisements on this interface\n");
1676 return CMD_WARNING_CONFIG_FAILED
;
1679 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1680 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1682 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1686 DEFUN (no_ipv6_nd_suppress_ra
,
1687 no_ipv6_nd_suppress_ra_cmd
,
1688 "no ipv6 nd suppress-ra",
1690 "Interface IPv6 config commands\n"
1691 "Neighbor discovery\n"
1692 "Suppress Router Advertisement\n")
1694 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1695 struct zebra_if
*zif
= ifp
->info
;
1697 if (if_is_loopback(ifp
)) {
1699 "Cannot configure IPv6 Router Advertisements on this interface\n");
1700 return CMD_WARNING_CONFIG_FAILED
;
1703 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1704 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1708 DEFUN (ipv6_nd_ra_interval_msec
,
1709 ipv6_nd_ra_interval_msec_cmd
,
1710 "ipv6 nd ra-interval msec (70-1800000)",
1711 "Interface IPv6 config commands\n"
1712 "Neighbor discovery\n"
1713 "Router Advertisement interval\n"
1714 "Router Advertisement interval in milliseconds\n"
1715 "Router Advertisement interval in milliseconds\n")
1718 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1720 struct zebra_if
*zif
= ifp
->info
;
1721 struct zebra_vrf
*zvrf
;
1722 struct adv_if
*adv_if
;
1724 zvrf
= rtadv_interface_get_zvrf(ifp
);
1726 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1727 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1728 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1730 "This ra-interval would conflict with configured ra-lifetime!\n");
1731 return CMD_WARNING_CONFIG_FAILED
;
1734 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1735 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1737 adv_if_free(adv_if
);
1740 if (interval
% 1000)
1741 (void)adv_msec_if_add(zvrf
, ifp
->name
);
1743 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1744 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1745 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1746 zif
->rtadv
.AdvIntervalTimer
= 0;
1751 DEFUN (ipv6_nd_ra_interval
,
1752 ipv6_nd_ra_interval_cmd
,
1753 "ipv6 nd ra-interval (1-1800)",
1754 "Interface IPv6 config commands\n"
1755 "Neighbor discovery\n"
1756 "Router Advertisement interval\n"
1757 "Router Advertisement interval in seconds\n")
1760 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1762 struct zebra_if
*zif
= ifp
->info
;
1763 struct zebra_vrf
*zvrf
;
1764 struct adv_if
*adv_if
;
1766 zvrf
= rtadv_interface_get_zvrf(ifp
);
1768 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1769 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1770 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1772 "This ra-interval would conflict with configured ra-lifetime!\n");
1773 return CMD_WARNING_CONFIG_FAILED
;
1776 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1777 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1779 adv_if_free(adv_if
);
1782 /* convert to milliseconds */
1783 interval
= interval
* 1000;
1785 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1786 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1787 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1788 zif
->rtadv
.AdvIntervalTimer
= 0;
1793 DEFUN (no_ipv6_nd_ra_interval
,
1794 no_ipv6_nd_ra_interval_cmd
,
1795 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1797 "Interface IPv6 config commands\n"
1798 "Neighbor discovery\n"
1799 "Router Advertisement interval\n"
1800 "Router Advertisement interval in seconds\n"
1801 "Specify millisecond router advertisement interval\n"
1802 "Router Advertisement interval in milliseconds\n")
1804 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1805 struct zebra_if
*zif
= ifp
->info
;
1806 struct zebra_vrf
*zvrf
= NULL
;
1807 struct adv_if
*adv_if
;
1809 zvrf
= rtadv_interface_get_zvrf(ifp
);
1811 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1812 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1814 adv_if_free(adv_if
);
1817 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1819 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1820 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1822 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1824 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1825 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1830 DEFUN (ipv6_nd_ra_lifetime
,
1831 ipv6_nd_ra_lifetime_cmd
,
1832 "ipv6 nd ra-lifetime (0-9000)",
1833 "Interface IPv6 config commands\n"
1834 "Neighbor discovery\n"
1836 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1839 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1840 struct zebra_if
*zif
= ifp
->info
;
1843 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1845 /* The value to be placed in the Router Lifetime field
1846 * of Router Advertisements sent from the interface,
1847 * in seconds. MUST be either zero or between
1848 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1849 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1851 "This ra-lifetime would conflict with configured ra-interval\n");
1852 return CMD_WARNING_CONFIG_FAILED
;
1855 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1860 DEFUN (no_ipv6_nd_ra_lifetime
,
1861 no_ipv6_nd_ra_lifetime_cmd
,
1862 "no ipv6 nd ra-lifetime [(0-9000)]",
1864 "Interface IPv6 config commands\n"
1865 "Neighbor discovery\n"
1867 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1869 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1870 struct zebra_if
*zif
= ifp
->info
;
1872 zif
->rtadv
.AdvDefaultLifetime
= -1;
1877 DEFUN (ipv6_nd_reachable_time
,
1878 ipv6_nd_reachable_time_cmd
,
1879 "ipv6 nd reachable-time (1-3600000)",
1880 "Interface IPv6 config commands\n"
1881 "Neighbor discovery\n"
1883 "Reachable time in milliseconds\n")
1886 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1887 struct zebra_if
*zif
= ifp
->info
;
1888 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1892 DEFUN (no_ipv6_nd_reachable_time
,
1893 no_ipv6_nd_reachable_time_cmd
,
1894 "no ipv6 nd reachable-time [(1-3600000)]",
1896 "Interface IPv6 config commands\n"
1897 "Neighbor discovery\n"
1899 "Reachable time in milliseconds\n")
1901 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1902 struct zebra_if
*zif
= ifp
->info
;
1904 zif
->rtadv
.AdvReachableTime
= 0;
1909 DEFUN (ipv6_nd_homeagent_preference
,
1910 ipv6_nd_homeagent_preference_cmd
,
1911 "ipv6 nd home-agent-preference (0-65535)",
1912 "Interface IPv6 config commands\n"
1913 "Neighbor discovery\n"
1914 "Home Agent preference\n"
1915 "preference value (default is 0, least preferred)\n")
1918 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1919 struct zebra_if
*zif
= ifp
->info
;
1920 zif
->rtadv
.HomeAgentPreference
=
1921 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1925 DEFUN (no_ipv6_nd_homeagent_preference
,
1926 no_ipv6_nd_homeagent_preference_cmd
,
1927 "no ipv6 nd home-agent-preference [(0-65535)]",
1929 "Interface IPv6 config commands\n"
1930 "Neighbor discovery\n"
1931 "Home Agent preference\n"
1932 "preference value (default is 0, least preferred)\n")
1934 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1935 struct zebra_if
*zif
= ifp
->info
;
1937 zif
->rtadv
.HomeAgentPreference
= 0;
1942 DEFUN (ipv6_nd_homeagent_lifetime
,
1943 ipv6_nd_homeagent_lifetime_cmd
,
1944 "ipv6 nd home-agent-lifetime (0-65520)",
1945 "Interface IPv6 config commands\n"
1946 "Neighbor discovery\n"
1947 "Home Agent lifetime\n"
1948 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1951 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1952 struct zebra_if
*zif
= ifp
->info
;
1953 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1957 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1958 no_ipv6_nd_homeagent_lifetime_cmd
,
1959 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1961 "Interface IPv6 config commands\n"
1962 "Neighbor discovery\n"
1963 "Home Agent lifetime\n"
1964 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1966 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1967 struct zebra_if
*zif
= ifp
->info
;
1969 zif
->rtadv
.HomeAgentLifetime
= -1;
1974 DEFUN (ipv6_nd_managed_config_flag
,
1975 ipv6_nd_managed_config_flag_cmd
,
1976 "ipv6 nd managed-config-flag",
1977 "Interface IPv6 config commands\n"
1978 "Neighbor discovery\n"
1979 "Managed address configuration flag\n")
1981 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1982 struct zebra_if
*zif
= ifp
->info
;
1984 zif
->rtadv
.AdvManagedFlag
= 1;
1989 DEFUN (no_ipv6_nd_managed_config_flag
,
1990 no_ipv6_nd_managed_config_flag_cmd
,
1991 "no ipv6 nd managed-config-flag",
1993 "Interface IPv6 config commands\n"
1994 "Neighbor discovery\n"
1995 "Managed address configuration flag\n")
1997 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1998 struct zebra_if
*zif
= ifp
->info
;
2000 zif
->rtadv
.AdvManagedFlag
= 0;
2005 DEFUN (ipv6_nd_homeagent_config_flag
,
2006 ipv6_nd_homeagent_config_flag_cmd
,
2007 "ipv6 nd home-agent-config-flag",
2008 "Interface IPv6 config commands\n"
2009 "Neighbor discovery\n"
2010 "Home Agent configuration flag\n")
2012 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2013 struct zebra_if
*zif
= ifp
->info
;
2015 zif
->rtadv
.AdvHomeAgentFlag
= 1;
2020 DEFUN (no_ipv6_nd_homeagent_config_flag
,
2021 no_ipv6_nd_homeagent_config_flag_cmd
,
2022 "no ipv6 nd home-agent-config-flag",
2024 "Interface IPv6 config commands\n"
2025 "Neighbor discovery\n"
2026 "Home Agent configuration flag\n")
2028 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2029 struct zebra_if
*zif
= ifp
->info
;
2031 zif
->rtadv
.AdvHomeAgentFlag
= 0;
2036 DEFUN (ipv6_nd_adv_interval_config_option
,
2037 ipv6_nd_adv_interval_config_option_cmd
,
2038 "ipv6 nd adv-interval-option",
2039 "Interface IPv6 config commands\n"
2040 "Neighbor discovery\n"
2041 "Advertisement Interval Option\n")
2043 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2044 struct zebra_if
*zif
= ifp
->info
;
2046 zif
->rtadv
.AdvIntervalOption
= 1;
2051 DEFUN (no_ipv6_nd_adv_interval_config_option
,
2052 no_ipv6_nd_adv_interval_config_option_cmd
,
2053 "no ipv6 nd adv-interval-option",
2055 "Interface IPv6 config commands\n"
2056 "Neighbor discovery\n"
2057 "Advertisement Interval Option\n")
2059 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2060 struct zebra_if
*zif
= ifp
->info
;
2062 zif
->rtadv
.AdvIntervalOption
= 0;
2067 DEFUN (ipv6_nd_other_config_flag
,
2068 ipv6_nd_other_config_flag_cmd
,
2069 "ipv6 nd other-config-flag",
2070 "Interface IPv6 config commands\n"
2071 "Neighbor discovery\n"
2072 "Other statefull configuration flag\n")
2074 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2075 struct zebra_if
*zif
= ifp
->info
;
2077 zif
->rtadv
.AdvOtherConfigFlag
= 1;
2082 DEFUN (no_ipv6_nd_other_config_flag
,
2083 no_ipv6_nd_other_config_flag_cmd
,
2084 "no ipv6 nd other-config-flag",
2086 "Interface IPv6 config commands\n"
2087 "Neighbor discovery\n"
2088 "Other statefull configuration flag\n")
2090 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2091 struct zebra_if
*zif
= ifp
->info
;
2093 zif
->rtadv
.AdvOtherConfigFlag
= 0;
2098 DEFUN (ipv6_nd_prefix
,
2100 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2101 "Interface IPv6 config commands\n"
2102 "Neighbor discovery\n"
2103 "Prefix information\n"
2105 "Valid lifetime in seconds\n"
2106 "Infinite valid lifetime\n"
2107 "Preferred lifetime in seconds\n"
2108 "Infinite preferred lifetime\n"
2109 "Set Router Address flag\n"
2110 "Do not use prefix for onlink determination\n"
2111 "Do not use prefix for autoconfiguration\n"
2112 "Do not use prefix for autoconfiguration\n"
2113 "Do not use prefix for onlink determination\n")
2116 char *prefix
= argv
[3]->arg
;
2117 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
2118 || strmatch(argv
[4]->text
, "infinite"));
2119 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
2121 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
2123 char *lifetime
= NULL
, *preflifetime
= NULL
;
2124 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
2126 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2128 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
2133 strmatch(argv
[idx_routeropts
]->text
, "router-address");
2135 offlink
= (argc
> idx_routeropts
+ 1
2136 || strmatch(argv
[idx_routeropts
]->text
,
2138 noautoconf
= (argc
> idx_routeropts
+ 1
2139 || strmatch(argv
[idx_routeropts
]->text
,
2145 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2146 struct zebra_if
*zebra_if
= ifp
->info
;
2148 struct rtadv_prefix rp
;
2150 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2152 vty_out(vty
, "Malformed IPv6 prefix\n");
2153 return CMD_WARNING_CONFIG_FAILED
;
2155 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2156 rp
.AdvOnLinkFlag
= !offlink
;
2157 rp
.AdvAutonomousFlag
= !noautoconf
;
2158 rp
.AdvRouterAddressFlag
= routeraddr
;
2159 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
2160 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
2161 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2164 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
2166 : strtoll(lifetime
, NULL
, 10);
2167 rp
.AdvPreferredLifetime
=
2168 strmatch(preflifetime
, "infinite")
2170 : strtoll(preflifetime
, NULL
, 10);
2171 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
2172 vty_out(vty
, "Invalid preferred lifetime\n");
2173 return CMD_WARNING_CONFIG_FAILED
;
2177 rtadv_prefix_set(zebra_if
, &rp
);
2182 DEFUN (no_ipv6_nd_prefix
,
2183 no_ipv6_nd_prefix_cmd
,
2184 "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]>]",
2186 "Interface IPv6 config commands\n"
2187 "Neighbor discovery\n"
2188 "Prefix information\n"
2190 "Valid lifetime in seconds\n"
2191 "Infinite valid lifetime\n"
2192 "Preferred lifetime in seconds\n"
2193 "Infinite preferred lifetime\n"
2194 "Set Router Address flag\n"
2195 "Do not use prefix for onlink determination\n"
2196 "Do not use prefix for autoconfiguration\n"
2197 "Do not use prefix for autoconfiguration\n"
2198 "Do not use prefix for onlink determination\n")
2200 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2201 struct zebra_if
*zebra_if
= ifp
->info
;
2203 struct rtadv_prefix rp
;
2204 char *prefix
= argv
[4]->arg
;
2206 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2208 vty_out(vty
, "Malformed IPv6 prefix\n");
2209 return CMD_WARNING_CONFIG_FAILED
;
2211 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2212 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2214 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
2216 vty_out(vty
, "Non-existant IPv6 prefix\n");
2217 return CMD_WARNING_CONFIG_FAILED
;
2223 DEFUN (ipv6_nd_router_preference
,
2224 ipv6_nd_router_preference_cmd
,
2225 "ipv6 nd router-preference <high|medium|low>",
2226 "Interface IPv6 config commands\n"
2227 "Neighbor discovery\n"
2228 "Default router preference\n"
2229 "High default router preference\n"
2230 "Medium default router preference (default)\n"
2231 "Low default router preference\n")
2233 int idx_high_medium_low
= 3;
2234 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2235 struct zebra_if
*zif
= ifp
->info
;
2238 while (0 != rtadv_pref_strs
[i
]) {
2239 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
2242 zif
->rtadv
.DefaultPreference
= i
;
2248 return CMD_ERR_NO_MATCH
;
2251 DEFUN (no_ipv6_nd_router_preference
,
2252 no_ipv6_nd_router_preference_cmd
,
2253 "no ipv6 nd router-preference [<high|medium|low>]",
2255 "Interface IPv6 config commands\n"
2256 "Neighbor discovery\n"
2257 "Default router preference\n"
2258 "High default router preference\n"
2259 "Medium default router preference (default)\n"
2260 "Low default router preference\n")
2262 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2263 struct zebra_if
*zif
= ifp
->info
;
2265 zif
->rtadv
.DefaultPreference
=
2266 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
2273 "ipv6 nd mtu (1-65535)",
2274 "Interface IPv6 config commands\n"
2275 "Neighbor discovery\n"
2280 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2281 struct zebra_if
*zif
= ifp
->info
;
2282 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2286 DEFUN (no_ipv6_nd_mtu
,
2288 "no ipv6 nd mtu [(1-65535)]",
2290 "Interface IPv6 config commands\n"
2291 "Neighbor discovery\n"
2295 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2296 struct zebra_if
*zif
= ifp
->info
;
2297 zif
->rtadv
.AdvLinkMTU
= 0;
2301 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
2303 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
2306 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
2308 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
2311 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
2312 struct rtadv_rdnss
*rdnss
)
2314 struct listnode
*node
;
2315 struct rtadv_rdnss
*p
;
2317 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2318 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
2323 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
2324 struct rtadv_rdnss
*rdnss
)
2326 struct rtadv_rdnss
*p
;
2328 p
= rtadv_rdnss_lookup(list
, rdnss
);
2332 p
= rtadv_rdnss_new();
2333 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
2334 listnode_add(list
, p
);
2339 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2341 struct rtadv_rdnss
*p
;
2343 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2344 p
->lifetime
= rdnss
->lifetime
;
2345 p
->lifetime_set
= rdnss
->lifetime_set
;
2348 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2350 struct rtadv_rdnss
*p
;
2352 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2354 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
2355 rtadv_rdnss_free(p
);
2362 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
2364 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
2367 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
2369 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
2372 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
2373 struct rtadv_dnssl
*dnssl
)
2375 struct listnode
*node
;
2376 struct rtadv_dnssl
*p
;
2378 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2379 if (!strcasecmp(p
->name
, dnssl
->name
))
2384 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
2385 struct rtadv_dnssl
*dnssl
)
2387 struct rtadv_dnssl
*p
;
2389 p
= rtadv_dnssl_lookup(list
, dnssl
);
2393 p
= rtadv_dnssl_new();
2394 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2395 listnode_add(list
, p
);
2400 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2402 struct rtadv_dnssl
*p
;
2404 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2405 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2408 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2410 struct rtadv_dnssl
*p
;
2412 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2414 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
2415 rtadv_dnssl_free(p
);
2423 * Convert dotted domain name (with or without trailing root zone dot) to
2424 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2425 * to strlen(in) + 2 octets to out.
2427 * Returns the number of octets written to out or -1 if in does not constitute
2428 * a valid domain name.
2430 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
2432 const char *label_start
, *label_end
;
2438 while (*label_start
) {
2441 label_end
= strchr(label_start
, '.');
2442 if (label_end
== NULL
)
2443 label_end
= label_start
+ strlen(label_start
);
2445 label_len
= label_end
- label_start
;
2446 if (label_len
>= 64)
2447 return -1; /* labels must be 63 octets or less */
2449 out
[outp
++] = (uint8_t)label_len
;
2450 memcpy(out
+ outp
, label_start
, label_len
);
2452 label_start
+= label_len
;
2453 if (*label_start
== '.')
2461 DEFUN(ipv6_nd_rdnss
,
2463 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2464 "Interface IPv6 config commands\n"
2465 "Neighbor discovery\n"
2466 "Recursive DNS server information\n"
2468 "Valid lifetime in seconds\n"
2469 "Infinite valid lifetime\n")
2471 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2472 struct zebra_if
*zif
= ifp
->info
;
2473 struct rtadv_rdnss rdnss
= {};
2475 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
2476 vty_out(vty
, "Malformed IPv6 address\n");
2477 return CMD_WARNING_CONFIG_FAILED
;
2480 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2482 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
2484 : strtoll(lifetime
, NULL
, 10);
2485 rdnss
.lifetime_set
= 1;
2488 rtadv_rdnss_set(zif
, &rdnss
);
2493 DEFUN(no_ipv6_nd_rdnss
,
2494 no_ipv6_nd_rdnss_cmd
,
2495 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2497 "Interface IPv6 config commands\n"
2498 "Neighbor discovery\n"
2499 "Recursive DNS server information\n"
2501 "Valid lifetime in seconds\n"
2502 "Infinite valid lifetime\n")
2504 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2505 struct zebra_if
*zif
= ifp
->info
;
2506 struct rtadv_rdnss rdnss
= {};
2508 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
2509 vty_out(vty
, "Malformed IPv6 address\n");
2510 return CMD_WARNING_CONFIG_FAILED
;
2512 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
2513 vty_out(vty
, "Non-existant RDNSS address\n");
2514 return CMD_WARNING_CONFIG_FAILED
;
2520 DEFUN(ipv6_nd_dnssl
,
2522 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2523 "Interface IPv6 config commands\n"
2524 "Neighbor discovery\n"
2525 "DNS search list information\n"
2526 "Domain name suffix\n"
2527 "Valid lifetime in seconds\n"
2528 "Infinite valid lifetime\n")
2530 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2531 struct zebra_if
*zif
= ifp
->info
;
2532 struct rtadv_dnssl dnssl
= {};
2536 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
2537 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2538 vty_out(vty
, "Malformed DNS search domain\n");
2539 return CMD_WARNING_CONFIG_FAILED
;
2541 if (dnssl
.name
[len
- 1] == '.') {
2543 * Allow, but don't require, a trailing dot signifying the root
2544 * zone. Canonicalize by cutting it off if present.
2546 dnssl
.name
[len
- 1] = '\0';
2550 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2552 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
2554 : strtoll(lifetime
, NULL
, 10);
2555 dnssl
.lifetime_set
= 1;
2558 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2560 vty_out(vty
, "Malformed DNS search domain\n");
2561 return CMD_WARNING_CONFIG_FAILED
;
2563 dnssl
.encoded_len
= ret
;
2564 rtadv_dnssl_set(zif
, &dnssl
);
2569 DEFUN(no_ipv6_nd_dnssl
,
2570 no_ipv6_nd_dnssl_cmd
,
2571 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2573 "Interface IPv6 config commands\n"
2574 "Neighbor discovery\n"
2575 "DNS search list information\n"
2576 "Domain name suffix\n"
2577 "Valid lifetime in seconds\n"
2578 "Infinite valid lifetime\n")
2580 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2581 struct zebra_if
*zif
= ifp
->info
;
2582 struct rtadv_dnssl dnssl
= {};
2585 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2586 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2587 vty_out(vty
, "Malformed DNS search domain\n");
2588 return CMD_WARNING_CONFIG_FAILED
;
2590 if (dnssl
.name
[len
- 1] == '.') {
2591 dnssl
.name
[len
- 1] = '\0';
2594 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2595 vty_out(vty
, "Non-existant DNS search domain\n");
2596 return CMD_WARNING_CONFIG_FAILED
;
2603 /* Dump interface ND information to vty. */
2604 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2606 struct zebra_if
*zif
;
2607 struct rtadvconf
*rtadv
;
2610 zif
= (struct zebra_if
*)ifp
->info
;
2611 rtadv
= &zif
->rtadv
;
2613 if (rtadv
->AdvSendAdvertisements
) {
2615 " ND advertised reachable time is %d milliseconds\n",
2616 rtadv
->AdvReachableTime
);
2618 " ND advertised retransmit interval is %u milliseconds\n",
2619 rtadv
->AdvRetransTimer
);
2620 vty_out(vty
, " ND advertised hop-count limit is %d hops\n",
2621 rtadv
->AdvCurHopLimit
);
2622 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2623 zif
->ra_sent
, zif
->ra_rcvd
);
2624 interval
= rtadv
->MaxRtrAdvInterval
;
2625 if (interval
% 1000)
2627 " ND router advertisements are sent every %d milliseconds\n",
2631 " ND router advertisements are sent every %d seconds\n",
2633 if (!rtadv
->UseFastRexmit
)
2635 " ND router advertisements do not use fast retransmit\n");
2637 if (rtadv
->AdvDefaultLifetime
!= -1)
2639 " ND router advertisements live for %d seconds\n",
2640 rtadv
->AdvDefaultLifetime
);
2643 " ND router advertisements lifetime tracks ra-interval\n");
2645 " ND router advertisement default router preference is %s\n",
2646 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2647 if (rtadv
->AdvManagedFlag
)
2649 " Hosts use DHCP to obtain routable addresses.\n");
2652 " Hosts use stateless autoconfig for addresses.\n");
2653 if (rtadv
->AdvHomeAgentFlag
) {
2655 " ND router advertisements with Home Agent flag bit set.\n");
2656 if (rtadv
->HomeAgentLifetime
!= -1)
2658 " Home Agent lifetime is %u seconds\n",
2659 rtadv
->HomeAgentLifetime
);
2662 " Home Agent lifetime tracks ra-lifetime\n");
2663 vty_out(vty
, " Home Agent preference is %u\n",
2664 rtadv
->HomeAgentPreference
);
2666 if (rtadv
->AdvIntervalOption
)
2668 " ND router advertisements with Adv. Interval option.\n");
2674 /* Write configuration about router advertisement. */
2675 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2677 struct zebra_if
*zif
;
2678 struct listnode
*node
;
2679 struct rtadv_prefix
*rprefix
;
2680 struct rtadv_rdnss
*rdnss
;
2681 struct rtadv_dnssl
*dnssl
;
2686 if (!if_is_loopback(ifp
)) {
2687 if (zif
->rtadv
.AdvSendAdvertisements
2688 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2689 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2692 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2693 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2694 if (interval
% 1000)
2695 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2697 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2698 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2702 if (zif
->rtadv
.AdvIntervalOption
)
2703 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2705 if (!zif
->rtadv
.UseFastRexmit
)
2706 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2708 if (zif
->rtadv
.AdvRetransTimer
!= 0)
2709 vty_out(vty
, " ipv6 nd ra-retrans-interval %u\n",
2710 zif
->rtadv
.AdvRetransTimer
);
2712 if (zif
->rtadv
.AdvCurHopLimit
!= RTADV_DEFAULT_HOPLIMIT
)
2713 vty_out(vty
, " ipv6 nd ra-hop-limit %d\n",
2714 zif
->rtadv
.AdvCurHopLimit
);
2716 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2717 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2718 zif
->rtadv
.AdvDefaultLifetime
);
2720 if (zif
->rtadv
.HomeAgentPreference
)
2721 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2722 zif
->rtadv
.HomeAgentPreference
);
2724 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2725 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2726 zif
->rtadv
.HomeAgentLifetime
);
2728 if (zif
->rtadv
.AdvHomeAgentFlag
)
2729 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2731 if (zif
->rtadv
.AdvReachableTime
)
2732 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2733 zif
->rtadv
.AdvReachableTime
);
2735 if (zif
->rtadv
.AdvManagedFlag
)
2736 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2738 if (zif
->rtadv
.AdvOtherConfigFlag
)
2739 vty_out(vty
, " ipv6 nd other-config-flag\n");
2741 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2742 vty_out(vty
, " ipv6 nd router-preference %s\n",
2743 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2745 if (zif
->rtadv
.AdvLinkMTU
)
2746 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2748 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
2749 if ((rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
2750 || (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
)) {
2751 vty_out(vty
, " ipv6 nd prefix %pFX", &rprefix
->prefix
);
2752 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2753 || (rprefix
->AdvPreferredLifetime
2754 != RTADV_PREFERRED_LIFETIME
)) {
2755 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2756 vty_out(vty
, " infinite");
2759 rprefix
->AdvValidLifetime
);
2760 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2761 vty_out(vty
, " infinite");
2764 rprefix
->AdvPreferredLifetime
);
2766 if (!rprefix
->AdvOnLinkFlag
)
2767 vty_out(vty
, " off-link");
2768 if (!rprefix
->AdvAutonomousFlag
)
2769 vty_out(vty
, " no-autoconfig");
2770 if (rprefix
->AdvRouterAddressFlag
)
2771 vty_out(vty
, " router-address");
2776 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2777 char buf
[INET6_ADDRSTRLEN
];
2779 vty_out(vty
, " ipv6 nd rdnss %s",
2780 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2781 if (rdnss
->lifetime_set
) {
2782 if (rdnss
->lifetime
== UINT32_MAX
)
2783 vty_out(vty
, " infinite");
2785 vty_out(vty
, " %u", rdnss
->lifetime
);
2789 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2790 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2791 if (dnssl
->lifetime_set
) {
2792 if (dnssl
->lifetime
== UINT32_MAX
)
2793 vty_out(vty
, " infinite");
2795 vty_out(vty
, " %u", dnssl
->lifetime
);
2803 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2805 struct rtadv
*rtadv
;
2807 if (IS_ZEBRA_DEBUG_EVENT
) {
2808 struct vrf
*vrf
= zvrf
->vrf
;
2810 zlog_debug("%s(%s) with event: %d and val: %d", __func__
,
2811 VRF_LOGNAME(vrf
), event
, val
);
2814 rtadv
= &zvrf
->rtadv
;
2818 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2820 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2824 THREAD_OFF(rtadv
->ra_timer
);
2825 THREAD_OFF(rtadv
->ra_read
);
2828 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2831 case RTADV_TIMER_MSEC
:
2832 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2836 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2845 void rtadv_if_up(struct zebra_if
*zif
)
2847 struct zebra_vrf
*zvrf
= rtadv_interface_get_zvrf(zif
->ifp
);
2849 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
2850 if (zif
->rtadv
.AdvSendAdvertisements
&&
2851 (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) &&
2852 zif
->rtadv
.UseFastRexmit
) {
2853 zif
->rtadv
.inFastRexmit
= 1;
2854 zif
->rtadv
.NumFastReXmitsRemain
= RTADV_NUM_FAST_REXMITS
;
2858 * startup the state machine, if it hasn't been already
2859 * due to a delayed ifindex on startup ordering
2861 if (zif
->rtadv
.AdvSendAdvertisements
)
2862 rtadv_start_interface_events(zvrf
, zif
);
2865 void rtadv_if_init(struct zebra_if
*zif
)
2867 /* Set default router advertise values. */
2868 struct rtadvconf
*rtadv
;
2870 rtadv
= &zif
->rtadv
;
2872 rtadv
->AdvSendAdvertisements
= 0;
2873 rtadv
->MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
2874 rtadv
->MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
2875 rtadv
->AdvIntervalTimer
= 0;
2876 rtadv
->AdvManagedFlag
= 0;
2877 rtadv
->AdvOtherConfigFlag
= 0;
2878 rtadv
->AdvHomeAgentFlag
= 0;
2879 rtadv
->AdvLinkMTU
= 0;
2880 rtadv
->AdvReachableTime
= 0;
2881 rtadv
->AdvRetransTimer
= 0;
2882 rtadv
->AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
2883 memset(&rtadv
->lastadvcurhoplimit
, 0,
2884 sizeof(rtadv
->lastadvcurhoplimit
));
2885 memset(&rtadv
->lastadvmanagedflag
, 0,
2886 sizeof(rtadv
->lastadvmanagedflag
));
2887 memset(&rtadv
->lastadvotherconfigflag
, 0,
2888 sizeof(rtadv
->lastadvotherconfigflag
));
2889 memset(&rtadv
->lastadvreachabletime
, 0,
2890 sizeof(rtadv
->lastadvreachabletime
));
2891 memset(&rtadv
->lastadvretranstimer
, 0,
2892 sizeof(rtadv
->lastadvretranstimer
));
2893 rtadv
->AdvDefaultLifetime
= -1; /* derive from MaxRtrAdvInterval */
2894 rtadv
->HomeAgentPreference
= 0;
2895 rtadv
->HomeAgentLifetime
= -1; /* derive from AdvDefaultLifetime */
2896 rtadv
->AdvIntervalOption
= 0;
2897 rtadv
->UseFastRexmit
= true;
2898 rtadv
->DefaultPreference
= RTADV_PREF_MEDIUM
;
2900 rtadv_prefixes_init(rtadv
->prefixes
);
2902 rtadv
->AdvRDNSSList
= list_new();
2903 rtadv
->AdvDNSSLList
= list_new();
2906 void rtadv_if_fini(struct zebra_if
*zif
)
2908 struct rtadvconf
*rtadv
;
2909 struct rtadv_prefix
*rp
;
2911 rtadv
= &zif
->rtadv
;
2913 while ((rp
= rtadv_prefixes_pop(rtadv
->prefixes
)))
2914 rtadv_prefix_free(rp
);
2916 list_delete(&rtadv
->AdvRDNSSList
);
2917 list_delete(&rtadv
->AdvDNSSLList
);
2920 void rtadv_vrf_init(struct zebra_vrf
*zvrf
)
2922 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2925 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2928 void rtadv_vrf_terminate(struct zebra_vrf
*zvrf
)
2930 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2933 rtadv_event(zvrf
, RTADV_STOP
, 0);
2934 if (zvrf
->rtadv
.sock
>= 0) {
2935 close(zvrf
->rtadv
.sock
);
2936 zvrf
->rtadv
.sock
= -1;
2940 adv_msec_if_clean(zvrf
);
2943 void rtadv_cmd_init(void)
2945 interfaces_configured_for_ra_from_bgp
= 0;
2947 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2948 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2950 install_element(VIEW_NODE
, &show_ipv6_nd_ra_if_cmd
);
2952 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2953 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2954 install_element(INTERFACE_NODE
, &ipv6_nd_ra_retrans_interval_cmd
);
2955 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_retrans_interval_cmd
);
2956 install_element(INTERFACE_NODE
, &ipv6_nd_ra_hop_limit_cmd
);
2957 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_hop_limit_cmd
);
2958 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2959 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2960 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2961 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2962 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2963 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2964 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2965 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2966 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2967 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2968 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2969 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2970 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2971 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2972 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2973 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2974 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2975 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2976 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2977 install_element(INTERFACE_NODE
,
2978 &ipv6_nd_adv_interval_config_option_cmd
);
2979 install_element(INTERFACE_NODE
,
2980 &no_ipv6_nd_adv_interval_config_option_cmd
);
2981 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2982 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2983 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2984 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2985 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2986 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2987 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2988 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2989 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2990 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2993 static int if_join_all_router(int sock
, struct interface
*ifp
)
2997 struct ipv6_mreq mreq
;
2999 memset(&mreq
, 0, sizeof(mreq
));
3000 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
3001 mreq
.ipv6mr_interface
= ifp
->ifindex
;
3003 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
3006 flog_err_sys(EC_LIB_SOCKET
,
3007 "%s(%u): Failed to join group, socket %u error %s",
3008 ifp
->name
, ifp
->ifindex
, sock
,
3009 safe_strerror(errno
));
3011 if (IS_ZEBRA_DEBUG_EVENT
)
3013 "%s(%s:%u): Join All-Routers multicast group, socket %u",
3014 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
3019 static int if_leave_all_router(int sock
, struct interface
*ifp
)
3023 struct ipv6_mreq mreq
;
3025 memset(&mreq
, 0, sizeof(mreq
));
3026 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
3027 mreq
.ipv6mr_interface
= ifp
->ifindex
;
3029 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
3034 "%s(%s:%u): Failed to leave group, socket %u error %s",
3035 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
,
3036 safe_strerror(errno
));
3038 if (IS_ZEBRA_DEBUG_EVENT
)
3040 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
3041 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
3046 bool rtadv_compiled_in(void)
3051 #else /* !HAVE_RTADV */
3053 * If the end user does not have RADV enabled we should
3054 * handle this better
3056 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
3058 if (IS_ZEBRA_DEBUG_PACKET
)
3060 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3061 zserv_command_string(hdr
->command
));
3066 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
3068 if (IS_ZEBRA_DEBUG_PACKET
)
3070 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3071 zserv_command_string(hdr
->command
));
3076 bool rtadv_compiled_in(void)
3081 #endif /* HAVE_RTADV */
3083 uint32_t rtadv_get_interfaces_configured_from_bgp(void)
3085 return interfaces_configured_for_ra_from_bgp
;