1 /* Router advertisement
2 * Copyright (C) 2016 Cumulus Networks
3 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
4 * Copyright (C) 1999 Kunihiro Ishiguro
6 * This file is part of GNU Zebra.
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "lib_errors.h"
39 #include "zebra/interface.h"
40 #include "zebra/rtadv.h"
41 #include "zebra/debug.h"
42 #include "zebra/rib.h"
43 #include "zebra/zapi_msg.h"
44 #include "zebra/zebra_vrf.h"
45 #include "zebra/zebra_errors.h"
46 #include "zebra/zebra_router.h"
48 extern struct zebra_privs_t zserv_privs
;
50 static uint32_t interfaces_configured_for_ra_from_bgp
;
52 #if defined(HAVE_RTADV)
54 #ifndef VTYSH_EXTRACT_PL
55 #include "zebra/rtadv_clippy.c"
58 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_PREFIX
, "Router Advertisement Prefix");
59 DEFINE_MTYPE_STATIC(ZEBRA
, ADV_IF
, "Advertised Interface");
62 #include <netinet/icmp6.h>
65 /* If RFC2133 definition is used. */
66 #ifndef IPV6_JOIN_GROUP
67 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
69 #ifndef IPV6_LEAVE_GROUP
70 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
73 #define ALLNODE "ff02::1"
74 #define ALLROUTER "ff02::2"
78 char name
[INTERFACE_NAMSIZ
];
79 struct adv_if_list_item list_item
;
82 static int adv_if_cmp(const struct adv_if
*a
, const struct adv_if
*b
)
84 return if_cmp_name_func(a
->name
, b
->name
);
87 DECLARE_SORTLIST_UNIQ(adv_if_list
, struct adv_if
, list_item
, adv_if_cmp
);
89 static int rtadv_prefix_cmp(const struct rtadv_prefix
*a
,
90 const struct rtadv_prefix
*b
)
92 return prefix_cmp(&a
->prefix
, &b
->prefix
);
95 DECLARE_RBTREE_UNIQ(rtadv_prefixes
, struct rtadv_prefix
, item
,
98 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS");
99 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL");
101 /* Order is intentional. Matches RFC4191. This array is also used for
102 command matching, so only modify with care. */
103 static const char *const rtadv_pref_strs
[] = {
104 "medium", "high", "INVALID", "low", 0
115 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
117 static int if_join_all_router(int, struct interface
*);
118 static int if_leave_all_router(int, struct interface
*);
120 static struct zebra_vrf
*rtadv_interface_get_zvrf(const struct interface
*ifp
)
122 /* We use the default vrf for rtadv handling except in netns */
123 if (!vrf_is_backend_netns())
124 return vrf_info_lookup(VRF_DEFAULT
);
126 return ifp
->vrf
->info
;
129 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
132 struct interface
*iface
;
133 struct zebra_if
*zif
;
135 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
136 if (iface
&& iface
->info
) {
144 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
145 int buflen
, struct sockaddr_in6
*from
,
146 ifindex_t
*ifindex
, int *hoplimit
)
151 struct cmsghdr
*cmsgptr
;
156 /* Fill in message and iovec. */
157 memset(&msg
, 0, sizeof(msg
));
158 msg
.msg_name
= (void *)from
;
159 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
162 msg
.msg_control
= (void *)adata
;
163 msg
.msg_controllen
= sizeof(adata
);
165 iov
.iov_len
= buflen
;
167 /* If recvmsg fail return minus value. */
168 ret
= recvmsg(sock
, &msg
, 0);
172 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
173 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
174 /* I want interface index which this packet comes from. */
175 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
176 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
177 struct in6_pktinfo
*ptr
;
179 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
180 *ifindex
= ptr
->ipi6_ifindex
;
181 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
184 /* Incoming packet's hop limit. */
185 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
186 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
187 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
192 rtadv_increment_received(zvrf
, ifindex
);
196 #define RTADV_MSG_SIZE 4096
198 /* Send router advertisement packet. */
199 static void rtadv_send_packet(int sock
, struct interface
*ifp
,
200 enum ipv6_nd_suppress_ra_status stop
)
204 struct cmsghdr
*cmsgptr
;
205 struct in6_pktinfo
*pkt
;
206 struct sockaddr_in6 addr
;
207 static void *adata
= NULL
;
208 unsigned char buf
[RTADV_MSG_SIZE
];
209 struct nd_router_advert
*rtadv
;
212 struct zebra_if
*zif
;
213 struct rtadv_prefix
*rprefix
;
214 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
215 0, 0, 0, 0, 0, 0, 0, 1};
216 struct listnode
*node
;
217 uint16_t pkt_RouterLifetime
;
220 * Allocate control message bufffer. This is dynamic because
221 * CMSG_SPACE is not guaranteed not to call a function. Note that
222 * the size will be different on different architectures due to
223 * differing alignment rules.
226 /* XXX Free on shutdown. */
227 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
231 "rtadv_send_packet: can't malloc control data");
236 /* Logging of packet. */
237 if (IS_ZEBRA_DEBUG_PACKET
)
238 zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp
->name
,
239 ifp
->vrf
->name
, ifp
->ifindex
, sock
);
241 /* Fill in sockaddr_in6. */
242 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
243 addr
.sin6_family
= AF_INET6
;
245 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
246 #endif /* SIN6_LEN */
247 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
248 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
250 /* Fetch interface information. */
253 /* Make router advertisement message. */
254 rtadv
= (struct nd_router_advert
*)buf
;
256 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
257 rtadv
->nd_ra_code
= 0;
258 rtadv
->nd_ra_cksum
= 0;
260 rtadv
->nd_ra_curhoplimit
= zif
->rtadv
.AdvCurHopLimit
;
262 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
263 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
265 : zif
->rtadv
.DefaultPreference
;
266 rtadv
->nd_ra_flags_reserved
<<= 3;
268 if (zif
->rtadv
.AdvManagedFlag
)
269 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
270 if (zif
->rtadv
.AdvOtherConfigFlag
)
271 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
272 if (zif
->rtadv
.AdvHomeAgentFlag
)
273 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
274 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
275 * AdvDefaultLifetime is by default based on the value of
276 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
277 * field of Router Advertisements. Given that this field is expressed
278 * in seconds, a small MaxRtrAdvInterval value can result in a zero
279 * value for this field. To prevent this, routers SHOULD keep
280 * AdvDefaultLifetime in at least one second, even if the use of
281 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
283 zif
->rtadv
.AdvDefaultLifetime
!= -1
284 ? zif
->rtadv
.AdvDefaultLifetime
285 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
287 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
288 rtadv
->nd_ra_router_lifetime
=
289 (stop
== RA_SUPPRESS
) ? htons(0) : htons(pkt_RouterLifetime
);
290 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
291 rtadv
->nd_ra_retransmit
= htonl(zif
->rtadv
.AdvRetransTimer
);
293 len
= sizeof(struct nd_router_advert
);
295 /* If both the Home Agent Preference and Home Agent Lifetime are set to
296 * their default values specified above, this option SHOULD NOT be
297 * included in the Router Advertisement messages sent by this home
298 * agent. -- RFC6275, 7.4 */
299 if (zif
->rtadv
.AdvHomeAgentFlag
300 && (zif
->rtadv
.HomeAgentPreference
301 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
302 struct nd_opt_homeagent_info
*ndopt_hai
=
303 (struct nd_opt_homeagent_info
*)(buf
+ len
);
304 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
305 ndopt_hai
->nd_opt_hai_len
= 1;
306 ndopt_hai
->nd_opt_hai_reserved
= 0;
307 ndopt_hai
->nd_opt_hai_preference
=
308 htons(zif
->rtadv
.HomeAgentPreference
);
309 /* 16-bit unsigned integer. The lifetime associated with the
311 * agent in units of seconds. The default value is the same as
313 * Router Lifetime, as specified in the main body of the Router
314 * Advertisement. The maximum value corresponds to 18.2 hours.
316 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
317 ndopt_hai
->nd_opt_hai_lifetime
=
318 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
319 ? zif
->rtadv
.HomeAgentLifetime
320 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
325 len
+= sizeof(struct nd_opt_homeagent_info
);
328 if (zif
->rtadv
.AdvIntervalOption
) {
329 struct nd_opt_adv_interval
*ndopt_adv
=
330 (struct nd_opt_adv_interval
*)(buf
+ len
);
331 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
332 ndopt_adv
->nd_opt_ai_len
= 1;
333 ndopt_adv
->nd_opt_ai_reserved
= 0;
334 ndopt_adv
->nd_opt_ai_interval
=
335 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
336 len
+= sizeof(struct nd_opt_adv_interval
);
339 /* Fill in prefix. */
340 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
341 struct nd_opt_prefix_info
*pinfo
;
343 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
345 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
346 pinfo
->nd_opt_pi_len
= 4;
347 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
349 pinfo
->nd_opt_pi_flags_reserved
= 0;
350 if (rprefix
->AdvOnLinkFlag
)
351 pinfo
->nd_opt_pi_flags_reserved
|=
352 ND_OPT_PI_FLAG_ONLINK
;
353 if (rprefix
->AdvAutonomousFlag
)
354 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
355 if (rprefix
->AdvRouterAddressFlag
)
356 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
358 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
359 pinfo
->nd_opt_pi_preferred_time
=
360 htonl(rprefix
->AdvPreferredLifetime
);
361 pinfo
->nd_opt_pi_reserved2
= 0;
363 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
364 &rprefix
->prefix
.prefix
);
366 len
+= sizeof(struct nd_opt_prefix_info
);
369 /* Hardware address. */
370 if (ifp
->hw_addr_len
!= 0) {
371 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
373 /* Option length should be rounded up to next octet if
374 the link address does not end on an octet boundary. */
375 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
377 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
378 len
+= ifp
->hw_addr_len
;
380 /* Pad option to end on an octet boundary. */
381 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
382 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
386 if (zif
->rtadv
.AdvLinkMTU
) {
387 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
388 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
389 opt
->nd_opt_mtu_len
= 1;
390 opt
->nd_opt_mtu_reserved
= 0;
391 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
392 len
+= sizeof(struct nd_opt_mtu
);
396 * There is no limit on the number of configurable recursive DNS
397 * servers or search list entries. We don't want the RA message
398 * to exceed the link's MTU (risking fragmentation) or even
399 * blow the stack buffer allocated for it.
401 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
403 /* Recursive DNS servers */
404 struct rtadv_rdnss
*rdnss
;
406 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
408 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
410 if (len
+ opt_len
> max_len
) {
412 "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
413 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
);
416 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
418 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
419 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
420 opt
->nd_opt_rdnss_reserved
= 0;
421 opt
->nd_opt_rdnss_lifetime
= htonl(
424 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
426 len
+= sizeof(struct nd_opt_rdnss
);
428 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
429 len
+= sizeof(struct in6_addr
);
432 /* DNS search list */
433 struct rtadv_dnssl
*dnssl
;
435 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
436 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
437 + ((dnssl
->encoded_len
+ 7) & ~7);
439 if (len
+ opt_len
> max_len
) {
441 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
442 ifp
->name
, ifp
->ifindex
);
445 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
447 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
448 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
449 opt
->nd_opt_dnssl_reserved
= 0;
450 opt
->nd_opt_dnssl_lifetime
= htonl(
453 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
455 len
+= sizeof(struct nd_opt_dnssl
);
457 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
458 len
+= dnssl
->encoded_len
;
460 /* Zero-pad to 8-octet boundary */
467 msg
.msg_name
= (void *)&addr
;
468 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
471 msg
.msg_control
= (void *)adata
;
472 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
477 cmsgptr
= CMSG_FIRSTHDR(&msg
);
478 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
479 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
480 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
482 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
483 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
484 pkt
->ipi6_ifindex
= ifp
->ifindex
;
486 ret
= sendmsg(sock
, &msg
, 0);
488 flog_err_sys(EC_LIB_SOCKET
,
489 "%s(%u): Tx RA failed, socket %u error %d (%s)",
490 ifp
->name
, ifp
->ifindex
, sock
, errno
,
491 safe_strerror(errno
));
496 static void rtadv_timer(struct thread
*thread
)
498 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
500 struct interface
*ifp
;
501 struct zebra_if
*zif
;
504 zvrf
->rtadv
.ra_timer
= NULL
;
505 if (adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
) == 0) {
506 period
= 1000; /* 1 s */
507 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
509 period
= 10; /* 10 ms */
510 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
513 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
514 FOR_ALL_INTERFACES (vrf
, ifp
) {
515 if (if_is_loopback(ifp
) || !if_is_operative(ifp
) ||
516 IS_ZEBRA_IF_BRIDGE_SLAVE(ifp
) ||
517 !connected_get_linklocal(ifp
) ||
518 (vrf_is_backend_netns() &&
519 ifp
->vrf
->vrf_id
!= zvrf
->vrf
->vrf_id
))
524 if (zif
->rtadv
.AdvSendAdvertisements
) {
525 if (zif
->rtadv
.inFastRexmit
526 && zif
->rtadv
.UseFastRexmit
) {
527 /* We assume we fast rexmit every sec so
530 if (--zif
->rtadv
.NumFastReXmitsRemain
532 zif
->rtadv
.inFastRexmit
= 0;
534 if (IS_ZEBRA_DEBUG_SEND
)
536 "Fast RA Rexmit on interface %s(%s:%u)",
541 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
,
544 zif
->rtadv
.AdvIntervalTimer
-= period
;
545 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
547 MaxRtrAdvInterval each
548 time isn't what section
549 6.2.4 of RFC4861 tells to do.
551 zif
->rtadv
.AdvIntervalTimer
=
555 zvrf
->rtadv
.sock
, ifp
,
563 static void rtadv_process_solicit(struct interface
*ifp
)
565 struct zebra_vrf
*zvrf
;
566 struct zebra_if
*zif
;
568 zvrf
= rtadv_interface_get_zvrf(ifp
);
573 * If FastRetransmit is enabled, send the RA immediately.
574 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
575 * (3 seconds) since the last RA was sent, send it now and reset
576 * the timer to start at the max (configured) again.
577 * If not enabled and it is less than 3 seconds since the last
578 * RA packet was sent, set the timer for 3 seconds so the next
579 * one will be sent with a minimum of 3 seconds between RAs.
582 if ((zif
->rtadv
.UseFastRexmit
)
583 || (zif
->rtadv
.AdvIntervalTimer
<=
584 (zif
->rtadv
.MaxRtrAdvInterval
- MIN_DELAY_BETWEEN_RAS
))) {
585 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_ENABLE
);
586 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
588 zif
->rtadv
.AdvIntervalTimer
= MIN_DELAY_BETWEEN_RAS
;
592 * This function processes optional attributes off of
593 * end of a RA packet received. At this point in
594 * time we only care about this in one situation
595 * which is when a interface does not have a LL
596 * v6 address. We still need to be able to install
597 * the mac address for v4 to v6 resolution
599 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
600 struct interface
*ifp
,
601 struct sockaddr_in6
*addr
)
606 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
608 switch(opt_hdr
->nd_opt_type
) {
609 case ND_OPT_SOURCE_LINKADDR
:
610 mac
= (char *)(optional
+2);
611 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
612 &addr
->sin6_addr
, 1);
618 len
-= 8 * opt_hdr
->nd_opt_len
;
619 optional
+= 8 * opt_hdr
->nd_opt_len
;
623 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
624 struct interface
*ifp
,
625 struct sockaddr_in6
*addr
)
627 struct nd_router_advert
*radvert
;
628 char addr_str
[INET6_ADDRSTRLEN
];
629 struct zebra_if
*zif
;
634 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
636 if (len
< sizeof(struct nd_router_advert
)) {
637 if (IS_ZEBRA_DEBUG_PACKET
)
639 "%s(%s:%u): Rx RA with invalid length %d from %s",
640 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, len
,
645 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
646 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
647 len
- sizeof(struct nd_router_advert
),
649 if (IS_ZEBRA_DEBUG_PACKET
)
651 "%s(%s:%u): Rx RA with non-linklocal source address from %s",
652 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
,
657 radvert
= (struct nd_router_advert
*)msg
;
659 #define SIXHOUR2USEC (int64_t)6 * 60 * 60 * 1000000
661 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
) &&
662 (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
) &&
663 (monotime_since(&zif
->rtadv
.lastadvcurhoplimit
, NULL
) >
665 zif
->rtadv
.lastadvcurhoplimit
.tv_sec
== 0)) {
667 EC_ZEBRA_RA_PARAM_MISMATCH
,
668 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
669 ifp
->name
, ifp
->ifindex
, addr_str
);
670 monotime(&zif
->rtadv
.lastadvcurhoplimit
);
673 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
) &&
674 !zif
->rtadv
.AdvManagedFlag
&&
675 (monotime_since(&zif
->rtadv
.lastadvmanagedflag
, NULL
) >
677 zif
->rtadv
.lastadvmanagedflag
.tv_sec
== 0)) {
679 EC_ZEBRA_RA_PARAM_MISMATCH
,
680 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
681 ifp
->name
, ifp
->ifindex
, addr_str
);
682 monotime(&zif
->rtadv
.lastadvmanagedflag
);
685 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
) &&
686 !zif
->rtadv
.AdvOtherConfigFlag
&&
687 (monotime_since(&zif
->rtadv
.lastadvotherconfigflag
, NULL
) >
689 zif
->rtadv
.lastadvotherconfigflag
.tv_sec
== 0)) {
691 EC_ZEBRA_RA_PARAM_MISMATCH
,
692 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
693 ifp
->name
, ifp
->ifindex
, addr_str
);
694 monotime(&zif
->rtadv
.lastadvotherconfigflag
);
697 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
) &&
698 (ntohl(radvert
->nd_ra_reachable
) != zif
->rtadv
.AdvReachableTime
) &&
699 (monotime_since(&zif
->rtadv
.lastadvreachabletime
, NULL
) >
701 zif
->rtadv
.lastadvreachabletime
.tv_sec
== 0)) {
703 EC_ZEBRA_RA_PARAM_MISMATCH
,
704 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
705 ifp
->name
, ifp
->ifindex
, addr_str
);
706 monotime(&zif
->rtadv
.lastadvreachabletime
);
709 if ((ntohl(radvert
->nd_ra_retransmit
) !=
710 (unsigned int)zif
->rtadv
.AdvRetransTimer
) &&
711 (monotime_since(&zif
->rtadv
.lastadvretranstimer
, NULL
) >
713 zif
->rtadv
.lastadvretranstimer
.tv_sec
== 0)) {
715 EC_ZEBRA_RA_PARAM_MISMATCH
,
716 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
717 ifp
->name
, ifp
->ifindex
, addr_str
);
718 monotime(&zif
->rtadv
.lastadvretranstimer
);
721 /* Create entry for neighbor if not known. */
723 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
724 p
.prefixlen
= IPV6_MAX_BITLEN
;
726 if (!nbr_connected_check(ifp
, &p
))
727 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
731 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
732 ifindex_t ifindex
, int hoplimit
,
733 struct sockaddr_in6
*from
,
734 struct zebra_vrf
*zvrf
)
736 struct icmp6_hdr
*icmph
;
737 struct interface
*ifp
;
738 struct zebra_if
*zif
;
739 char addr_str
[INET6_ADDRSTRLEN
];
741 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
743 /* Interface search. */
744 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
746 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
747 "RA/RS received on unknown IF %u from %s", ifindex
,
752 if (IS_ZEBRA_DEBUG_PACKET
)
753 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp
->name
,
754 ifp
->vrf
->name
, ifp
->ifindex
, len
, addr_str
);
756 if (if_is_loopback(ifp
))
759 /* Check interface configuration. */
761 if (!zif
->rtadv
.AdvSendAdvertisements
)
764 /* ICMP message length check. */
765 if (len
< sizeof(struct icmp6_hdr
)) {
767 "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
768 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, len
);
772 icmph
= (struct icmp6_hdr
*)buf
;
774 /* ICMP message type check. */
775 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
776 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
777 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
778 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
,
783 /* Hoplimit check. */
784 if (hoplimit
>= 0 && hoplimit
!= 255) {
785 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
786 ifp
->vrf
->name
, ifp
->ifindex
, hoplimit
);
790 /* Check ICMP message type. */
791 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
792 rtadv_process_solicit(ifp
);
793 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
794 rtadv_process_advert(buf
, len
, ifp
, from
);
799 static void rtadv_read(struct thread
*thread
)
803 uint8_t buf
[RTADV_MSG_SIZE
];
804 struct sockaddr_in6 from
;
805 ifindex_t ifindex
= 0;
807 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
809 sock
= THREAD_FD(thread
);
810 zvrf
->rtadv
.ra_read
= NULL
;
812 /* Register myself. */
813 rtadv_event(zvrf
, RTADV_READ
, 0);
815 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
819 flog_err_sys(EC_LIB_SOCKET
,
820 "RA/RS recv failed, socket %u error %s", sock
,
821 safe_strerror(errno
));
825 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
828 static int rtadv_make_socket(ns_id_t ns_id
)
832 struct icmp6_filter filter
;
835 frr_with_privs(&zserv_privs
) {
837 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
839 * with privs might set errno too if it fails save
846 zlog_warn("RTADV socket for ns: %u failure to create: %s(%u)",
847 ns_id
, safe_strerror(error
), error
);
851 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
853 zlog_warn("RTADV failure to set Packet Information");
857 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
859 zlog_warn("RTADV failure to set multicast Loop detection");
863 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
865 zlog_warn("RTADV failure to set maximum unicast hops");
869 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
871 zlog_warn("RTADV failure to set maximum multicast hops");
875 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
877 zlog_warn("RTADV failure to set maximum incoming hop limit");
882 ICMP6_FILTER_SETBLOCKALL(&filter
);
883 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
884 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
886 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
887 sizeof(struct icmp6_filter
));
889 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
897 static struct adv_if
*adv_if_new(const char *name
)
901 new = XCALLOC(MTYPE_ADV_IF
, sizeof(struct adv_if
));
903 strlcpy(new->name
, name
, sizeof(new->name
));
908 static void adv_if_free(struct adv_if
*adv_if
)
910 XFREE(MTYPE_ADV_IF
, adv_if
);
913 static bool adv_if_is_empty_internal(const struct adv_if_list_head
*adv_if_head
)
915 return adv_if_list_count(adv_if_head
) ? false : true;
918 static struct adv_if
*adv_if_add_internal(struct adv_if_list_head
*adv_if_head
,
921 struct adv_if adv_if_lookup
= {};
922 struct adv_if
*adv_if
= NULL
;
924 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
925 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
930 adv_if
= adv_if_new(adv_if_lookup
.name
);
931 adv_if_list_add(adv_if_head
, adv_if
);
936 static struct adv_if
*adv_if_del_internal(struct adv_if_list_head
*adv_if_head
,
939 struct adv_if adv_if_lookup
= {};
940 struct adv_if
*adv_if
= NULL
;
942 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
943 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
948 adv_if_list_del(adv_if_head
, adv_if
);
953 static void adv_if_clean_internal(struct adv_if_list_head
*adv_if_head
)
955 struct adv_if
*node
= NULL
;
957 if (!adv_if_is_empty_internal(adv_if_head
)) {
958 frr_each_safe (adv_if_list
, adv_if_head
, node
) {
959 adv_if_list_del(adv_if_head
, node
);
964 adv_if_list_fini(adv_if_head
);
969 * Add to list. On Success, return NULL, otherwise return already existing
972 static struct adv_if
*adv_if_add(struct zebra_vrf
*zvrf
, const char *name
)
974 struct adv_if
*adv_if
= NULL
;
976 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_if
, name
);
981 if (IS_ZEBRA_DEBUG_EVENT
) {
982 struct vrf
*vrf
= zvrf
->vrf
;
984 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
985 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
986 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
993 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
996 static struct adv_if
*adv_if_del(struct zebra_vrf
*zvrf
, const char *name
)
998 struct adv_if
*adv_if
= NULL
;
1000 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_if
, name
);
1005 if (IS_ZEBRA_DEBUG_EVENT
) {
1006 struct vrf
*vrf
= zvrf
->vrf
;
1008 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1009 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1010 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1017 * Add to list. On Success, return NULL, otherwise return already existing
1020 static struct adv_if
*adv_msec_if_add(struct zebra_vrf
*zvrf
, const char *name
)
1022 struct adv_if
*adv_if
= NULL
;
1024 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1029 if (IS_ZEBRA_DEBUG_EVENT
) {
1030 struct vrf
*vrf
= zvrf
->vrf
;
1032 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1033 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1034 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1041 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1044 static struct adv_if
*adv_msec_if_del(struct zebra_vrf
*zvrf
, const char *name
)
1046 struct adv_if
*adv_if
= NULL
;
1048 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_msec_if
, name
);
1053 if (IS_ZEBRA_DEBUG_EVENT
) {
1054 struct vrf
*vrf
= zvrf
->vrf
;
1056 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
1057 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
1058 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1064 /* Clean adv_if list, called on vrf terminate */
1065 static void adv_if_clean(struct zebra_vrf
*zvrf
)
1067 if (IS_ZEBRA_DEBUG_EVENT
) {
1068 struct vrf
*vrf
= zvrf
->vrf
;
1070 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1071 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1072 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1075 adv_if_clean_internal(&zvrf
->rtadv
.adv_if
);
1078 /* Clean adv_msec_if list, called on vrf terminate */
1079 static void adv_msec_if_clean(struct zebra_vrf
*zvrf
)
1081 if (IS_ZEBRA_DEBUG_EVENT
) {
1082 struct vrf
*vrf
= zvrf
->vrf
;
1084 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1085 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1086 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1089 adv_if_clean_internal(&zvrf
->rtadv
.adv_msec_if
);
1092 static struct rtadv_prefix
*rtadv_prefix_new(void)
1094 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
1097 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
1099 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
1102 static struct rtadv_prefix
*rtadv_prefix_get(struct rtadv_prefixes_head
*list
,
1103 struct prefix_ipv6
*p
)
1105 struct rtadv_prefix
*rprefix
, ref
;
1109 rprefix
= rtadv_prefixes_find(list
, &ref
);
1113 rprefix
= rtadv_prefix_new();
1114 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
1115 rtadv_prefixes_add(list
, rprefix
);
1120 static void rtadv_prefix_set_defaults(struct rtadv_prefix
*rp
)
1122 rp
->AdvAutonomousFlag
= 1;
1123 rp
->AdvOnLinkFlag
= 1;
1124 rp
->AdvRouterAddressFlag
= 0;
1125 rp
->AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1126 rp
->AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1129 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1131 struct rtadv_prefix
*rprefix
;
1133 rprefix
= rtadv_prefix_get(zif
->rtadv
.prefixes
, &rp
->prefix
);
1136 * Set parameters based on where the prefix is created.
1137 * If auto-created based on kernel address addition, set the
1138 * default values. If created from a manual "ipv6 nd prefix"
1139 * command, take the parameters from the manual command. Note
1140 * that if the manual command exists, the default values will
1141 * not overwrite the manual values.
1143 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1144 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_AUTO
)
1145 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1147 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1149 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
1150 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
1151 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
1152 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
1153 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
1154 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1155 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
1156 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1158 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1159 rtadv_prefix_set_defaults(rprefix
);
1164 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1166 struct rtadv_prefix
*rprefix
;
1168 rprefix
= rtadv_prefixes_find(zif
->rtadv
.prefixes
, rp
);
1169 if (rprefix
!= NULL
) {
1172 * When deleting an address from the list, need to take care
1173 * it wasn't defined both automatically via kernel
1174 * address addition as well as manually by vtysh cli. If both,
1175 * we don't actually delete but may change the parameters
1176 * back to default if a manually defined entry is deleted.
1178 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1179 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1180 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1181 rtadv_prefix_set_defaults(rprefix
);
1184 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1185 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1186 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1191 rtadv_prefixes_del(zif
->rtadv
.prefixes
, rprefix
);
1192 rtadv_prefix_free(rprefix
);
1198 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
1199 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
1201 struct rtadv_prefix rp
;
1204 apply_mask_ipv6(&rp
.prefix
);
1205 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1206 rtadv_prefix_set(zif
, &rp
);
1209 /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
1210 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
1212 struct rtadv_prefix rp
;
1214 rp
.prefix
= *((struct prefix_ipv6
*)p
);
1215 apply_mask_ipv6(&rp
.prefix
);
1216 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1217 rtadv_prefix_reset(zif
, &rp
);
1220 static void rtadv_start_interface_events(struct zebra_vrf
*zvrf
,
1221 struct zebra_if
*zif
)
1223 struct adv_if
*adv_if
= NULL
;
1225 if (zif
->ifp
->ifindex
== IFINDEX_INTERNAL
) {
1226 if (IS_ZEBRA_DEBUG_EVENT
)
1228 "%s(%s) has not configured an ifindex yet, delaying until we have one",
1229 zif
->ifp
->name
, zvrf
->vrf
->name
);
1233 adv_if
= adv_if_add(zvrf
, zif
->ifp
->name
);
1235 return; /* Already added */
1237 if_join_all_router(zvrf
->rtadv
.sock
, zif
->ifp
);
1239 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 1)
1240 rtadv_event(zvrf
, RTADV_START
, 0);
1243 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
1244 enum ipv6_nd_suppress_ra_status status
)
1246 struct zebra_if
*zif
;
1247 struct zebra_vrf
*zvrf
;
1248 struct adv_if
*adv_if
= NULL
;
1252 zvrf
= rtadv_interface_get_zvrf(ifp
);
1254 if (status
== RA_SUPPRESS
) {
1255 /* RA is currently enabled */
1256 if (zif
->rtadv
.AdvSendAdvertisements
) {
1257 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1258 zif
->rtadv
.AdvSendAdvertisements
= 0;
1259 zif
->rtadv
.AdvIntervalTimer
= 0;
1261 adv_if
= adv_if_del(zvrf
, ifp
->name
);
1263 return; /* Nothing to delete */
1265 adv_if_free(adv_if
);
1267 if_leave_all_router(zvrf
->rtadv
.sock
, ifp
);
1269 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 0)
1270 rtadv_event(zvrf
, RTADV_STOP
, 0);
1273 if (!zif
->rtadv
.AdvSendAdvertisements
) {
1274 zif
->rtadv
.AdvSendAdvertisements
= 1;
1275 zif
->rtadv
.AdvIntervalTimer
= 0;
1276 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
1277 && zif
->rtadv
.UseFastRexmit
) {
1279 * Enable Fast RA only when RA interval is in
1280 * secs and Fast RA retransmit is enabled
1282 zif
->rtadv
.inFastRexmit
= 1;
1283 zif
->rtadv
.NumFastReXmitsRemain
=
1284 RTADV_NUM_FAST_REXMITS
;
1287 rtadv_start_interface_events(zvrf
, zif
);
1293 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1294 * Note that while the client could request RA on an interface on which the
1295 * operator has not enabled RA, RA won't be disabled upon client request
1296 * if the operator has explicitly enabled RA. The enable request can also
1297 * specify a RA interval (in seconds).
1299 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
1303 struct interface
*ifp
;
1304 struct zebra_if
*zif
;
1305 uint32_t ra_interval
;
1309 /* Get interface index and RA interval. */
1310 STREAM_GETL(s
, ifindex
);
1311 STREAM_GETL(s
, ra_interval
);
1313 if (IS_ZEBRA_DEBUG_EVENT
) {
1314 struct vrf
*vrf
= zvrf
->vrf
;
1316 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1317 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1318 enable
? "enable" : "disable",
1319 zebra_route_string(client
->proto
), ra_interval
);
1322 /* Locate interface and check VRF match. */
1323 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
1325 struct vrf
*vrf
= zvrf
->vrf
;
1327 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
1328 "%s:%u: IF %u RA %s client %s - interface unknown",
1329 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1330 enable
? "enable" : "disable",
1331 zebra_route_string(client
->proto
));
1334 if (vrf_is_backend_netns() && ifp
->vrf
->vrf_id
!= zvrf_id(zvrf
)) {
1336 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1337 ifp
->vrf
->name
, zvrf_id(zvrf
), ifindex
,
1338 enable
? "enable" : "disable",
1339 zebra_route_string(client
->proto
), ifp
->vrf
->vrf_id
);
1345 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1346 interfaces_configured_for_ra_from_bgp
++;
1348 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1349 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1351 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1352 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1353 VTY_RA_INTERVAL_CONFIGURED
))
1354 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1356 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1357 interfaces_configured_for_ra_from_bgp
--;
1359 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1360 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1361 VTY_RA_INTERVAL_CONFIGURED
))
1362 zif
->rtadv
.MaxRtrAdvInterval
=
1363 RTADV_MAX_RTR_ADV_INTERVAL
;
1364 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1365 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1372 * send router lifetime value of zero in RAs on this interface since we're
1373 * ceasing to advertise and want to let our neighbors know.
1374 * RFC 4861 secion 6.2.5
1376 void rtadv_stop_ra(struct interface
*ifp
)
1378 struct zebra_if
*zif
;
1379 struct zebra_vrf
*zvrf
;
1382 zvrf
= rtadv_interface_get_zvrf(ifp
);
1384 if (zif
->rtadv
.AdvSendAdvertisements
)
1385 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1389 * Send router lifetime value of zero in RAs on all interfaces since we're
1390 * ceasing to advertise globally and want to let all of our neighbors know
1391 * RFC 4861 secion 6.2.5
1393 * Delete all ipv6 global prefixes added to the router advertisement prefix
1394 * lists prior to ceasing.
1396 void rtadv_stop_ra_all(void)
1399 struct interface
*ifp
;
1400 struct zebra_if
*zif
;
1401 struct rtadv_prefix
*rprefix
;
1403 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1404 FOR_ALL_INTERFACES (vrf
, ifp
) {
1407 frr_each_safe (rtadv_prefixes
, zif
->rtadv
.prefixes
,
1409 rtadv_prefix_reset(zif
, rprefix
);
1415 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1417 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1419 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1421 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1424 static void show_zvrf_rtadv_adv_if_helper(struct vty
*vty
,
1425 struct adv_if_list_head
*adv_if_head
)
1427 struct adv_if
*node
= NULL
;
1429 if (!adv_if_is_empty_internal(adv_if_head
)) {
1430 frr_each (adv_if_list
, adv_if_head
, node
) {
1431 vty_out(vty
, " %s\n", node
->name
);
1438 static void show_zvrf_rtadv_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
)
1440 vty_out(vty
, "VRF: %s\n", zvrf_name(zvrf
));
1441 vty_out(vty
, " Interfaces:\n");
1442 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_if
);
1444 vty_out(vty
, " Interfaces(msec):\n");
1445 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_msec_if
);
1448 DEFPY(show_ipv6_nd_ra_if
, show_ipv6_nd_ra_if_cmd
,
1449 "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
1451 "Neighbor discovery\n"
1452 "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR
)
1454 struct zebra_vrf
*zvrf
= NULL
;
1456 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1458 "%% VRF subcommand only applicable for netns-based vrfs.\n");
1465 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1466 struct zebra_vrf
*zvrf
;
1472 show_zvrf_rtadv_helper(vty
, zvrf
);
1479 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1481 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1484 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1489 show_zvrf_rtadv_helper(vty
, zvrf
);
1494 DEFUN (ipv6_nd_ra_fast_retrans
,
1495 ipv6_nd_ra_fast_retrans_cmd
,
1496 "ipv6 nd ra-fast-retrans",
1497 "Interface IPv6 config commands\n"
1498 "Neighbor discovery\n"
1499 "Fast retransmit of RA packets\n")
1501 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1502 struct zebra_if
*zif
= ifp
->info
;
1504 if (if_is_loopback(ifp
)) {
1506 "Cannot configure IPv6 Router Advertisements on this interface\n");
1507 return CMD_WARNING_CONFIG_FAILED
;
1510 zif
->rtadv
.UseFastRexmit
= true;
1515 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1516 no_ipv6_nd_ra_fast_retrans_cmd
,
1517 "no ipv6 nd ra-fast-retrans",
1519 "Interface IPv6 config commands\n"
1520 "Neighbor discovery\n"
1521 "Fast retransmit of RA packets\n")
1523 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1524 struct zebra_if
*zif
= ifp
->info
;
1526 if (if_is_loopback(ifp
)) {
1528 "Cannot configure IPv6 Router Advertisements on this interface\n");
1529 return CMD_WARNING_CONFIG_FAILED
;
1532 zif
->rtadv
.UseFastRexmit
= false;
1537 DEFPY (ipv6_nd_ra_hop_limit
,
1538 ipv6_nd_ra_hop_limit_cmd
,
1539 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1540 "Interface IPv6 config commands\n"
1541 "Neighbor discovery\n"
1542 "Advertisement Hop Limit\n"
1543 "Advertisement Hop Limit in hops (default:64)\n")
1545 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1546 struct zebra_if
*zif
= ifp
->info
;
1548 if (if_is_loopback(ifp
)) {
1550 "Cannot configure IPv6 Router Advertisements on this interface\n");
1551 return CMD_WARNING_CONFIG_FAILED
;
1554 zif
->rtadv
.AdvCurHopLimit
= hopcount
;
1559 DEFPY (no_ipv6_nd_ra_hop_limit
,
1560 no_ipv6_nd_ra_hop_limit_cmd
,
1561 "no ipv6 nd ra-hop-limit [(0-255)]",
1563 "Interface IPv6 config commands\n"
1564 "Neighbor discovery\n"
1565 "Advertisement Hop Limit\n"
1566 "Advertisement Hop Limit in hops\n")
1568 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1569 struct zebra_if
*zif
= ifp
->info
;
1571 if (if_is_loopback(ifp
)) {
1573 "Cannot configure IPv6 Router Advertisements on this interface\n");
1574 return CMD_WARNING_CONFIG_FAILED
;
1577 zif
->rtadv
.AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
1582 DEFPY (ipv6_nd_ra_retrans_interval
,
1583 ipv6_nd_ra_retrans_interval_cmd
,
1584 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1585 "Interface IPv6 config commands\n"
1586 "Neighbor discovery\n"
1587 "Advertisement Retransmit Interval\n"
1588 "Advertisement Retransmit Interval in msec\n")
1590 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1591 struct zebra_if
*zif
= ifp
->info
;
1593 if (if_is_loopback(ifp
)) {
1595 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1596 return CMD_WARNING_CONFIG_FAILED
;
1599 zif
->rtadv
.AdvRetransTimer
= interval
;
1604 DEFPY (no_ipv6_nd_ra_retrans_interval
,
1605 no_ipv6_nd_ra_retrans_interval_cmd
,
1606 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1608 "Interface IPv6 config commands\n"
1609 "Neighbor discovery\n"
1610 "Advertisement Retransmit Interval\n"
1611 "Advertisement Retransmit Interval in msec\n")
1613 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1614 struct zebra_if
*zif
= ifp
->info
;
1616 if (if_is_loopback(ifp
)) {
1618 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1619 return CMD_WARNING_CONFIG_FAILED
;
1622 zif
->rtadv
.AdvRetransTimer
= 0;
1627 DEFUN (ipv6_nd_suppress_ra
,
1628 ipv6_nd_suppress_ra_cmd
,
1629 "ipv6 nd suppress-ra",
1630 "Interface IPv6 config commands\n"
1631 "Neighbor discovery\n"
1632 "Suppress Router Advertisement\n")
1634 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1635 struct zebra_if
*zif
= ifp
->info
;
1637 if (if_is_loopback(ifp
)) {
1639 "Cannot configure IPv6 Router Advertisements on this interface\n");
1640 return CMD_WARNING_CONFIG_FAILED
;
1643 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1644 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1646 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1650 DEFUN (no_ipv6_nd_suppress_ra
,
1651 no_ipv6_nd_suppress_ra_cmd
,
1652 "no ipv6 nd suppress-ra",
1654 "Interface IPv6 config commands\n"
1655 "Neighbor discovery\n"
1656 "Suppress Router Advertisement\n")
1658 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1659 struct zebra_if
*zif
= ifp
->info
;
1661 if (if_is_loopback(ifp
)) {
1663 "Cannot configure IPv6 Router Advertisements on this interface\n");
1664 return CMD_WARNING_CONFIG_FAILED
;
1667 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1668 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1672 DEFUN (ipv6_nd_ra_interval_msec
,
1673 ipv6_nd_ra_interval_msec_cmd
,
1674 "ipv6 nd ra-interval msec (70-1800000)",
1675 "Interface IPv6 config commands\n"
1676 "Neighbor discovery\n"
1677 "Router Advertisement interval\n"
1678 "Router Advertisement interval in milliseconds\n"
1679 "Router Advertisement interval in milliseconds\n")
1682 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1684 struct zebra_if
*zif
= ifp
->info
;
1685 struct zebra_vrf
*zvrf
;
1686 struct adv_if
*adv_if
;
1688 zvrf
= rtadv_interface_get_zvrf(ifp
);
1690 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1691 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1692 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1694 "This ra-interval would conflict with configured ra-lifetime!\n");
1695 return CMD_WARNING_CONFIG_FAILED
;
1698 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1699 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1701 adv_if_free(adv_if
);
1704 if (interval
% 1000)
1705 (void)adv_msec_if_add(zvrf
, ifp
->name
);
1707 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1708 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1709 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1710 zif
->rtadv
.AdvIntervalTimer
= 0;
1715 DEFUN (ipv6_nd_ra_interval
,
1716 ipv6_nd_ra_interval_cmd
,
1717 "ipv6 nd ra-interval (1-1800)",
1718 "Interface IPv6 config commands\n"
1719 "Neighbor discovery\n"
1720 "Router Advertisement interval\n"
1721 "Router Advertisement interval in seconds\n")
1724 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1726 struct zebra_if
*zif
= ifp
->info
;
1727 struct zebra_vrf
*zvrf
;
1728 struct adv_if
*adv_if
;
1730 zvrf
= rtadv_interface_get_zvrf(ifp
);
1732 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1733 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1734 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1736 "This ra-interval would conflict with configured ra-lifetime!\n");
1737 return CMD_WARNING_CONFIG_FAILED
;
1740 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1741 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1743 adv_if_free(adv_if
);
1746 /* convert to milliseconds */
1747 interval
= interval
* 1000;
1749 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1750 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1751 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1752 zif
->rtadv
.AdvIntervalTimer
= 0;
1757 DEFUN (no_ipv6_nd_ra_interval
,
1758 no_ipv6_nd_ra_interval_cmd
,
1759 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1761 "Interface IPv6 config commands\n"
1762 "Neighbor discovery\n"
1763 "Router Advertisement interval\n"
1764 "Router Advertisement interval in seconds\n"
1765 "Specify millisecond router advertisement interval\n"
1766 "Router Advertisement interval in milliseconds\n")
1768 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1769 struct zebra_if
*zif
= ifp
->info
;
1770 struct zebra_vrf
*zvrf
= NULL
;
1771 struct adv_if
*adv_if
;
1773 zvrf
= rtadv_interface_get_zvrf(ifp
);
1775 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1776 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1778 adv_if_free(adv_if
);
1781 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1783 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1784 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1786 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1788 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1789 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1794 DEFUN (ipv6_nd_ra_lifetime
,
1795 ipv6_nd_ra_lifetime_cmd
,
1796 "ipv6 nd ra-lifetime (0-9000)",
1797 "Interface IPv6 config commands\n"
1798 "Neighbor discovery\n"
1800 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1803 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1804 struct zebra_if
*zif
= ifp
->info
;
1807 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1809 /* The value to be placed in the Router Lifetime field
1810 * of Router Advertisements sent from the interface,
1811 * in seconds. MUST be either zero or between
1812 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1813 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1815 "This ra-lifetime would conflict with configured ra-interval\n");
1816 return CMD_WARNING_CONFIG_FAILED
;
1819 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1824 DEFUN (no_ipv6_nd_ra_lifetime
,
1825 no_ipv6_nd_ra_lifetime_cmd
,
1826 "no ipv6 nd ra-lifetime [(0-9000)]",
1828 "Interface IPv6 config commands\n"
1829 "Neighbor discovery\n"
1831 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1833 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1834 struct zebra_if
*zif
= ifp
->info
;
1836 zif
->rtadv
.AdvDefaultLifetime
= -1;
1841 DEFUN (ipv6_nd_reachable_time
,
1842 ipv6_nd_reachable_time_cmd
,
1843 "ipv6 nd reachable-time (1-3600000)",
1844 "Interface IPv6 config commands\n"
1845 "Neighbor discovery\n"
1847 "Reachable time in milliseconds\n")
1850 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1851 struct zebra_if
*zif
= ifp
->info
;
1852 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1856 DEFUN (no_ipv6_nd_reachable_time
,
1857 no_ipv6_nd_reachable_time_cmd
,
1858 "no ipv6 nd reachable-time [(1-3600000)]",
1860 "Interface IPv6 config commands\n"
1861 "Neighbor discovery\n"
1863 "Reachable time in milliseconds\n")
1865 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1866 struct zebra_if
*zif
= ifp
->info
;
1868 zif
->rtadv
.AdvReachableTime
= 0;
1873 DEFUN (ipv6_nd_homeagent_preference
,
1874 ipv6_nd_homeagent_preference_cmd
,
1875 "ipv6 nd home-agent-preference (0-65535)",
1876 "Interface IPv6 config commands\n"
1877 "Neighbor discovery\n"
1878 "Home Agent preference\n"
1879 "preference value (default is 0, least preferred)\n")
1882 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1883 struct zebra_if
*zif
= ifp
->info
;
1884 zif
->rtadv
.HomeAgentPreference
=
1885 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1889 DEFUN (no_ipv6_nd_homeagent_preference
,
1890 no_ipv6_nd_homeagent_preference_cmd
,
1891 "no ipv6 nd home-agent-preference [(0-65535)]",
1893 "Interface IPv6 config commands\n"
1894 "Neighbor discovery\n"
1895 "Home Agent preference\n"
1896 "preference value (default is 0, least preferred)\n")
1898 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1899 struct zebra_if
*zif
= ifp
->info
;
1901 zif
->rtadv
.HomeAgentPreference
= 0;
1906 DEFUN (ipv6_nd_homeagent_lifetime
,
1907 ipv6_nd_homeagent_lifetime_cmd
,
1908 "ipv6 nd home-agent-lifetime (0-65520)",
1909 "Interface IPv6 config commands\n"
1910 "Neighbor discovery\n"
1911 "Home Agent lifetime\n"
1912 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1915 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1916 struct zebra_if
*zif
= ifp
->info
;
1917 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1921 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1922 no_ipv6_nd_homeagent_lifetime_cmd
,
1923 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1925 "Interface IPv6 config commands\n"
1926 "Neighbor discovery\n"
1927 "Home Agent lifetime\n"
1928 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1930 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1931 struct zebra_if
*zif
= ifp
->info
;
1933 zif
->rtadv
.HomeAgentLifetime
= -1;
1938 DEFUN (ipv6_nd_managed_config_flag
,
1939 ipv6_nd_managed_config_flag_cmd
,
1940 "ipv6 nd managed-config-flag",
1941 "Interface IPv6 config commands\n"
1942 "Neighbor discovery\n"
1943 "Managed address configuration flag\n")
1945 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1946 struct zebra_if
*zif
= ifp
->info
;
1948 zif
->rtadv
.AdvManagedFlag
= 1;
1953 DEFUN (no_ipv6_nd_managed_config_flag
,
1954 no_ipv6_nd_managed_config_flag_cmd
,
1955 "no ipv6 nd managed-config-flag",
1957 "Interface IPv6 config commands\n"
1958 "Neighbor discovery\n"
1959 "Managed address configuration flag\n")
1961 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1962 struct zebra_if
*zif
= ifp
->info
;
1964 zif
->rtadv
.AdvManagedFlag
= 0;
1969 DEFUN (ipv6_nd_homeagent_config_flag
,
1970 ipv6_nd_homeagent_config_flag_cmd
,
1971 "ipv6 nd home-agent-config-flag",
1972 "Interface IPv6 config commands\n"
1973 "Neighbor discovery\n"
1974 "Home Agent configuration flag\n")
1976 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1977 struct zebra_if
*zif
= ifp
->info
;
1979 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1984 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1985 no_ipv6_nd_homeagent_config_flag_cmd
,
1986 "no ipv6 nd home-agent-config-flag",
1988 "Interface IPv6 config commands\n"
1989 "Neighbor discovery\n"
1990 "Home Agent configuration flag\n")
1992 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1993 struct zebra_if
*zif
= ifp
->info
;
1995 zif
->rtadv
.AdvHomeAgentFlag
= 0;
2000 DEFUN (ipv6_nd_adv_interval_config_option
,
2001 ipv6_nd_adv_interval_config_option_cmd
,
2002 "ipv6 nd adv-interval-option",
2003 "Interface IPv6 config commands\n"
2004 "Neighbor discovery\n"
2005 "Advertisement Interval Option\n")
2007 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2008 struct zebra_if
*zif
= ifp
->info
;
2010 zif
->rtadv
.AdvIntervalOption
= 1;
2015 DEFUN (no_ipv6_nd_adv_interval_config_option
,
2016 no_ipv6_nd_adv_interval_config_option_cmd
,
2017 "no ipv6 nd adv-interval-option",
2019 "Interface IPv6 config commands\n"
2020 "Neighbor discovery\n"
2021 "Advertisement Interval Option\n")
2023 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2024 struct zebra_if
*zif
= ifp
->info
;
2026 zif
->rtadv
.AdvIntervalOption
= 0;
2031 DEFUN (ipv6_nd_other_config_flag
,
2032 ipv6_nd_other_config_flag_cmd
,
2033 "ipv6 nd other-config-flag",
2034 "Interface IPv6 config commands\n"
2035 "Neighbor discovery\n"
2036 "Other statefull configuration flag\n")
2038 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2039 struct zebra_if
*zif
= ifp
->info
;
2041 zif
->rtadv
.AdvOtherConfigFlag
= 1;
2046 DEFUN (no_ipv6_nd_other_config_flag
,
2047 no_ipv6_nd_other_config_flag_cmd
,
2048 "no ipv6 nd other-config-flag",
2050 "Interface IPv6 config commands\n"
2051 "Neighbor discovery\n"
2052 "Other statefull configuration flag\n")
2054 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2055 struct zebra_if
*zif
= ifp
->info
;
2057 zif
->rtadv
.AdvOtherConfigFlag
= 0;
2062 DEFUN (ipv6_nd_prefix
,
2064 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2065 "Interface IPv6 config commands\n"
2066 "Neighbor discovery\n"
2067 "Prefix information\n"
2069 "Valid lifetime in seconds\n"
2070 "Infinite valid lifetime\n"
2071 "Preferred lifetime in seconds\n"
2072 "Infinite preferred lifetime\n"
2073 "Set Router Address flag\n"
2074 "Do not use prefix for onlink determination\n"
2075 "Do not use prefix for autoconfiguration\n"
2076 "Do not use prefix for autoconfiguration\n"
2077 "Do not use prefix for onlink determination\n")
2080 char *prefix
= argv
[3]->arg
;
2081 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
2082 || strmatch(argv
[4]->text
, "infinite"));
2083 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
2085 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
2087 char *lifetime
= NULL
, *preflifetime
= NULL
;
2088 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
2090 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2092 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
2097 strmatch(argv
[idx_routeropts
]->text
, "router-address");
2099 offlink
= (argc
> idx_routeropts
+ 1
2100 || strmatch(argv
[idx_routeropts
]->text
,
2102 noautoconf
= (argc
> idx_routeropts
+ 1
2103 || strmatch(argv
[idx_routeropts
]->text
,
2109 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2110 struct zebra_if
*zebra_if
= ifp
->info
;
2112 struct rtadv_prefix rp
;
2114 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2116 vty_out(vty
, "Malformed IPv6 prefix\n");
2117 return CMD_WARNING_CONFIG_FAILED
;
2119 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2120 rp
.AdvOnLinkFlag
= !offlink
;
2121 rp
.AdvAutonomousFlag
= !noautoconf
;
2122 rp
.AdvRouterAddressFlag
= routeraddr
;
2123 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
2124 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
2125 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2128 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
2130 : strtoll(lifetime
, NULL
, 10);
2131 rp
.AdvPreferredLifetime
=
2132 strmatch(preflifetime
, "infinite")
2134 : strtoll(preflifetime
, NULL
, 10);
2135 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
2136 vty_out(vty
, "Invalid preferred lifetime\n");
2137 return CMD_WARNING_CONFIG_FAILED
;
2141 rtadv_prefix_set(zebra_if
, &rp
);
2146 DEFUN (no_ipv6_nd_prefix
,
2147 no_ipv6_nd_prefix_cmd
,
2148 "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]>]",
2150 "Interface IPv6 config commands\n"
2151 "Neighbor discovery\n"
2152 "Prefix information\n"
2154 "Valid lifetime in seconds\n"
2155 "Infinite valid lifetime\n"
2156 "Preferred lifetime in seconds\n"
2157 "Infinite preferred lifetime\n"
2158 "Set Router Address flag\n"
2159 "Do not use prefix for onlink determination\n"
2160 "Do not use prefix for autoconfiguration\n"
2161 "Do not use prefix for autoconfiguration\n"
2162 "Do not use prefix for onlink determination\n")
2164 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2165 struct zebra_if
*zebra_if
= ifp
->info
;
2167 struct rtadv_prefix rp
;
2168 char *prefix
= argv
[4]->arg
;
2170 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2172 vty_out(vty
, "Malformed IPv6 prefix\n");
2173 return CMD_WARNING_CONFIG_FAILED
;
2175 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2176 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2178 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
2180 vty_out(vty
, "Non-existant IPv6 prefix\n");
2181 return CMD_WARNING_CONFIG_FAILED
;
2187 DEFUN (ipv6_nd_router_preference
,
2188 ipv6_nd_router_preference_cmd
,
2189 "ipv6 nd router-preference <high|medium|low>",
2190 "Interface IPv6 config commands\n"
2191 "Neighbor discovery\n"
2192 "Default router preference\n"
2193 "High default router preference\n"
2194 "Medium default router preference (default)\n"
2195 "Low default router preference\n")
2197 int idx_high_medium_low
= 3;
2198 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2199 struct zebra_if
*zif
= ifp
->info
;
2202 while (0 != rtadv_pref_strs
[i
]) {
2203 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
2206 zif
->rtadv
.DefaultPreference
= i
;
2212 return CMD_ERR_NO_MATCH
;
2215 DEFUN (no_ipv6_nd_router_preference
,
2216 no_ipv6_nd_router_preference_cmd
,
2217 "no ipv6 nd router-preference [<high|medium|low>]",
2219 "Interface IPv6 config commands\n"
2220 "Neighbor discovery\n"
2221 "Default router preference\n"
2222 "High default router preference\n"
2223 "Medium default router preference (default)\n"
2224 "Low default router preference\n")
2226 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2227 struct zebra_if
*zif
= ifp
->info
;
2229 zif
->rtadv
.DefaultPreference
=
2230 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
2237 "ipv6 nd mtu (1-65535)",
2238 "Interface IPv6 config commands\n"
2239 "Neighbor discovery\n"
2244 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2245 struct zebra_if
*zif
= ifp
->info
;
2246 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2250 DEFUN (no_ipv6_nd_mtu
,
2252 "no ipv6 nd mtu [(1-65535)]",
2254 "Interface IPv6 config commands\n"
2255 "Neighbor discovery\n"
2259 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2260 struct zebra_if
*zif
= ifp
->info
;
2261 zif
->rtadv
.AdvLinkMTU
= 0;
2265 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
2267 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
2270 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
2272 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
2275 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
2276 struct rtadv_rdnss
*rdnss
)
2278 struct listnode
*node
;
2279 struct rtadv_rdnss
*p
;
2281 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2282 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
2287 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
2288 struct rtadv_rdnss
*rdnss
)
2290 struct rtadv_rdnss
*p
;
2292 p
= rtadv_rdnss_lookup(list
, rdnss
);
2296 p
= rtadv_rdnss_new();
2297 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
2298 listnode_add(list
, p
);
2303 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2305 struct rtadv_rdnss
*p
;
2307 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2308 p
->lifetime
= rdnss
->lifetime
;
2309 p
->lifetime_set
= rdnss
->lifetime_set
;
2312 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2314 struct rtadv_rdnss
*p
;
2316 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2318 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
2319 rtadv_rdnss_free(p
);
2326 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
2328 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
2331 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
2333 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
2336 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
2337 struct rtadv_dnssl
*dnssl
)
2339 struct listnode
*node
;
2340 struct rtadv_dnssl
*p
;
2342 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2343 if (!strcasecmp(p
->name
, dnssl
->name
))
2348 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
2349 struct rtadv_dnssl
*dnssl
)
2351 struct rtadv_dnssl
*p
;
2353 p
= rtadv_dnssl_lookup(list
, dnssl
);
2357 p
= rtadv_dnssl_new();
2358 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2359 listnode_add(list
, p
);
2364 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2366 struct rtadv_dnssl
*p
;
2368 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2369 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2372 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2374 struct rtadv_dnssl
*p
;
2376 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2378 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
2379 rtadv_dnssl_free(p
);
2387 * Convert dotted domain name (with or without trailing root zone dot) to
2388 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2389 * to strlen(in) + 2 octets to out.
2391 * Returns the number of octets written to out or -1 if in does not constitute
2392 * a valid domain name.
2394 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
2396 const char *label_start
, *label_end
;
2402 while (*label_start
) {
2405 label_end
= strchr(label_start
, '.');
2406 if (label_end
== NULL
)
2407 label_end
= label_start
+ strlen(label_start
);
2409 label_len
= label_end
- label_start
;
2410 if (label_len
>= 64)
2411 return -1; /* labels must be 63 octets or less */
2413 out
[outp
++] = (uint8_t)label_len
;
2414 memcpy(out
+ outp
, label_start
, label_len
);
2416 label_start
+= label_len
;
2417 if (*label_start
== '.')
2425 DEFUN(ipv6_nd_rdnss
,
2427 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2428 "Interface IPv6 config commands\n"
2429 "Neighbor discovery\n"
2430 "Recursive DNS server information\n"
2432 "Valid lifetime in seconds\n"
2433 "Infinite valid lifetime\n")
2435 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2436 struct zebra_if
*zif
= ifp
->info
;
2437 struct rtadv_rdnss rdnss
= {};
2439 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
2440 vty_out(vty
, "Malformed IPv6 address\n");
2441 return CMD_WARNING_CONFIG_FAILED
;
2444 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2446 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
2448 : strtoll(lifetime
, NULL
, 10);
2449 rdnss
.lifetime_set
= 1;
2452 rtadv_rdnss_set(zif
, &rdnss
);
2457 DEFUN(no_ipv6_nd_rdnss
,
2458 no_ipv6_nd_rdnss_cmd
,
2459 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2461 "Interface IPv6 config commands\n"
2462 "Neighbor discovery\n"
2463 "Recursive DNS server information\n"
2465 "Valid lifetime in seconds\n"
2466 "Infinite valid lifetime\n")
2468 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2469 struct zebra_if
*zif
= ifp
->info
;
2470 struct rtadv_rdnss rdnss
= {};
2472 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
2473 vty_out(vty
, "Malformed IPv6 address\n");
2474 return CMD_WARNING_CONFIG_FAILED
;
2476 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
2477 vty_out(vty
, "Non-existant RDNSS address\n");
2478 return CMD_WARNING_CONFIG_FAILED
;
2484 DEFUN(ipv6_nd_dnssl
,
2486 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2487 "Interface IPv6 config commands\n"
2488 "Neighbor discovery\n"
2489 "DNS search list information\n"
2490 "Domain name suffix\n"
2491 "Valid lifetime in seconds\n"
2492 "Infinite valid lifetime\n")
2494 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2495 struct zebra_if
*zif
= ifp
->info
;
2496 struct rtadv_dnssl dnssl
= {};
2500 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
2501 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2502 vty_out(vty
, "Malformed DNS search domain\n");
2503 return CMD_WARNING_CONFIG_FAILED
;
2505 if (dnssl
.name
[len
- 1] == '.') {
2507 * Allow, but don't require, a trailing dot signifying the root
2508 * zone. Canonicalize by cutting it off if present.
2510 dnssl
.name
[len
- 1] = '\0';
2514 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2516 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
2518 : strtoll(lifetime
, NULL
, 10);
2519 dnssl
.lifetime_set
= 1;
2522 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2524 vty_out(vty
, "Malformed DNS search domain\n");
2525 return CMD_WARNING_CONFIG_FAILED
;
2527 dnssl
.encoded_len
= ret
;
2528 rtadv_dnssl_set(zif
, &dnssl
);
2533 DEFUN(no_ipv6_nd_dnssl
,
2534 no_ipv6_nd_dnssl_cmd
,
2535 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2537 "Interface IPv6 config commands\n"
2538 "Neighbor discovery\n"
2539 "DNS search list information\n"
2540 "Domain name suffix\n"
2541 "Valid lifetime in seconds\n"
2542 "Infinite valid lifetime\n")
2544 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2545 struct zebra_if
*zif
= ifp
->info
;
2546 struct rtadv_dnssl dnssl
= {};
2549 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2550 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2551 vty_out(vty
, "Malformed DNS search domain\n");
2552 return CMD_WARNING_CONFIG_FAILED
;
2554 if (dnssl
.name
[len
- 1] == '.') {
2555 dnssl
.name
[len
- 1] = '\0';
2558 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2559 vty_out(vty
, "Non-existant DNS search domain\n");
2560 return CMD_WARNING_CONFIG_FAILED
;
2567 /* Dump interface ND information to vty. */
2568 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2570 struct zebra_if
*zif
;
2571 struct rtadvconf
*rtadv
;
2574 zif
= (struct zebra_if
*)ifp
->info
;
2575 rtadv
= &zif
->rtadv
;
2577 if (rtadv
->AdvSendAdvertisements
) {
2579 " ND advertised reachable time is %d milliseconds\n",
2580 rtadv
->AdvReachableTime
);
2582 " ND advertised retransmit interval is %u milliseconds\n",
2583 rtadv
->AdvRetransTimer
);
2584 vty_out(vty
, " ND advertised hop-count limit is %d hops\n",
2585 rtadv
->AdvCurHopLimit
);
2586 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2587 zif
->ra_sent
, zif
->ra_rcvd
);
2588 interval
= rtadv
->MaxRtrAdvInterval
;
2589 if (interval
% 1000)
2591 " ND router advertisements are sent every %d milliseconds\n",
2595 " ND router advertisements are sent every %d seconds\n",
2597 if (!rtadv
->UseFastRexmit
)
2599 " ND router advertisements do not use fast retransmit\n");
2601 if (rtadv
->AdvDefaultLifetime
!= -1)
2603 " ND router advertisements live for %d seconds\n",
2604 rtadv
->AdvDefaultLifetime
);
2607 " ND router advertisements lifetime tracks ra-interval\n");
2609 " ND router advertisement default router preference is %s\n",
2610 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2611 if (rtadv
->AdvManagedFlag
)
2613 " Hosts use DHCP to obtain routable addresses.\n");
2616 " Hosts use stateless autoconfig for addresses.\n");
2617 if (rtadv
->AdvHomeAgentFlag
) {
2619 " ND router advertisements with Home Agent flag bit set.\n");
2620 if (rtadv
->HomeAgentLifetime
!= -1)
2622 " Home Agent lifetime is %u seconds\n",
2623 rtadv
->HomeAgentLifetime
);
2626 " Home Agent lifetime tracks ra-lifetime\n");
2627 vty_out(vty
, " Home Agent preference is %u\n",
2628 rtadv
->HomeAgentPreference
);
2630 if (rtadv
->AdvIntervalOption
)
2632 " ND router advertisements with Adv. Interval option.\n");
2638 /* Write configuration about router advertisement. */
2639 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2641 struct zebra_if
*zif
;
2642 struct listnode
*node
;
2643 struct rtadv_prefix
*rprefix
;
2644 struct rtadv_rdnss
*rdnss
;
2645 struct rtadv_dnssl
*dnssl
;
2650 if (!if_is_loopback(ifp
)) {
2651 if (zif
->rtadv
.AdvSendAdvertisements
2652 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2653 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2656 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2657 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2658 if (interval
% 1000)
2659 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2661 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2662 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2666 if (zif
->rtadv
.AdvIntervalOption
)
2667 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2669 if (!zif
->rtadv
.UseFastRexmit
)
2670 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2672 if (zif
->rtadv
.AdvRetransTimer
!= 0)
2673 vty_out(vty
, " ipv6 nd ra-retrans-interval %u\n",
2674 zif
->rtadv
.AdvRetransTimer
);
2676 if (zif
->rtadv
.AdvCurHopLimit
!= RTADV_DEFAULT_HOPLIMIT
)
2677 vty_out(vty
, " ipv6 nd ra-hop-limit %d\n",
2678 zif
->rtadv
.AdvCurHopLimit
);
2680 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2681 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2682 zif
->rtadv
.AdvDefaultLifetime
);
2684 if (zif
->rtadv
.HomeAgentPreference
)
2685 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2686 zif
->rtadv
.HomeAgentPreference
);
2688 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2689 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2690 zif
->rtadv
.HomeAgentLifetime
);
2692 if (zif
->rtadv
.AdvHomeAgentFlag
)
2693 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2695 if (zif
->rtadv
.AdvReachableTime
)
2696 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2697 zif
->rtadv
.AdvReachableTime
);
2699 if (zif
->rtadv
.AdvManagedFlag
)
2700 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2702 if (zif
->rtadv
.AdvOtherConfigFlag
)
2703 vty_out(vty
, " ipv6 nd other-config-flag\n");
2705 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2706 vty_out(vty
, " ipv6 nd router-preference %s\n",
2707 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2709 if (zif
->rtadv
.AdvLinkMTU
)
2710 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2712 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
2713 if ((rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
2714 || (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
)) {
2715 vty_out(vty
, " ipv6 nd prefix %pFX", &rprefix
->prefix
);
2716 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2717 || (rprefix
->AdvPreferredLifetime
2718 != RTADV_PREFERRED_LIFETIME
)) {
2719 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2720 vty_out(vty
, " infinite");
2723 rprefix
->AdvValidLifetime
);
2724 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2725 vty_out(vty
, " infinite");
2728 rprefix
->AdvPreferredLifetime
);
2730 if (!rprefix
->AdvOnLinkFlag
)
2731 vty_out(vty
, " off-link");
2732 if (!rprefix
->AdvAutonomousFlag
)
2733 vty_out(vty
, " no-autoconfig");
2734 if (rprefix
->AdvRouterAddressFlag
)
2735 vty_out(vty
, " router-address");
2740 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2741 char buf
[INET6_ADDRSTRLEN
];
2743 vty_out(vty
, " ipv6 nd rdnss %s",
2744 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2745 if (rdnss
->lifetime_set
) {
2746 if (rdnss
->lifetime
== UINT32_MAX
)
2747 vty_out(vty
, " infinite");
2749 vty_out(vty
, " %u", rdnss
->lifetime
);
2753 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2754 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2755 if (dnssl
->lifetime_set
) {
2756 if (dnssl
->lifetime
== UINT32_MAX
)
2757 vty_out(vty
, " infinite");
2759 vty_out(vty
, " %u", dnssl
->lifetime
);
2767 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2769 struct rtadv
*rtadv
;
2771 if (IS_ZEBRA_DEBUG_EVENT
) {
2772 struct vrf
*vrf
= zvrf
->vrf
;
2774 zlog_debug("%s(%s) with event: %d and val: %d", __func__
,
2775 VRF_LOGNAME(vrf
), event
, val
);
2778 rtadv
= &zvrf
->rtadv
;
2782 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2784 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2788 THREAD_OFF(rtadv
->ra_timer
);
2789 THREAD_OFF(rtadv
->ra_read
);
2792 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2795 case RTADV_TIMER_MSEC
:
2796 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2800 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2809 void rtadv_if_up(struct zebra_if
*zif
)
2811 struct zebra_vrf
*zvrf
= rtadv_interface_get_zvrf(zif
->ifp
);
2813 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
2814 if (zif
->rtadv
.AdvSendAdvertisements
&&
2815 (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) &&
2816 zif
->rtadv
.UseFastRexmit
) {
2817 zif
->rtadv
.inFastRexmit
= 1;
2818 zif
->rtadv
.NumFastReXmitsRemain
= RTADV_NUM_FAST_REXMITS
;
2822 * startup the state machine, if it hasn't been already
2823 * due to a delayed ifindex on startup ordering
2825 if (zif
->rtadv
.AdvSendAdvertisements
)
2826 rtadv_start_interface_events(zvrf
, zif
);
2829 void rtadv_if_init(struct zebra_if
*zif
)
2831 /* Set default router advertise values. */
2832 struct rtadvconf
*rtadv
;
2834 rtadv
= &zif
->rtadv
;
2836 rtadv
->AdvSendAdvertisements
= 0;
2837 rtadv
->MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
2838 rtadv
->MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
2839 rtadv
->AdvIntervalTimer
= 0;
2840 rtadv
->AdvManagedFlag
= 0;
2841 rtadv
->AdvOtherConfigFlag
= 0;
2842 rtadv
->AdvHomeAgentFlag
= 0;
2843 rtadv
->AdvLinkMTU
= 0;
2844 rtadv
->AdvReachableTime
= 0;
2845 rtadv
->AdvRetransTimer
= 0;
2846 rtadv
->AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
2847 memset(&rtadv
->lastadvcurhoplimit
, 0,
2848 sizeof(rtadv
->lastadvcurhoplimit
));
2849 memset(&rtadv
->lastadvmanagedflag
, 0,
2850 sizeof(rtadv
->lastadvmanagedflag
));
2851 memset(&rtadv
->lastadvotherconfigflag
, 0,
2852 sizeof(rtadv
->lastadvotherconfigflag
));
2853 memset(&rtadv
->lastadvreachabletime
, 0,
2854 sizeof(rtadv
->lastadvreachabletime
));
2855 memset(&rtadv
->lastadvretranstimer
, 0,
2856 sizeof(rtadv
->lastadvretranstimer
));
2857 rtadv
->AdvDefaultLifetime
= -1; /* derive from MaxRtrAdvInterval */
2858 rtadv
->HomeAgentPreference
= 0;
2859 rtadv
->HomeAgentLifetime
= -1; /* derive from AdvDefaultLifetime */
2860 rtadv
->AdvIntervalOption
= 0;
2861 rtadv
->UseFastRexmit
= true;
2862 rtadv
->DefaultPreference
= RTADV_PREF_MEDIUM
;
2864 rtadv_prefixes_init(rtadv
->prefixes
);
2866 rtadv
->AdvRDNSSList
= list_new();
2867 rtadv
->AdvDNSSLList
= list_new();
2870 void rtadv_if_fini(struct zebra_if
*zif
)
2872 struct rtadvconf
*rtadv
;
2873 struct rtadv_prefix
*rp
;
2875 rtadv
= &zif
->rtadv
;
2877 while ((rp
= rtadv_prefixes_pop(rtadv
->prefixes
)))
2878 rtadv_prefix_free(rp
);
2880 list_delete(&rtadv
->AdvRDNSSList
);
2881 list_delete(&rtadv
->AdvDNSSLList
);
2884 void rtadv_vrf_init(struct zebra_vrf
*zvrf
)
2886 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2889 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2892 void rtadv_vrf_terminate(struct zebra_vrf
*zvrf
)
2894 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2897 rtadv_event(zvrf
, RTADV_STOP
, 0);
2898 if (zvrf
->rtadv
.sock
>= 0) {
2899 close(zvrf
->rtadv
.sock
);
2900 zvrf
->rtadv
.sock
= -1;
2904 adv_msec_if_clean(zvrf
);
2907 void rtadv_cmd_init(void)
2909 interfaces_configured_for_ra_from_bgp
= 0;
2911 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2912 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2914 install_element(VIEW_NODE
, &show_ipv6_nd_ra_if_cmd
);
2916 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2917 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2918 install_element(INTERFACE_NODE
, &ipv6_nd_ra_retrans_interval_cmd
);
2919 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_retrans_interval_cmd
);
2920 install_element(INTERFACE_NODE
, &ipv6_nd_ra_hop_limit_cmd
);
2921 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_hop_limit_cmd
);
2922 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2923 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2924 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2925 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2926 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2927 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2928 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2929 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2930 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2931 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2932 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2933 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2934 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2935 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2936 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2937 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2938 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2939 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2940 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2941 install_element(INTERFACE_NODE
,
2942 &ipv6_nd_adv_interval_config_option_cmd
);
2943 install_element(INTERFACE_NODE
,
2944 &no_ipv6_nd_adv_interval_config_option_cmd
);
2945 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2946 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2947 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2948 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2949 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2950 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2951 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2952 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2953 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2954 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2957 static int if_join_all_router(int sock
, struct interface
*ifp
)
2961 struct ipv6_mreq mreq
;
2963 memset(&mreq
, 0, sizeof(mreq
));
2964 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2965 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2967 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2970 flog_err_sys(EC_LIB_SOCKET
,
2971 "%s(%u): Failed to join group, socket %u error %s",
2972 ifp
->name
, ifp
->ifindex
, sock
,
2973 safe_strerror(errno
));
2975 if (IS_ZEBRA_DEBUG_EVENT
)
2977 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2978 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
2983 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2987 struct ipv6_mreq mreq
;
2989 memset(&mreq
, 0, sizeof(mreq
));
2990 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2991 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2993 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2998 "%s(%s:%u): Failed to leave group, socket %u error %s",
2999 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
,
3000 safe_strerror(errno
));
3002 if (IS_ZEBRA_DEBUG_EVENT
)
3004 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
3005 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
3010 bool rtadv_compiled_in(void)
3015 #else /* !HAVE_RTADV */
3017 * If the end user does not have RADV enabled we should
3018 * handle this better
3020 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
3022 if (IS_ZEBRA_DEBUG_PACKET
)
3024 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3025 zserv_command_string(hdr
->command
));
3030 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
3032 if (IS_ZEBRA_DEBUG_PACKET
)
3034 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3035 zserv_command_string(hdr
->command
));
3040 bool rtadv_compiled_in(void)
3045 #endif /* HAVE_RTADV */
3047 uint32_t rtadv_get_interfaces_configured_from_bgp(void)
3049 return interfaces_configured_for_ra_from_bgp
;