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
;
834 frr_with_privs(&zserv_privs
) {
836 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
844 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
849 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
854 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
859 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
864 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
870 ICMP6_FILTER_SETBLOCKALL(&filter
);
871 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
872 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
874 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
875 sizeof(struct icmp6_filter
));
877 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
885 static struct adv_if
*adv_if_new(const char *name
)
889 new = XCALLOC(MTYPE_ADV_IF
, sizeof(struct adv_if
));
891 strlcpy(new->name
, name
, sizeof(new->name
));
896 static void adv_if_free(struct adv_if
*adv_if
)
898 XFREE(MTYPE_ADV_IF
, adv_if
);
901 static bool adv_if_is_empty_internal(const struct adv_if_list_head
*adv_if_head
)
903 return adv_if_list_count(adv_if_head
) ? false : true;
906 static struct adv_if
*adv_if_add_internal(struct adv_if_list_head
*adv_if_head
,
909 struct adv_if adv_if_lookup
= {};
910 struct adv_if
*adv_if
= NULL
;
912 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
913 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
918 adv_if
= adv_if_new(adv_if_lookup
.name
);
919 adv_if_list_add(adv_if_head
, adv_if
);
924 static struct adv_if
*adv_if_del_internal(struct adv_if_list_head
*adv_if_head
,
927 struct adv_if adv_if_lookup
= {};
928 struct adv_if
*adv_if
= NULL
;
930 strlcpy(adv_if_lookup
.name
, name
, sizeof(adv_if_lookup
.name
));
931 adv_if
= adv_if_list_find(adv_if_head
, &adv_if_lookup
);
936 adv_if_list_del(adv_if_head
, adv_if
);
941 static void adv_if_clean_internal(struct adv_if_list_head
*adv_if_head
)
943 struct adv_if
*node
= NULL
;
945 if (!adv_if_is_empty_internal(adv_if_head
)) {
946 frr_each_safe (adv_if_list
, adv_if_head
, node
) {
947 adv_if_list_del(adv_if_head
, node
);
952 adv_if_list_fini(adv_if_head
);
957 * Add to list. On Success, return NULL, otherwise return already existing
960 static struct adv_if
*adv_if_add(struct zebra_vrf
*zvrf
, const char *name
)
962 struct adv_if
*adv_if
= NULL
;
964 adv_if
= adv_if_add_internal(&zvrf
->rtadv
.adv_if
, name
);
969 if (IS_ZEBRA_DEBUG_EVENT
) {
970 struct vrf
*vrf
= zvrf
->vrf
;
972 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
973 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
974 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
981 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
984 static struct adv_if
*adv_if_del(struct zebra_vrf
*zvrf
, const char *name
)
986 struct adv_if
*adv_if
= NULL
;
988 adv_if
= adv_if_del_internal(&zvrf
->rtadv
.adv_if
, name
);
993 if (IS_ZEBRA_DEBUG_EVENT
) {
994 struct vrf
*vrf
= zvrf
->vrf
;
996 zlog_debug("%s: %s:%u IF %s count: %zu", __func__
,
997 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), name
,
998 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1005 * Add to list. On Success, return NULL, otherwise return already existing
1008 static struct adv_if
*adv_msec_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_msec_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_msec_if
));
1029 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1032 static struct adv_if
*adv_msec_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_msec_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_msec_if
));
1052 /* Clean adv_if list, called on vrf terminate */
1053 static void adv_if_clean(struct zebra_vrf
*zvrf
)
1055 if (IS_ZEBRA_DEBUG_EVENT
) {
1056 struct vrf
*vrf
= zvrf
->vrf
;
1058 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1059 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1060 adv_if_list_count(&zvrf
->rtadv
.adv_if
));
1063 adv_if_clean_internal(&zvrf
->rtadv
.adv_if
);
1066 /* Clean adv_msec_if list, called on vrf terminate */
1067 static void adv_msec_if_clean(struct zebra_vrf
*zvrf
)
1069 if (IS_ZEBRA_DEBUG_EVENT
) {
1070 struct vrf
*vrf
= zvrf
->vrf
;
1072 zlog_debug("%s: %s:%u count: %zu -> 0", __func__
,
1073 VRF_LOGNAME(vrf
), zvrf_id(zvrf
),
1074 adv_if_list_count(&zvrf
->rtadv
.adv_msec_if
));
1077 adv_if_clean_internal(&zvrf
->rtadv
.adv_msec_if
);
1080 static struct rtadv_prefix
*rtadv_prefix_new(void)
1082 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
1085 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
1087 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
1090 static struct rtadv_prefix
*rtadv_prefix_get(struct rtadv_prefixes_head
*list
,
1091 struct prefix_ipv6
*p
)
1093 struct rtadv_prefix
*rprefix
, ref
;
1097 rprefix
= rtadv_prefixes_find(list
, &ref
);
1101 rprefix
= rtadv_prefix_new();
1102 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
1103 rtadv_prefixes_add(list
, rprefix
);
1108 static void rtadv_prefix_set_defaults(struct rtadv_prefix
*rp
)
1110 rp
->AdvAutonomousFlag
= 1;
1111 rp
->AdvOnLinkFlag
= 1;
1112 rp
->AdvRouterAddressFlag
= 0;
1113 rp
->AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1114 rp
->AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1117 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1119 struct rtadv_prefix
*rprefix
;
1121 rprefix
= rtadv_prefix_get(zif
->rtadv
.prefixes
, &rp
->prefix
);
1124 * Set parameters based on where the prefix is created.
1125 * If auto-created based on kernel address addition, set the
1126 * default values. If created from a manual "ipv6 nd prefix"
1127 * command, take the parameters from the manual command. Note
1128 * that if the manual command exists, the default values will
1129 * not overwrite the manual values.
1131 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1132 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_AUTO
)
1133 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1135 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1137 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
1138 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
1139 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
1140 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
1141 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
1142 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1143 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
1144 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
1146 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1147 rtadv_prefix_set_defaults(rprefix
);
1152 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
1154 struct rtadv_prefix
*rprefix
;
1156 rprefix
= rtadv_prefixes_find(zif
->rtadv
.prefixes
, rp
);
1157 if (rprefix
!= NULL
) {
1160 * When deleting an address from the list, need to take care
1161 * it wasn't defined both automatically via kernel
1162 * address addition as well as manually by vtysh cli. If both,
1163 * we don't actually delete but may change the parameters
1164 * back to default if a manually defined entry is deleted.
1166 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
1167 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1168 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1169 rtadv_prefix_set_defaults(rprefix
);
1172 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
1173 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
1174 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1179 rtadv_prefixes_del(zif
->rtadv
.prefixes
, rprefix
);
1180 rtadv_prefix_free(rprefix
);
1186 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
1187 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
1189 struct rtadv_prefix rp
;
1192 apply_mask_ipv6(&rp
.prefix
);
1193 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1194 rtadv_prefix_set(zif
, &rp
);
1197 /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
1198 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
1200 struct rtadv_prefix rp
;
1202 rp
.prefix
= *((struct prefix_ipv6
*)p
);
1203 apply_mask_ipv6(&rp
.prefix
);
1204 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1205 rtadv_prefix_reset(zif
, &rp
);
1208 static void rtadv_start_interface_events(struct zebra_vrf
*zvrf
,
1209 struct zebra_if
*zif
)
1211 struct adv_if
*adv_if
= NULL
;
1213 if (zif
->ifp
->ifindex
== IFINDEX_INTERNAL
) {
1214 if (IS_ZEBRA_DEBUG_EVENT
)
1216 "%s(%s) has not configured an ifindex yet, delaying until we have one",
1217 zif
->ifp
->name
, zvrf
->vrf
->name
);
1221 adv_if
= adv_if_add(zvrf
, zif
->ifp
->name
);
1223 return; /* Already added */
1225 if_join_all_router(zvrf
->rtadv
.sock
, zif
->ifp
);
1227 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 1)
1228 rtadv_event(zvrf
, RTADV_START
, 0);
1231 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
1232 enum ipv6_nd_suppress_ra_status status
)
1234 struct zebra_if
*zif
;
1235 struct zebra_vrf
*zvrf
;
1236 struct adv_if
*adv_if
= NULL
;
1240 zvrf
= rtadv_interface_get_zvrf(ifp
);
1242 if (status
== RA_SUPPRESS
) {
1243 /* RA is currently enabled */
1244 if (zif
->rtadv
.AdvSendAdvertisements
) {
1245 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1246 zif
->rtadv
.AdvSendAdvertisements
= 0;
1247 zif
->rtadv
.AdvIntervalTimer
= 0;
1249 adv_if
= adv_if_del(zvrf
, ifp
->name
);
1251 return; /* Nothing to delete */
1253 adv_if_free(adv_if
);
1255 if_leave_all_router(zvrf
->rtadv
.sock
, ifp
);
1257 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 0)
1258 rtadv_event(zvrf
, RTADV_STOP
, 0);
1261 if (!zif
->rtadv
.AdvSendAdvertisements
) {
1262 zif
->rtadv
.AdvSendAdvertisements
= 1;
1263 zif
->rtadv
.AdvIntervalTimer
= 0;
1264 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
1265 && zif
->rtadv
.UseFastRexmit
) {
1267 * Enable Fast RA only when RA interval is in
1268 * secs and Fast RA retransmit is enabled
1270 zif
->rtadv
.inFastRexmit
= 1;
1271 zif
->rtadv
.NumFastReXmitsRemain
=
1272 RTADV_NUM_FAST_REXMITS
;
1275 rtadv_start_interface_events(zvrf
, zif
);
1281 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1282 * Note that while the client could request RA on an interface on which the
1283 * operator has not enabled RA, RA won't be disabled upon client request
1284 * if the operator has explicitly enabled RA. The enable request can also
1285 * specify a RA interval (in seconds).
1287 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
1291 struct interface
*ifp
;
1292 struct zebra_if
*zif
;
1293 uint32_t ra_interval
;
1297 /* Get interface index and RA interval. */
1298 STREAM_GETL(s
, ifindex
);
1299 STREAM_GETL(s
, ra_interval
);
1301 if (IS_ZEBRA_DEBUG_EVENT
) {
1302 struct vrf
*vrf
= zvrf
->vrf
;
1304 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1305 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1306 enable
? "enable" : "disable",
1307 zebra_route_string(client
->proto
), ra_interval
);
1310 /* Locate interface and check VRF match. */
1311 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
1313 struct vrf
*vrf
= zvrf
->vrf
;
1315 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
1316 "%s:%u: IF %u RA %s client %s - interface unknown",
1317 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1318 enable
? "enable" : "disable",
1319 zebra_route_string(client
->proto
));
1322 if (vrf_is_backend_netns() && ifp
->vrf
->vrf_id
!= zvrf_id(zvrf
)) {
1324 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1325 ifp
->vrf
->name
, zvrf_id(zvrf
), ifindex
,
1326 enable
? "enable" : "disable",
1327 zebra_route_string(client
->proto
), ifp
->vrf
->vrf_id
);
1333 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1334 interfaces_configured_for_ra_from_bgp
++;
1336 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1337 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1339 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1340 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1341 VTY_RA_INTERVAL_CONFIGURED
))
1342 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1344 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1345 interfaces_configured_for_ra_from_bgp
--;
1347 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1348 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1349 VTY_RA_INTERVAL_CONFIGURED
))
1350 zif
->rtadv
.MaxRtrAdvInterval
=
1351 RTADV_MAX_RTR_ADV_INTERVAL
;
1352 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1353 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1360 * send router lifetime value of zero in RAs on this interface since we're
1361 * ceasing to advertise and want to let our neighbors know.
1362 * RFC 4861 secion 6.2.5
1364 void rtadv_stop_ra(struct interface
*ifp
)
1366 struct zebra_if
*zif
;
1367 struct zebra_vrf
*zvrf
;
1370 zvrf
= rtadv_interface_get_zvrf(ifp
);
1372 if (zif
->rtadv
.AdvSendAdvertisements
)
1373 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1377 * Send router lifetime value of zero in RAs on all interfaces since we're
1378 * ceasing to advertise globally and want to let all of our neighbors know
1379 * RFC 4861 secion 6.2.5
1381 * Delete all ipv6 global prefixes added to the router advertisement prefix
1382 * lists prior to ceasing.
1384 void rtadv_stop_ra_all(void)
1387 struct interface
*ifp
;
1388 struct zebra_if
*zif
;
1389 struct rtadv_prefix
*rprefix
;
1391 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1392 FOR_ALL_INTERFACES (vrf
, ifp
) {
1395 frr_each_safe (rtadv_prefixes
, zif
->rtadv
.prefixes
,
1397 rtadv_prefix_reset(zif
, rprefix
);
1403 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1405 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1407 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1409 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1412 static void show_zvrf_rtadv_adv_if_helper(struct vty
*vty
,
1413 struct adv_if_list_head
*adv_if_head
)
1415 struct adv_if
*node
= NULL
;
1417 if (!adv_if_is_empty_internal(adv_if_head
)) {
1418 frr_each (adv_if_list
, adv_if_head
, node
) {
1419 vty_out(vty
, " %s\n", node
->name
);
1426 static void show_zvrf_rtadv_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
)
1428 vty_out(vty
, "VRF: %s\n", zvrf_name(zvrf
));
1429 vty_out(vty
, " Interfaces:\n");
1430 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_if
);
1432 vty_out(vty
, " Interfaces(msec):\n");
1433 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_msec_if
);
1436 DEFPY(show_ipv6_nd_ra_if
, show_ipv6_nd_ra_if_cmd
,
1437 "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
1439 "Neighbor discovery\n"
1440 "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR
)
1442 struct zebra_vrf
*zvrf
= NULL
;
1444 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1446 "%% VRF subcommand only applicable for netns-based vrfs.\n");
1453 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1454 struct zebra_vrf
*zvrf
;
1460 show_zvrf_rtadv_helper(vty
, zvrf
);
1467 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1469 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1472 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1477 show_zvrf_rtadv_helper(vty
, zvrf
);
1482 DEFUN (ipv6_nd_ra_fast_retrans
,
1483 ipv6_nd_ra_fast_retrans_cmd
,
1484 "ipv6 nd ra-fast-retrans",
1485 "Interface IPv6 config commands\n"
1486 "Neighbor discovery\n"
1487 "Fast retransmit of RA packets\n")
1489 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1490 struct zebra_if
*zif
= ifp
->info
;
1492 if (if_is_loopback(ifp
)) {
1494 "Cannot configure IPv6 Router Advertisements on this interface\n");
1495 return CMD_WARNING_CONFIG_FAILED
;
1498 zif
->rtadv
.UseFastRexmit
= true;
1503 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1504 no_ipv6_nd_ra_fast_retrans_cmd
,
1505 "no ipv6 nd ra-fast-retrans",
1507 "Interface IPv6 config commands\n"
1508 "Neighbor discovery\n"
1509 "Fast retransmit of RA packets\n")
1511 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1512 struct zebra_if
*zif
= ifp
->info
;
1514 if (if_is_loopback(ifp
)) {
1516 "Cannot configure IPv6 Router Advertisements on this interface\n");
1517 return CMD_WARNING_CONFIG_FAILED
;
1520 zif
->rtadv
.UseFastRexmit
= false;
1525 DEFPY (ipv6_nd_ra_hop_limit
,
1526 ipv6_nd_ra_hop_limit_cmd
,
1527 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1528 "Interface IPv6 config commands\n"
1529 "Neighbor discovery\n"
1530 "Advertisement Hop Limit\n"
1531 "Advertisement Hop Limit in hops (default:64)\n")
1533 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1534 struct zebra_if
*zif
= ifp
->info
;
1536 if (if_is_loopback(ifp
)) {
1538 "Cannot configure IPv6 Router Advertisements on this interface\n");
1539 return CMD_WARNING_CONFIG_FAILED
;
1542 zif
->rtadv
.AdvCurHopLimit
= hopcount
;
1547 DEFPY (no_ipv6_nd_ra_hop_limit
,
1548 no_ipv6_nd_ra_hop_limit_cmd
,
1549 "no ipv6 nd ra-hop-limit [(0-255)]",
1551 "Interface IPv6 config commands\n"
1552 "Neighbor discovery\n"
1553 "Advertisement Hop Limit\n"
1554 "Advertisement Hop Limit in hops\n")
1556 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1557 struct zebra_if
*zif
= ifp
->info
;
1559 if (if_is_loopback(ifp
)) {
1561 "Cannot configure IPv6 Router Advertisements on this interface\n");
1562 return CMD_WARNING_CONFIG_FAILED
;
1565 zif
->rtadv
.AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
1570 DEFPY (ipv6_nd_ra_retrans_interval
,
1571 ipv6_nd_ra_retrans_interval_cmd
,
1572 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1573 "Interface IPv6 config commands\n"
1574 "Neighbor discovery\n"
1575 "Advertisement Retransmit Interval\n"
1576 "Advertisement Retransmit Interval in msec\n")
1578 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1579 struct zebra_if
*zif
= ifp
->info
;
1581 if (if_is_loopback(ifp
)) {
1583 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1584 return CMD_WARNING_CONFIG_FAILED
;
1587 zif
->rtadv
.AdvRetransTimer
= interval
;
1592 DEFPY (no_ipv6_nd_ra_retrans_interval
,
1593 no_ipv6_nd_ra_retrans_interval_cmd
,
1594 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1596 "Interface IPv6 config commands\n"
1597 "Neighbor discovery\n"
1598 "Advertisement Retransmit Interval\n"
1599 "Advertisement Retransmit Interval in msec\n")
1601 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1602 struct zebra_if
*zif
= ifp
->info
;
1604 if (if_is_loopback(ifp
)) {
1606 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1607 return CMD_WARNING_CONFIG_FAILED
;
1610 zif
->rtadv
.AdvRetransTimer
= 0;
1615 DEFUN (ipv6_nd_suppress_ra
,
1616 ipv6_nd_suppress_ra_cmd
,
1617 "ipv6 nd suppress-ra",
1618 "Interface IPv6 config commands\n"
1619 "Neighbor discovery\n"
1620 "Suppress Router Advertisement\n")
1622 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1623 struct zebra_if
*zif
= ifp
->info
;
1625 if (if_is_loopback(ifp
)) {
1627 "Cannot configure IPv6 Router Advertisements on this interface\n");
1628 return CMD_WARNING_CONFIG_FAILED
;
1631 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1632 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1634 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1638 DEFUN (no_ipv6_nd_suppress_ra
,
1639 no_ipv6_nd_suppress_ra_cmd
,
1640 "no ipv6 nd suppress-ra",
1642 "Interface IPv6 config commands\n"
1643 "Neighbor discovery\n"
1644 "Suppress Router Advertisement\n")
1646 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1647 struct zebra_if
*zif
= ifp
->info
;
1649 if (if_is_loopback(ifp
)) {
1651 "Cannot configure IPv6 Router Advertisements on this interface\n");
1652 return CMD_WARNING_CONFIG_FAILED
;
1655 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1656 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1660 DEFUN (ipv6_nd_ra_interval_msec
,
1661 ipv6_nd_ra_interval_msec_cmd
,
1662 "ipv6 nd ra-interval msec (70-1800000)",
1663 "Interface IPv6 config commands\n"
1664 "Neighbor discovery\n"
1665 "Router Advertisement interval\n"
1666 "Router Advertisement interval in milliseconds\n"
1667 "Router Advertisement interval in milliseconds\n")
1670 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1672 struct zebra_if
*zif
= ifp
->info
;
1673 struct zebra_vrf
*zvrf
;
1674 struct adv_if
*adv_if
;
1676 zvrf
= rtadv_interface_get_zvrf(ifp
);
1678 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1679 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1680 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1682 "This ra-interval would conflict with configured ra-lifetime!\n");
1683 return CMD_WARNING_CONFIG_FAILED
;
1686 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1687 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1689 adv_if_free(adv_if
);
1692 if (interval
% 1000)
1693 (void)adv_msec_if_add(zvrf
, ifp
->name
);
1695 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1696 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1697 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1698 zif
->rtadv
.AdvIntervalTimer
= 0;
1703 DEFUN (ipv6_nd_ra_interval
,
1704 ipv6_nd_ra_interval_cmd
,
1705 "ipv6 nd ra-interval (1-1800)",
1706 "Interface IPv6 config commands\n"
1707 "Neighbor discovery\n"
1708 "Router Advertisement interval\n"
1709 "Router Advertisement interval in seconds\n")
1712 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1714 struct zebra_if
*zif
= ifp
->info
;
1715 struct zebra_vrf
*zvrf
;
1716 struct adv_if
*adv_if
;
1718 zvrf
= rtadv_interface_get_zvrf(ifp
);
1720 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1721 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1722 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1724 "This ra-interval would conflict with configured ra-lifetime!\n");
1725 return CMD_WARNING_CONFIG_FAILED
;
1728 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1729 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1731 adv_if_free(adv_if
);
1734 /* convert to milliseconds */
1735 interval
= interval
* 1000;
1737 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1738 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1739 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1740 zif
->rtadv
.AdvIntervalTimer
= 0;
1745 DEFUN (no_ipv6_nd_ra_interval
,
1746 no_ipv6_nd_ra_interval_cmd
,
1747 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1749 "Interface IPv6 config commands\n"
1750 "Neighbor discovery\n"
1751 "Router Advertisement interval\n"
1752 "Router Advertisement interval in seconds\n"
1753 "Specify millisecond router advertisement interval\n"
1754 "Router Advertisement interval in milliseconds\n")
1756 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1757 struct zebra_if
*zif
= ifp
->info
;
1758 struct zebra_vrf
*zvrf
= NULL
;
1759 struct adv_if
*adv_if
;
1761 zvrf
= rtadv_interface_get_zvrf(ifp
);
1763 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1764 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1766 adv_if_free(adv_if
);
1769 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1771 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1772 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1774 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1776 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1777 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1782 DEFUN (ipv6_nd_ra_lifetime
,
1783 ipv6_nd_ra_lifetime_cmd
,
1784 "ipv6 nd ra-lifetime (0-9000)",
1785 "Interface IPv6 config commands\n"
1786 "Neighbor discovery\n"
1788 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1791 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1792 struct zebra_if
*zif
= ifp
->info
;
1795 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1797 /* The value to be placed in the Router Lifetime field
1798 * of Router Advertisements sent from the interface,
1799 * in seconds. MUST be either zero or between
1800 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1801 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1803 "This ra-lifetime would conflict with configured ra-interval\n");
1804 return CMD_WARNING_CONFIG_FAILED
;
1807 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1812 DEFUN (no_ipv6_nd_ra_lifetime
,
1813 no_ipv6_nd_ra_lifetime_cmd
,
1814 "no ipv6 nd ra-lifetime [(0-9000)]",
1816 "Interface IPv6 config commands\n"
1817 "Neighbor discovery\n"
1819 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1821 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1822 struct zebra_if
*zif
= ifp
->info
;
1824 zif
->rtadv
.AdvDefaultLifetime
= -1;
1829 DEFUN (ipv6_nd_reachable_time
,
1830 ipv6_nd_reachable_time_cmd
,
1831 "ipv6 nd reachable-time (1-3600000)",
1832 "Interface IPv6 config commands\n"
1833 "Neighbor discovery\n"
1835 "Reachable time in milliseconds\n")
1838 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1839 struct zebra_if
*zif
= ifp
->info
;
1840 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1844 DEFUN (no_ipv6_nd_reachable_time
,
1845 no_ipv6_nd_reachable_time_cmd
,
1846 "no ipv6 nd reachable-time [(1-3600000)]",
1848 "Interface IPv6 config commands\n"
1849 "Neighbor discovery\n"
1851 "Reachable time in milliseconds\n")
1853 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1854 struct zebra_if
*zif
= ifp
->info
;
1856 zif
->rtadv
.AdvReachableTime
= 0;
1861 DEFUN (ipv6_nd_homeagent_preference
,
1862 ipv6_nd_homeagent_preference_cmd
,
1863 "ipv6 nd home-agent-preference (0-65535)",
1864 "Interface IPv6 config commands\n"
1865 "Neighbor discovery\n"
1866 "Home Agent preference\n"
1867 "preference value (default is 0, least preferred)\n")
1870 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1871 struct zebra_if
*zif
= ifp
->info
;
1872 zif
->rtadv
.HomeAgentPreference
=
1873 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1877 DEFUN (no_ipv6_nd_homeagent_preference
,
1878 no_ipv6_nd_homeagent_preference_cmd
,
1879 "no ipv6 nd home-agent-preference [(0-65535)]",
1881 "Interface IPv6 config commands\n"
1882 "Neighbor discovery\n"
1883 "Home Agent preference\n"
1884 "preference value (default is 0, least preferred)\n")
1886 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1887 struct zebra_if
*zif
= ifp
->info
;
1889 zif
->rtadv
.HomeAgentPreference
= 0;
1894 DEFUN (ipv6_nd_homeagent_lifetime
,
1895 ipv6_nd_homeagent_lifetime_cmd
,
1896 "ipv6 nd home-agent-lifetime (0-65520)",
1897 "Interface IPv6 config commands\n"
1898 "Neighbor discovery\n"
1899 "Home Agent lifetime\n"
1900 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1903 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1904 struct zebra_if
*zif
= ifp
->info
;
1905 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1909 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1910 no_ipv6_nd_homeagent_lifetime_cmd
,
1911 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1913 "Interface IPv6 config commands\n"
1914 "Neighbor discovery\n"
1915 "Home Agent lifetime\n"
1916 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1918 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1919 struct zebra_if
*zif
= ifp
->info
;
1921 zif
->rtadv
.HomeAgentLifetime
= -1;
1926 DEFUN (ipv6_nd_managed_config_flag
,
1927 ipv6_nd_managed_config_flag_cmd
,
1928 "ipv6 nd managed-config-flag",
1929 "Interface IPv6 config commands\n"
1930 "Neighbor discovery\n"
1931 "Managed address configuration flag\n")
1933 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1934 struct zebra_if
*zif
= ifp
->info
;
1936 zif
->rtadv
.AdvManagedFlag
= 1;
1941 DEFUN (no_ipv6_nd_managed_config_flag
,
1942 no_ipv6_nd_managed_config_flag_cmd
,
1943 "no ipv6 nd managed-config-flag",
1945 "Interface IPv6 config commands\n"
1946 "Neighbor discovery\n"
1947 "Managed address configuration flag\n")
1949 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1950 struct zebra_if
*zif
= ifp
->info
;
1952 zif
->rtadv
.AdvManagedFlag
= 0;
1957 DEFUN (ipv6_nd_homeagent_config_flag
,
1958 ipv6_nd_homeagent_config_flag_cmd
,
1959 "ipv6 nd home-agent-config-flag",
1960 "Interface IPv6 config commands\n"
1961 "Neighbor discovery\n"
1962 "Home Agent configuration flag\n")
1964 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1965 struct zebra_if
*zif
= ifp
->info
;
1967 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1972 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1973 no_ipv6_nd_homeagent_config_flag_cmd
,
1974 "no ipv6 nd home-agent-config-flag",
1976 "Interface IPv6 config commands\n"
1977 "Neighbor discovery\n"
1978 "Home Agent configuration flag\n")
1980 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1981 struct zebra_if
*zif
= ifp
->info
;
1983 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1988 DEFUN (ipv6_nd_adv_interval_config_option
,
1989 ipv6_nd_adv_interval_config_option_cmd
,
1990 "ipv6 nd adv-interval-option",
1991 "Interface IPv6 config commands\n"
1992 "Neighbor discovery\n"
1993 "Advertisement Interval Option\n")
1995 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1996 struct zebra_if
*zif
= ifp
->info
;
1998 zif
->rtadv
.AdvIntervalOption
= 1;
2003 DEFUN (no_ipv6_nd_adv_interval_config_option
,
2004 no_ipv6_nd_adv_interval_config_option_cmd
,
2005 "no ipv6 nd adv-interval-option",
2007 "Interface IPv6 config commands\n"
2008 "Neighbor discovery\n"
2009 "Advertisement Interval Option\n")
2011 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2012 struct zebra_if
*zif
= ifp
->info
;
2014 zif
->rtadv
.AdvIntervalOption
= 0;
2019 DEFUN (ipv6_nd_other_config_flag
,
2020 ipv6_nd_other_config_flag_cmd
,
2021 "ipv6 nd other-config-flag",
2022 "Interface IPv6 config commands\n"
2023 "Neighbor discovery\n"
2024 "Other statefull configuration flag\n")
2026 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2027 struct zebra_if
*zif
= ifp
->info
;
2029 zif
->rtadv
.AdvOtherConfigFlag
= 1;
2034 DEFUN (no_ipv6_nd_other_config_flag
,
2035 no_ipv6_nd_other_config_flag_cmd
,
2036 "no ipv6 nd other-config-flag",
2038 "Interface IPv6 config commands\n"
2039 "Neighbor discovery\n"
2040 "Other statefull configuration flag\n")
2042 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2043 struct zebra_if
*zif
= ifp
->info
;
2045 zif
->rtadv
.AdvOtherConfigFlag
= 0;
2050 DEFUN (ipv6_nd_prefix
,
2052 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2053 "Interface IPv6 config commands\n"
2054 "Neighbor discovery\n"
2055 "Prefix information\n"
2057 "Valid lifetime in seconds\n"
2058 "Infinite valid lifetime\n"
2059 "Preferred lifetime in seconds\n"
2060 "Infinite preferred lifetime\n"
2061 "Set Router Address flag\n"
2062 "Do not use prefix for onlink determination\n"
2063 "Do not use prefix for autoconfiguration\n"
2064 "Do not use prefix for autoconfiguration\n"
2065 "Do not use prefix for onlink determination\n")
2068 char *prefix
= argv
[3]->arg
;
2069 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
2070 || strmatch(argv
[4]->text
, "infinite"));
2071 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
2073 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
2075 char *lifetime
= NULL
, *preflifetime
= NULL
;
2076 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
2078 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2080 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
2085 strmatch(argv
[idx_routeropts
]->text
, "router-address");
2087 offlink
= (argc
> idx_routeropts
+ 1
2088 || strmatch(argv
[idx_routeropts
]->text
,
2090 noautoconf
= (argc
> idx_routeropts
+ 1
2091 || strmatch(argv
[idx_routeropts
]->text
,
2097 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2098 struct zebra_if
*zebra_if
= ifp
->info
;
2100 struct rtadv_prefix rp
;
2102 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2104 vty_out(vty
, "Malformed IPv6 prefix\n");
2105 return CMD_WARNING_CONFIG_FAILED
;
2107 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2108 rp
.AdvOnLinkFlag
= !offlink
;
2109 rp
.AdvAutonomousFlag
= !noautoconf
;
2110 rp
.AdvRouterAddressFlag
= routeraddr
;
2111 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
2112 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
2113 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2116 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
2118 : strtoll(lifetime
, NULL
, 10);
2119 rp
.AdvPreferredLifetime
=
2120 strmatch(preflifetime
, "infinite")
2122 : strtoll(preflifetime
, NULL
, 10);
2123 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
2124 vty_out(vty
, "Invalid preferred lifetime\n");
2125 return CMD_WARNING_CONFIG_FAILED
;
2129 rtadv_prefix_set(zebra_if
, &rp
);
2134 DEFUN (no_ipv6_nd_prefix
,
2135 no_ipv6_nd_prefix_cmd
,
2136 "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]>]",
2138 "Interface IPv6 config commands\n"
2139 "Neighbor discovery\n"
2140 "Prefix information\n"
2142 "Valid lifetime in seconds\n"
2143 "Infinite valid lifetime\n"
2144 "Preferred lifetime in seconds\n"
2145 "Infinite preferred lifetime\n"
2146 "Set Router Address flag\n"
2147 "Do not use prefix for onlink determination\n"
2148 "Do not use prefix for autoconfiguration\n"
2149 "Do not use prefix for autoconfiguration\n"
2150 "Do not use prefix for onlink determination\n")
2152 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2153 struct zebra_if
*zebra_if
= ifp
->info
;
2155 struct rtadv_prefix rp
;
2156 char *prefix
= argv
[4]->arg
;
2158 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2160 vty_out(vty
, "Malformed IPv6 prefix\n");
2161 return CMD_WARNING_CONFIG_FAILED
;
2163 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2164 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2166 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
2168 vty_out(vty
, "Non-existant IPv6 prefix\n");
2169 return CMD_WARNING_CONFIG_FAILED
;
2175 DEFUN (ipv6_nd_router_preference
,
2176 ipv6_nd_router_preference_cmd
,
2177 "ipv6 nd router-preference <high|medium|low>",
2178 "Interface IPv6 config commands\n"
2179 "Neighbor discovery\n"
2180 "Default router preference\n"
2181 "High default router preference\n"
2182 "Medium default router preference (default)\n"
2183 "Low default router preference\n")
2185 int idx_high_medium_low
= 3;
2186 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2187 struct zebra_if
*zif
= ifp
->info
;
2190 while (0 != rtadv_pref_strs
[i
]) {
2191 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
2194 zif
->rtadv
.DefaultPreference
= i
;
2200 return CMD_ERR_NO_MATCH
;
2203 DEFUN (no_ipv6_nd_router_preference
,
2204 no_ipv6_nd_router_preference_cmd
,
2205 "no ipv6 nd router-preference [<high|medium|low>]",
2207 "Interface IPv6 config commands\n"
2208 "Neighbor discovery\n"
2209 "Default router preference\n"
2210 "High default router preference\n"
2211 "Medium default router preference (default)\n"
2212 "Low default router preference\n")
2214 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2215 struct zebra_if
*zif
= ifp
->info
;
2217 zif
->rtadv
.DefaultPreference
=
2218 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
2225 "ipv6 nd mtu (1-65535)",
2226 "Interface IPv6 config commands\n"
2227 "Neighbor discovery\n"
2232 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2233 struct zebra_if
*zif
= ifp
->info
;
2234 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2238 DEFUN (no_ipv6_nd_mtu
,
2240 "no ipv6 nd mtu [(1-65535)]",
2242 "Interface IPv6 config commands\n"
2243 "Neighbor discovery\n"
2247 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2248 struct zebra_if
*zif
= ifp
->info
;
2249 zif
->rtadv
.AdvLinkMTU
= 0;
2253 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
2255 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
2258 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
2260 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
2263 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
2264 struct rtadv_rdnss
*rdnss
)
2266 struct listnode
*node
;
2267 struct rtadv_rdnss
*p
;
2269 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2270 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
2275 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
2276 struct rtadv_rdnss
*rdnss
)
2278 struct rtadv_rdnss
*p
;
2280 p
= rtadv_rdnss_lookup(list
, rdnss
);
2284 p
= rtadv_rdnss_new();
2285 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
2286 listnode_add(list
, p
);
2291 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2293 struct rtadv_rdnss
*p
;
2295 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2296 p
->lifetime
= rdnss
->lifetime
;
2297 p
->lifetime_set
= rdnss
->lifetime_set
;
2300 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2302 struct rtadv_rdnss
*p
;
2304 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2306 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
2307 rtadv_rdnss_free(p
);
2314 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
2316 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
2319 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
2321 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
2324 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
2325 struct rtadv_dnssl
*dnssl
)
2327 struct listnode
*node
;
2328 struct rtadv_dnssl
*p
;
2330 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2331 if (!strcasecmp(p
->name
, dnssl
->name
))
2336 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
2337 struct rtadv_dnssl
*dnssl
)
2339 struct rtadv_dnssl
*p
;
2341 p
= rtadv_dnssl_lookup(list
, dnssl
);
2345 p
= rtadv_dnssl_new();
2346 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2347 listnode_add(list
, p
);
2352 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2354 struct rtadv_dnssl
*p
;
2356 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2357 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2360 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2362 struct rtadv_dnssl
*p
;
2364 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2366 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
2367 rtadv_dnssl_free(p
);
2375 * Convert dotted domain name (with or without trailing root zone dot) to
2376 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2377 * to strlen(in) + 2 octets to out.
2379 * Returns the number of octets written to out or -1 if in does not constitute
2380 * a valid domain name.
2382 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
2384 const char *label_start
, *label_end
;
2390 while (*label_start
) {
2393 label_end
= strchr(label_start
, '.');
2394 if (label_end
== NULL
)
2395 label_end
= label_start
+ strlen(label_start
);
2397 label_len
= label_end
- label_start
;
2398 if (label_len
>= 64)
2399 return -1; /* labels must be 63 octets or less */
2401 out
[outp
++] = (uint8_t)label_len
;
2402 memcpy(out
+ outp
, label_start
, label_len
);
2404 label_start
+= label_len
;
2405 if (*label_start
== '.')
2413 DEFUN(ipv6_nd_rdnss
,
2415 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2416 "Interface IPv6 config commands\n"
2417 "Neighbor discovery\n"
2418 "Recursive DNS server information\n"
2420 "Valid lifetime in seconds\n"
2421 "Infinite valid lifetime\n")
2423 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2424 struct zebra_if
*zif
= ifp
->info
;
2425 struct rtadv_rdnss rdnss
= {};
2427 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
2428 vty_out(vty
, "Malformed IPv6 address\n");
2429 return CMD_WARNING_CONFIG_FAILED
;
2432 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2434 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
2436 : strtoll(lifetime
, NULL
, 10);
2437 rdnss
.lifetime_set
= 1;
2440 rtadv_rdnss_set(zif
, &rdnss
);
2445 DEFUN(no_ipv6_nd_rdnss
,
2446 no_ipv6_nd_rdnss_cmd
,
2447 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2449 "Interface IPv6 config commands\n"
2450 "Neighbor discovery\n"
2451 "Recursive DNS server information\n"
2453 "Valid lifetime in seconds\n"
2454 "Infinite valid lifetime\n")
2456 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2457 struct zebra_if
*zif
= ifp
->info
;
2458 struct rtadv_rdnss rdnss
= {};
2460 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
2461 vty_out(vty
, "Malformed IPv6 address\n");
2462 return CMD_WARNING_CONFIG_FAILED
;
2464 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
2465 vty_out(vty
, "Non-existant RDNSS address\n");
2466 return CMD_WARNING_CONFIG_FAILED
;
2472 DEFUN(ipv6_nd_dnssl
,
2474 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2475 "Interface IPv6 config commands\n"
2476 "Neighbor discovery\n"
2477 "DNS search list information\n"
2478 "Domain name suffix\n"
2479 "Valid lifetime in seconds\n"
2480 "Infinite valid lifetime\n")
2482 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2483 struct zebra_if
*zif
= ifp
->info
;
2484 struct rtadv_dnssl dnssl
= {};
2488 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
2489 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2490 vty_out(vty
, "Malformed DNS search domain\n");
2491 return CMD_WARNING_CONFIG_FAILED
;
2493 if (dnssl
.name
[len
- 1] == '.') {
2495 * Allow, but don't require, a trailing dot signifying the root
2496 * zone. Canonicalize by cutting it off if present.
2498 dnssl
.name
[len
- 1] = '\0';
2502 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2504 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
2506 : strtoll(lifetime
, NULL
, 10);
2507 dnssl
.lifetime_set
= 1;
2510 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2512 vty_out(vty
, "Malformed DNS search domain\n");
2513 return CMD_WARNING_CONFIG_FAILED
;
2515 dnssl
.encoded_len
= ret
;
2516 rtadv_dnssl_set(zif
, &dnssl
);
2521 DEFUN(no_ipv6_nd_dnssl
,
2522 no_ipv6_nd_dnssl_cmd
,
2523 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2525 "Interface IPv6 config commands\n"
2526 "Neighbor discovery\n"
2527 "DNS search list information\n"
2528 "Domain name suffix\n"
2529 "Valid lifetime in seconds\n"
2530 "Infinite valid lifetime\n")
2532 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2533 struct zebra_if
*zif
= ifp
->info
;
2534 struct rtadv_dnssl dnssl
= {};
2537 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2538 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2539 vty_out(vty
, "Malformed DNS search domain\n");
2540 return CMD_WARNING_CONFIG_FAILED
;
2542 if (dnssl
.name
[len
- 1] == '.') {
2543 dnssl
.name
[len
- 1] = '\0';
2546 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2547 vty_out(vty
, "Non-existant DNS search domain\n");
2548 return CMD_WARNING_CONFIG_FAILED
;
2555 /* Dump interface ND information to vty. */
2556 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2558 struct zebra_if
*zif
;
2559 struct rtadvconf
*rtadv
;
2562 zif
= (struct zebra_if
*)ifp
->info
;
2563 rtadv
= &zif
->rtadv
;
2565 if (rtadv
->AdvSendAdvertisements
) {
2567 " ND advertised reachable time is %d milliseconds\n",
2568 rtadv
->AdvReachableTime
);
2570 " ND advertised retransmit interval is %u milliseconds\n",
2571 rtadv
->AdvRetransTimer
);
2572 vty_out(vty
, " ND advertised hop-count limit is %d hops\n",
2573 rtadv
->AdvCurHopLimit
);
2574 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2575 zif
->ra_sent
, zif
->ra_rcvd
);
2576 interval
= rtadv
->MaxRtrAdvInterval
;
2577 if (interval
% 1000)
2579 " ND router advertisements are sent every %d milliseconds\n",
2583 " ND router advertisements are sent every %d seconds\n",
2585 if (!rtadv
->UseFastRexmit
)
2587 " ND router advertisements do not use fast retransmit\n");
2589 if (rtadv
->AdvDefaultLifetime
!= -1)
2591 " ND router advertisements live for %d seconds\n",
2592 rtadv
->AdvDefaultLifetime
);
2595 " ND router advertisements lifetime tracks ra-interval\n");
2597 " ND router advertisement default router preference is %s\n",
2598 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2599 if (rtadv
->AdvManagedFlag
)
2601 " Hosts use DHCP to obtain routable addresses.\n");
2604 " Hosts use stateless autoconfig for addresses.\n");
2605 if (rtadv
->AdvHomeAgentFlag
) {
2607 " ND router advertisements with Home Agent flag bit set.\n");
2608 if (rtadv
->HomeAgentLifetime
!= -1)
2610 " Home Agent lifetime is %u seconds\n",
2611 rtadv
->HomeAgentLifetime
);
2614 " Home Agent lifetime tracks ra-lifetime\n");
2615 vty_out(vty
, " Home Agent preference is %u\n",
2616 rtadv
->HomeAgentPreference
);
2618 if (rtadv
->AdvIntervalOption
)
2620 " ND router advertisements with Adv. Interval option.\n");
2626 /* Write configuration about router advertisement. */
2627 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2629 struct zebra_if
*zif
;
2630 struct listnode
*node
;
2631 struct rtadv_prefix
*rprefix
;
2632 struct rtadv_rdnss
*rdnss
;
2633 struct rtadv_dnssl
*dnssl
;
2638 if (!if_is_loopback(ifp
)) {
2639 if (zif
->rtadv
.AdvSendAdvertisements
2640 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2641 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2644 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2645 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2646 if (interval
% 1000)
2647 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2649 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2650 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2654 if (zif
->rtadv
.AdvIntervalOption
)
2655 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2657 if (!zif
->rtadv
.UseFastRexmit
)
2658 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2660 if (zif
->rtadv
.AdvRetransTimer
!= 0)
2661 vty_out(vty
, " ipv6 nd ra-retrans-interval %u\n",
2662 zif
->rtadv
.AdvRetransTimer
);
2664 if (zif
->rtadv
.AdvCurHopLimit
!= RTADV_DEFAULT_HOPLIMIT
)
2665 vty_out(vty
, " ipv6 nd ra-hop-limit %d\n",
2666 zif
->rtadv
.AdvCurHopLimit
);
2668 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2669 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2670 zif
->rtadv
.AdvDefaultLifetime
);
2672 if (zif
->rtadv
.HomeAgentPreference
)
2673 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2674 zif
->rtadv
.HomeAgentPreference
);
2676 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2677 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2678 zif
->rtadv
.HomeAgentLifetime
);
2680 if (zif
->rtadv
.AdvHomeAgentFlag
)
2681 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2683 if (zif
->rtadv
.AdvReachableTime
)
2684 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2685 zif
->rtadv
.AdvReachableTime
);
2687 if (zif
->rtadv
.AdvManagedFlag
)
2688 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2690 if (zif
->rtadv
.AdvOtherConfigFlag
)
2691 vty_out(vty
, " ipv6 nd other-config-flag\n");
2693 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2694 vty_out(vty
, " ipv6 nd router-preference %s\n",
2695 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2697 if (zif
->rtadv
.AdvLinkMTU
)
2698 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2700 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
2701 if ((rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
2702 || (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
)) {
2703 vty_out(vty
, " ipv6 nd prefix %pFX", &rprefix
->prefix
);
2704 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2705 || (rprefix
->AdvPreferredLifetime
2706 != RTADV_PREFERRED_LIFETIME
)) {
2707 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2708 vty_out(vty
, " infinite");
2711 rprefix
->AdvValidLifetime
);
2712 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2713 vty_out(vty
, " infinite");
2716 rprefix
->AdvPreferredLifetime
);
2718 if (!rprefix
->AdvOnLinkFlag
)
2719 vty_out(vty
, " off-link");
2720 if (!rprefix
->AdvAutonomousFlag
)
2721 vty_out(vty
, " no-autoconfig");
2722 if (rprefix
->AdvRouterAddressFlag
)
2723 vty_out(vty
, " router-address");
2728 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2729 char buf
[INET6_ADDRSTRLEN
];
2731 vty_out(vty
, " ipv6 nd rdnss %s",
2732 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2733 if (rdnss
->lifetime_set
) {
2734 if (rdnss
->lifetime
== UINT32_MAX
)
2735 vty_out(vty
, " infinite");
2737 vty_out(vty
, " %u", rdnss
->lifetime
);
2741 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2742 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2743 if (dnssl
->lifetime_set
) {
2744 if (dnssl
->lifetime
== UINT32_MAX
)
2745 vty_out(vty
, " infinite");
2747 vty_out(vty
, " %u", dnssl
->lifetime
);
2755 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2757 struct rtadv
*rtadv
;
2759 if (IS_ZEBRA_DEBUG_EVENT
) {
2760 struct vrf
*vrf
= zvrf
->vrf
;
2762 zlog_debug("%s(%s) with event: %d and val: %d", __func__
,
2763 VRF_LOGNAME(vrf
), event
, val
);
2766 rtadv
= &zvrf
->rtadv
;
2770 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2772 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2776 THREAD_OFF(rtadv
->ra_timer
);
2777 THREAD_OFF(rtadv
->ra_read
);
2780 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2783 case RTADV_TIMER_MSEC
:
2784 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2788 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2797 void rtadv_if_up(struct zebra_if
*zif
)
2799 struct zebra_vrf
*zvrf
= rtadv_interface_get_zvrf(zif
->ifp
);
2801 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
2802 if (zif
->rtadv
.AdvSendAdvertisements
&&
2803 (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) &&
2804 zif
->rtadv
.UseFastRexmit
) {
2805 zif
->rtadv
.inFastRexmit
= 1;
2806 zif
->rtadv
.NumFastReXmitsRemain
= RTADV_NUM_FAST_REXMITS
;
2810 * startup the state machine, if it hasn't been already
2811 * due to a delayed ifindex on startup ordering
2813 if (zif
->rtadv
.AdvSendAdvertisements
)
2814 rtadv_start_interface_events(zvrf
, zif
);
2817 void rtadv_if_init(struct zebra_if
*zif
)
2819 /* Set default router advertise values. */
2820 struct rtadvconf
*rtadv
;
2822 rtadv
= &zif
->rtadv
;
2824 rtadv
->AdvSendAdvertisements
= 0;
2825 rtadv
->MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
2826 rtadv
->MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
2827 rtadv
->AdvIntervalTimer
= 0;
2828 rtadv
->AdvManagedFlag
= 0;
2829 rtadv
->AdvOtherConfigFlag
= 0;
2830 rtadv
->AdvHomeAgentFlag
= 0;
2831 rtadv
->AdvLinkMTU
= 0;
2832 rtadv
->AdvReachableTime
= 0;
2833 rtadv
->AdvRetransTimer
= 0;
2834 rtadv
->AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
2835 memset(&rtadv
->lastadvcurhoplimit
, 0,
2836 sizeof(rtadv
->lastadvcurhoplimit
));
2837 memset(&rtadv
->lastadvmanagedflag
, 0,
2838 sizeof(rtadv
->lastadvmanagedflag
));
2839 memset(&rtadv
->lastadvotherconfigflag
, 0,
2840 sizeof(rtadv
->lastadvotherconfigflag
));
2841 memset(&rtadv
->lastadvreachabletime
, 0,
2842 sizeof(rtadv
->lastadvreachabletime
));
2843 memset(&rtadv
->lastadvretranstimer
, 0,
2844 sizeof(rtadv
->lastadvretranstimer
));
2845 rtadv
->AdvDefaultLifetime
= -1; /* derive from MaxRtrAdvInterval */
2846 rtadv
->HomeAgentPreference
= 0;
2847 rtadv
->HomeAgentLifetime
= -1; /* derive from AdvDefaultLifetime */
2848 rtadv
->AdvIntervalOption
= 0;
2849 rtadv
->UseFastRexmit
= true;
2850 rtadv
->DefaultPreference
= RTADV_PREF_MEDIUM
;
2852 rtadv_prefixes_init(rtadv
->prefixes
);
2854 rtadv
->AdvRDNSSList
= list_new();
2855 rtadv
->AdvDNSSLList
= list_new();
2858 void rtadv_if_fini(struct zebra_if
*zif
)
2860 struct rtadvconf
*rtadv
;
2861 struct rtadv_prefix
*rp
;
2863 rtadv
= &zif
->rtadv
;
2865 while ((rp
= rtadv_prefixes_pop(rtadv
->prefixes
)))
2866 rtadv_prefix_free(rp
);
2868 list_delete(&rtadv
->AdvRDNSSList
);
2869 list_delete(&rtadv
->AdvDNSSLList
);
2872 void rtadv_vrf_init(struct zebra_vrf
*zvrf
)
2874 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2877 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2880 void rtadv_vrf_terminate(struct zebra_vrf
*zvrf
)
2882 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2885 rtadv_event(zvrf
, RTADV_STOP
, 0);
2886 if (zvrf
->rtadv
.sock
>= 0) {
2887 close(zvrf
->rtadv
.sock
);
2888 zvrf
->rtadv
.sock
= -1;
2892 adv_msec_if_clean(zvrf
);
2895 void rtadv_cmd_init(void)
2897 interfaces_configured_for_ra_from_bgp
= 0;
2899 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2900 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2902 install_element(VIEW_NODE
, &show_ipv6_nd_ra_if_cmd
);
2904 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2905 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2906 install_element(INTERFACE_NODE
, &ipv6_nd_ra_retrans_interval_cmd
);
2907 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_retrans_interval_cmd
);
2908 install_element(INTERFACE_NODE
, &ipv6_nd_ra_hop_limit_cmd
);
2909 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_hop_limit_cmd
);
2910 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2911 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2912 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2913 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2914 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2915 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2916 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2917 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2918 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2919 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2920 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2921 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2922 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2923 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2924 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2925 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2926 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2927 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2928 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2929 install_element(INTERFACE_NODE
,
2930 &ipv6_nd_adv_interval_config_option_cmd
);
2931 install_element(INTERFACE_NODE
,
2932 &no_ipv6_nd_adv_interval_config_option_cmd
);
2933 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2934 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2935 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2936 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2937 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2938 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2939 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2940 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2941 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2942 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2945 static int if_join_all_router(int sock
, struct interface
*ifp
)
2949 struct ipv6_mreq mreq
;
2951 memset(&mreq
, 0, sizeof(mreq
));
2952 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2953 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2955 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2958 flog_err_sys(EC_LIB_SOCKET
,
2959 "%s(%u): Failed to join group, socket %u error %s",
2960 ifp
->name
, ifp
->ifindex
, sock
,
2961 safe_strerror(errno
));
2963 if (IS_ZEBRA_DEBUG_EVENT
)
2965 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2966 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
2971 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2975 struct ipv6_mreq mreq
;
2977 memset(&mreq
, 0, sizeof(mreq
));
2978 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2979 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2981 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2986 "%s(%s:%u): Failed to leave group, socket %u error %s",
2987 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
,
2988 safe_strerror(errno
));
2990 if (IS_ZEBRA_DEBUG_EVENT
)
2992 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
2993 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
2998 bool rtadv_compiled_in(void)
3003 #else /* !HAVE_RTADV */
3005 * If the end user does not have RADV enabled we should
3006 * handle this better
3008 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
3010 if (IS_ZEBRA_DEBUG_PACKET
)
3012 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3013 zserv_command_string(hdr
->command
));
3018 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
3020 if (IS_ZEBRA_DEBUG_PACKET
)
3022 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3023 zserv_command_string(hdr
->command
));
3028 bool rtadv_compiled_in(void)
3033 #endif /* HAVE_RTADV */
3035 uint32_t rtadv_get_interfaces_configured_from_bgp(void)
3037 return interfaces_configured_for_ra_from_bgp
;