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 ipv6_nd_suppress_ra_set(struct interface
*ifp
,
1209 enum ipv6_nd_suppress_ra_status status
)
1211 struct zebra_if
*zif
;
1212 struct zebra_vrf
*zvrf
;
1213 struct adv_if
*adv_if
= NULL
;
1217 zvrf
= rtadv_interface_get_zvrf(ifp
);
1219 if (status
== RA_SUPPRESS
) {
1220 /* RA is currently enabled */
1221 if (zif
->rtadv
.AdvSendAdvertisements
) {
1222 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1223 zif
->rtadv
.AdvSendAdvertisements
= 0;
1224 zif
->rtadv
.AdvIntervalTimer
= 0;
1226 adv_if
= adv_if_del(zvrf
, ifp
->name
);
1228 return; /* Nothing to delete */
1230 adv_if_free(adv_if
);
1232 if_leave_all_router(zvrf
->rtadv
.sock
, ifp
);
1234 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 0)
1235 rtadv_event(zvrf
, RTADV_STOP
, 0);
1238 if (!zif
->rtadv
.AdvSendAdvertisements
) {
1239 zif
->rtadv
.AdvSendAdvertisements
= 1;
1240 zif
->rtadv
.AdvIntervalTimer
= 0;
1241 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
1242 && zif
->rtadv
.UseFastRexmit
) {
1244 * Enable Fast RA only when RA interval is in
1245 * secs and Fast RA retransmit is enabled
1247 zif
->rtadv
.inFastRexmit
= 1;
1248 zif
->rtadv
.NumFastReXmitsRemain
=
1249 RTADV_NUM_FAST_REXMITS
;
1252 adv_if
= adv_if_add(zvrf
, ifp
->name
);
1254 return; /* Alread added */
1256 if_join_all_router(zvrf
->rtadv
.sock
, ifp
);
1258 if (adv_if_list_count(&zvrf
->rtadv
.adv_if
) == 1)
1259 rtadv_event(zvrf
, RTADV_START
, 0);
1265 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1266 * Note that while the client could request RA on an interface on which the
1267 * operator has not enabled RA, RA won't be disabled upon client request
1268 * if the operator has explicitly enabled RA. The enable request can also
1269 * specify a RA interval (in seconds).
1271 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
1275 struct interface
*ifp
;
1276 struct zebra_if
*zif
;
1277 uint32_t ra_interval
;
1281 /* Get interface index and RA interval. */
1282 STREAM_GETL(s
, ifindex
);
1283 STREAM_GETL(s
, ra_interval
);
1285 if (IS_ZEBRA_DEBUG_EVENT
) {
1286 struct vrf
*vrf
= zvrf
->vrf
;
1288 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1289 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1290 enable
? "enable" : "disable",
1291 zebra_route_string(client
->proto
), ra_interval
);
1294 /* Locate interface and check VRF match. */
1295 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
1297 struct vrf
*vrf
= zvrf
->vrf
;
1299 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
1300 "%s:%u: IF %u RA %s client %s - interface unknown",
1301 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1302 enable
? "enable" : "disable",
1303 zebra_route_string(client
->proto
));
1306 if (vrf_is_backend_netns() && ifp
->vrf
->vrf_id
!= zvrf_id(zvrf
)) {
1308 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1309 ifp
->vrf
->name
, zvrf_id(zvrf
), ifindex
,
1310 enable
? "enable" : "disable",
1311 zebra_route_string(client
->proto
), ifp
->vrf
->vrf_id
);
1317 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1318 interfaces_configured_for_ra_from_bgp
++;
1320 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1321 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1323 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1324 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1325 VTY_RA_INTERVAL_CONFIGURED
))
1326 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1328 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1329 interfaces_configured_for_ra_from_bgp
--;
1331 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1332 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1333 VTY_RA_INTERVAL_CONFIGURED
))
1334 zif
->rtadv
.MaxRtrAdvInterval
=
1335 RTADV_MAX_RTR_ADV_INTERVAL
;
1336 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1337 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1344 * send router lifetime value of zero in RAs on this interface since we're
1345 * ceasing to advertise and want to let our neighbors know.
1346 * RFC 4861 secion 6.2.5
1348 void rtadv_stop_ra(struct interface
*ifp
)
1350 struct zebra_if
*zif
;
1351 struct zebra_vrf
*zvrf
;
1354 zvrf
= rtadv_interface_get_zvrf(ifp
);
1356 if (zif
->rtadv
.AdvSendAdvertisements
)
1357 rtadv_send_packet(zvrf
->rtadv
.sock
, ifp
, RA_SUPPRESS
);
1361 * Send router lifetime value of zero in RAs on all interfaces since we're
1362 * ceasing to advertise globally and want to let all of our neighbors know
1363 * RFC 4861 secion 6.2.5
1365 * Delete all ipv6 global prefixes added to the router advertisement prefix
1366 * lists prior to ceasing.
1368 void rtadv_stop_ra_all(void)
1371 struct interface
*ifp
;
1372 struct zebra_if
*zif
;
1373 struct rtadv_prefix
*rprefix
;
1375 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1376 FOR_ALL_INTERFACES (vrf
, ifp
) {
1379 frr_each_safe (rtadv_prefixes
, zif
->rtadv
.prefixes
,
1381 rtadv_prefix_reset(zif
, rprefix
);
1387 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1389 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1391 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1393 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1396 static void show_zvrf_rtadv_adv_if_helper(struct vty
*vty
,
1397 struct adv_if_list_head
*adv_if_head
)
1399 struct adv_if
*node
= NULL
;
1401 if (!adv_if_is_empty_internal(adv_if_head
)) {
1402 frr_each (adv_if_list
, adv_if_head
, node
) {
1403 vty_out(vty
, " %s\n", node
->name
);
1410 static void show_zvrf_rtadv_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
)
1412 vty_out(vty
, "VRF: %s\n", zvrf_name(zvrf
));
1413 vty_out(vty
, " Interfaces:\n");
1414 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_if
);
1416 vty_out(vty
, " Interfaces(msec):\n");
1417 show_zvrf_rtadv_adv_if_helper(vty
, &zvrf
->rtadv
.adv_msec_if
);
1420 DEFPY(show_ipv6_nd_ra_if
, show_ipv6_nd_ra_if_cmd
,
1421 "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
1423 "Neighbor discovery\n"
1424 "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR
)
1426 struct zebra_vrf
*zvrf
= NULL
;
1428 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1430 "%% VRF subcommand only applicable for netns-based vrfs.\n");
1437 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1438 struct zebra_vrf
*zvrf
;
1444 show_zvrf_rtadv_helper(vty
, zvrf
);
1451 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1453 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1456 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1461 show_zvrf_rtadv_helper(vty
, zvrf
);
1466 DEFUN (ipv6_nd_ra_fast_retrans
,
1467 ipv6_nd_ra_fast_retrans_cmd
,
1468 "ipv6 nd ra-fast-retrans",
1469 "Interface IPv6 config commands\n"
1470 "Neighbor discovery\n"
1471 "Fast retransmit of RA packets\n")
1473 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1474 struct zebra_if
*zif
= ifp
->info
;
1476 if (if_is_loopback(ifp
)) {
1478 "Cannot configure IPv6 Router Advertisements on this interface\n");
1479 return CMD_WARNING_CONFIG_FAILED
;
1482 zif
->rtadv
.UseFastRexmit
= true;
1487 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1488 no_ipv6_nd_ra_fast_retrans_cmd
,
1489 "no ipv6 nd ra-fast-retrans",
1491 "Interface IPv6 config commands\n"
1492 "Neighbor discovery\n"
1493 "Fast retransmit of RA packets\n")
1495 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1496 struct zebra_if
*zif
= ifp
->info
;
1498 if (if_is_loopback(ifp
)) {
1500 "Cannot configure IPv6 Router Advertisements on this interface\n");
1501 return CMD_WARNING_CONFIG_FAILED
;
1504 zif
->rtadv
.UseFastRexmit
= false;
1509 DEFPY (ipv6_nd_ra_hop_limit
,
1510 ipv6_nd_ra_hop_limit_cmd
,
1511 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1512 "Interface IPv6 config commands\n"
1513 "Neighbor discovery\n"
1514 "Advertisement Hop Limit\n"
1515 "Advertisement Hop Limit in hops (default:64)\n")
1517 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1518 struct zebra_if
*zif
= ifp
->info
;
1520 if (if_is_loopback(ifp
)) {
1522 "Cannot configure IPv6 Router Advertisements on this interface\n");
1523 return CMD_WARNING_CONFIG_FAILED
;
1526 zif
->rtadv
.AdvCurHopLimit
= hopcount
;
1531 DEFPY (no_ipv6_nd_ra_hop_limit
,
1532 no_ipv6_nd_ra_hop_limit_cmd
,
1533 "no ipv6 nd ra-hop-limit [(0-255)]",
1535 "Interface IPv6 config commands\n"
1536 "Neighbor discovery\n"
1537 "Advertisement Hop Limit\n"
1538 "Advertisement Hop Limit in hops\n")
1540 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1541 struct zebra_if
*zif
= ifp
->info
;
1543 if (if_is_loopback(ifp
)) {
1545 "Cannot configure IPv6 Router Advertisements on this interface\n");
1546 return CMD_WARNING_CONFIG_FAILED
;
1549 zif
->rtadv
.AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
1554 DEFPY (ipv6_nd_ra_retrans_interval
,
1555 ipv6_nd_ra_retrans_interval_cmd
,
1556 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1557 "Interface IPv6 config commands\n"
1558 "Neighbor discovery\n"
1559 "Advertisement Retransmit Interval\n"
1560 "Advertisement Retransmit Interval in msec\n")
1562 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1563 struct zebra_if
*zif
= ifp
->info
;
1565 if (if_is_loopback(ifp
)) {
1567 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1568 return CMD_WARNING_CONFIG_FAILED
;
1571 zif
->rtadv
.AdvRetransTimer
= interval
;
1576 DEFPY (no_ipv6_nd_ra_retrans_interval
,
1577 no_ipv6_nd_ra_retrans_interval_cmd
,
1578 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1580 "Interface IPv6 config commands\n"
1581 "Neighbor discovery\n"
1582 "Advertisement Retransmit Interval\n"
1583 "Advertisement Retransmit Interval in msec\n")
1585 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1586 struct zebra_if
*zif
= ifp
->info
;
1588 if (if_is_loopback(ifp
)) {
1590 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1591 return CMD_WARNING_CONFIG_FAILED
;
1594 zif
->rtadv
.AdvRetransTimer
= 0;
1599 DEFUN (ipv6_nd_suppress_ra
,
1600 ipv6_nd_suppress_ra_cmd
,
1601 "ipv6 nd suppress-ra",
1602 "Interface IPv6 config commands\n"
1603 "Neighbor discovery\n"
1604 "Suppress Router Advertisement\n")
1606 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1607 struct zebra_if
*zif
= ifp
->info
;
1609 if (if_is_loopback(ifp
)) {
1611 "Cannot configure IPv6 Router Advertisements on this interface\n");
1612 return CMD_WARNING_CONFIG_FAILED
;
1615 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1616 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1618 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1622 DEFUN (no_ipv6_nd_suppress_ra
,
1623 no_ipv6_nd_suppress_ra_cmd
,
1624 "no ipv6 nd suppress-ra",
1626 "Interface IPv6 config commands\n"
1627 "Neighbor discovery\n"
1628 "Suppress Router Advertisement\n")
1630 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1631 struct zebra_if
*zif
= ifp
->info
;
1633 if (if_is_loopback(ifp
)) {
1635 "Cannot configure IPv6 Router Advertisements on this interface\n");
1636 return CMD_WARNING_CONFIG_FAILED
;
1639 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1640 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1644 DEFUN (ipv6_nd_ra_interval_msec
,
1645 ipv6_nd_ra_interval_msec_cmd
,
1646 "ipv6 nd ra-interval msec (70-1800000)",
1647 "Interface IPv6 config commands\n"
1648 "Neighbor discovery\n"
1649 "Router Advertisement interval\n"
1650 "Router Advertisement interval in milliseconds\n"
1651 "Router Advertisement interval in milliseconds\n")
1654 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1656 struct zebra_if
*zif
= ifp
->info
;
1657 struct zebra_vrf
*zvrf
;
1658 struct adv_if
*adv_if
;
1660 zvrf
= rtadv_interface_get_zvrf(ifp
);
1662 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1663 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1664 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1666 "This ra-interval would conflict with configured ra-lifetime!\n");
1667 return CMD_WARNING_CONFIG_FAILED
;
1670 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1671 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1673 adv_if_free(adv_if
);
1676 if (interval
% 1000)
1677 (void)adv_msec_if_add(zvrf
, ifp
->name
);
1679 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1680 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1681 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1682 zif
->rtadv
.AdvIntervalTimer
= 0;
1687 DEFUN (ipv6_nd_ra_interval
,
1688 ipv6_nd_ra_interval_cmd
,
1689 "ipv6 nd ra-interval (1-1800)",
1690 "Interface IPv6 config commands\n"
1691 "Neighbor discovery\n"
1692 "Router Advertisement interval\n"
1693 "Router Advertisement interval in seconds\n")
1696 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1698 struct zebra_if
*zif
= ifp
->info
;
1699 struct zebra_vrf
*zvrf
;
1700 struct adv_if
*adv_if
;
1702 zvrf
= rtadv_interface_get_zvrf(ifp
);
1704 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1705 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1706 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1708 "This ra-interval would conflict with configured ra-lifetime!\n");
1709 return CMD_WARNING_CONFIG_FAILED
;
1712 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1713 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1715 adv_if_free(adv_if
);
1718 /* convert to milliseconds */
1719 interval
= interval
* 1000;
1721 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1722 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1723 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1724 zif
->rtadv
.AdvIntervalTimer
= 0;
1729 DEFUN (no_ipv6_nd_ra_interval
,
1730 no_ipv6_nd_ra_interval_cmd
,
1731 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1733 "Interface IPv6 config commands\n"
1734 "Neighbor discovery\n"
1735 "Router Advertisement interval\n"
1736 "Router Advertisement interval in seconds\n"
1737 "Specify millisecond router advertisement interval\n"
1738 "Router Advertisement interval in milliseconds\n")
1740 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1741 struct zebra_if
*zif
= ifp
->info
;
1742 struct zebra_vrf
*zvrf
= NULL
;
1743 struct adv_if
*adv_if
;
1745 zvrf
= rtadv_interface_get_zvrf(ifp
);
1747 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000) {
1748 adv_if
= adv_msec_if_del(zvrf
, ifp
->name
);
1750 adv_if_free(adv_if
);
1753 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1755 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1756 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1758 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1760 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1761 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1766 DEFUN (ipv6_nd_ra_lifetime
,
1767 ipv6_nd_ra_lifetime_cmd
,
1768 "ipv6 nd ra-lifetime (0-9000)",
1769 "Interface IPv6 config commands\n"
1770 "Neighbor discovery\n"
1772 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1775 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1776 struct zebra_if
*zif
= ifp
->info
;
1779 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1781 /* The value to be placed in the Router Lifetime field
1782 * of Router Advertisements sent from the interface,
1783 * in seconds. MUST be either zero or between
1784 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1785 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1787 "This ra-lifetime would conflict with configured ra-interval\n");
1788 return CMD_WARNING_CONFIG_FAILED
;
1791 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1796 DEFUN (no_ipv6_nd_ra_lifetime
,
1797 no_ipv6_nd_ra_lifetime_cmd
,
1798 "no ipv6 nd ra-lifetime [(0-9000)]",
1800 "Interface IPv6 config commands\n"
1801 "Neighbor discovery\n"
1803 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1805 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1806 struct zebra_if
*zif
= ifp
->info
;
1808 zif
->rtadv
.AdvDefaultLifetime
= -1;
1813 DEFUN (ipv6_nd_reachable_time
,
1814 ipv6_nd_reachable_time_cmd
,
1815 "ipv6 nd reachable-time (1-3600000)",
1816 "Interface IPv6 config commands\n"
1817 "Neighbor discovery\n"
1819 "Reachable time in milliseconds\n")
1822 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1823 struct zebra_if
*zif
= ifp
->info
;
1824 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1828 DEFUN (no_ipv6_nd_reachable_time
,
1829 no_ipv6_nd_reachable_time_cmd
,
1830 "no ipv6 nd reachable-time [(1-3600000)]",
1832 "Interface IPv6 config commands\n"
1833 "Neighbor discovery\n"
1835 "Reachable time in milliseconds\n")
1837 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1838 struct zebra_if
*zif
= ifp
->info
;
1840 zif
->rtadv
.AdvReachableTime
= 0;
1845 DEFUN (ipv6_nd_homeagent_preference
,
1846 ipv6_nd_homeagent_preference_cmd
,
1847 "ipv6 nd home-agent-preference (0-65535)",
1848 "Interface IPv6 config commands\n"
1849 "Neighbor discovery\n"
1850 "Home Agent preference\n"
1851 "preference value (default is 0, least preferred)\n")
1854 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1855 struct zebra_if
*zif
= ifp
->info
;
1856 zif
->rtadv
.HomeAgentPreference
=
1857 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1861 DEFUN (no_ipv6_nd_homeagent_preference
,
1862 no_ipv6_nd_homeagent_preference_cmd
,
1863 "no ipv6 nd home-agent-preference [(0-65535)]",
1865 "Interface IPv6 config commands\n"
1866 "Neighbor discovery\n"
1867 "Home Agent preference\n"
1868 "preference value (default is 0, least preferred)\n")
1870 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1871 struct zebra_if
*zif
= ifp
->info
;
1873 zif
->rtadv
.HomeAgentPreference
= 0;
1878 DEFUN (ipv6_nd_homeagent_lifetime
,
1879 ipv6_nd_homeagent_lifetime_cmd
,
1880 "ipv6 nd home-agent-lifetime (0-65520)",
1881 "Interface IPv6 config commands\n"
1882 "Neighbor discovery\n"
1883 "Home Agent lifetime\n"
1884 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1887 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1888 struct zebra_if
*zif
= ifp
->info
;
1889 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1893 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1894 no_ipv6_nd_homeagent_lifetime_cmd
,
1895 "no 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")
1902 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1903 struct zebra_if
*zif
= ifp
->info
;
1905 zif
->rtadv
.HomeAgentLifetime
= -1;
1910 DEFUN (ipv6_nd_managed_config_flag
,
1911 ipv6_nd_managed_config_flag_cmd
,
1912 "ipv6 nd managed-config-flag",
1913 "Interface IPv6 config commands\n"
1914 "Neighbor discovery\n"
1915 "Managed address configuration flag\n")
1917 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1918 struct zebra_if
*zif
= ifp
->info
;
1920 zif
->rtadv
.AdvManagedFlag
= 1;
1925 DEFUN (no_ipv6_nd_managed_config_flag
,
1926 no_ipv6_nd_managed_config_flag_cmd
,
1927 "no 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
= 0;
1941 DEFUN (ipv6_nd_homeagent_config_flag
,
1942 ipv6_nd_homeagent_config_flag_cmd
,
1943 "ipv6 nd home-agent-config-flag",
1944 "Interface IPv6 config commands\n"
1945 "Neighbor discovery\n"
1946 "Home Agent configuration flag\n")
1948 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1949 struct zebra_if
*zif
= ifp
->info
;
1951 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1956 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1957 no_ipv6_nd_homeagent_config_flag_cmd
,
1958 "no 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
= 0;
1972 DEFUN (ipv6_nd_adv_interval_config_option
,
1973 ipv6_nd_adv_interval_config_option_cmd
,
1974 "ipv6 nd adv-interval-option",
1975 "Interface IPv6 config commands\n"
1976 "Neighbor discovery\n"
1977 "Advertisement Interval Option\n")
1979 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1980 struct zebra_if
*zif
= ifp
->info
;
1982 zif
->rtadv
.AdvIntervalOption
= 1;
1987 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1988 no_ipv6_nd_adv_interval_config_option_cmd
,
1989 "no 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
= 0;
2003 DEFUN (ipv6_nd_other_config_flag
,
2004 ipv6_nd_other_config_flag_cmd
,
2005 "ipv6 nd other-config-flag",
2006 "Interface IPv6 config commands\n"
2007 "Neighbor discovery\n"
2008 "Other statefull configuration flag\n")
2010 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2011 struct zebra_if
*zif
= ifp
->info
;
2013 zif
->rtadv
.AdvOtherConfigFlag
= 1;
2018 DEFUN (no_ipv6_nd_other_config_flag
,
2019 no_ipv6_nd_other_config_flag_cmd
,
2020 "no 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
= 0;
2034 DEFUN (ipv6_nd_prefix
,
2036 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2037 "Interface IPv6 config commands\n"
2038 "Neighbor discovery\n"
2039 "Prefix information\n"
2041 "Valid lifetime in seconds\n"
2042 "Infinite valid lifetime\n"
2043 "Preferred lifetime in seconds\n"
2044 "Infinite preferred lifetime\n"
2045 "Set Router Address flag\n"
2046 "Do not use prefix for onlink determination\n"
2047 "Do not use prefix for autoconfiguration\n"
2048 "Do not use prefix for autoconfiguration\n"
2049 "Do not use prefix for onlink determination\n")
2052 char *prefix
= argv
[3]->arg
;
2053 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
2054 || strmatch(argv
[4]->text
, "infinite"));
2055 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
2057 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
2059 char *lifetime
= NULL
, *preflifetime
= NULL
;
2060 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
2062 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2064 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
2069 strmatch(argv
[idx_routeropts
]->text
, "router-address");
2071 offlink
= (argc
> idx_routeropts
+ 1
2072 || strmatch(argv
[idx_routeropts
]->text
,
2074 noautoconf
= (argc
> idx_routeropts
+ 1
2075 || strmatch(argv
[idx_routeropts
]->text
,
2081 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2082 struct zebra_if
*zebra_if
= ifp
->info
;
2084 struct rtadv_prefix rp
;
2086 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2088 vty_out(vty
, "Malformed IPv6 prefix\n");
2089 return CMD_WARNING_CONFIG_FAILED
;
2091 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2092 rp
.AdvOnLinkFlag
= !offlink
;
2093 rp
.AdvAutonomousFlag
= !noautoconf
;
2094 rp
.AdvRouterAddressFlag
= routeraddr
;
2095 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
2096 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
2097 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2100 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
2102 : strtoll(lifetime
, NULL
, 10);
2103 rp
.AdvPreferredLifetime
=
2104 strmatch(preflifetime
, "infinite")
2106 : strtoll(preflifetime
, NULL
, 10);
2107 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
2108 vty_out(vty
, "Invalid preferred lifetime\n");
2109 return CMD_WARNING_CONFIG_FAILED
;
2113 rtadv_prefix_set(zebra_if
, &rp
);
2118 DEFUN (no_ipv6_nd_prefix
,
2119 no_ipv6_nd_prefix_cmd
,
2120 "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]>]",
2122 "Interface IPv6 config commands\n"
2123 "Neighbor discovery\n"
2124 "Prefix information\n"
2126 "Valid lifetime in seconds\n"
2127 "Infinite valid lifetime\n"
2128 "Preferred lifetime in seconds\n"
2129 "Infinite preferred lifetime\n"
2130 "Set Router Address flag\n"
2131 "Do not use prefix for onlink determination\n"
2132 "Do not use prefix for autoconfiguration\n"
2133 "Do not use prefix for autoconfiguration\n"
2134 "Do not use prefix for onlink determination\n")
2136 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2137 struct zebra_if
*zebra_if
= ifp
->info
;
2139 struct rtadv_prefix rp
;
2140 char *prefix
= argv
[4]->arg
;
2142 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
2144 vty_out(vty
, "Malformed IPv6 prefix\n");
2145 return CMD_WARNING_CONFIG_FAILED
;
2147 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
2148 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
2150 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
2152 vty_out(vty
, "Non-existant IPv6 prefix\n");
2153 return CMD_WARNING_CONFIG_FAILED
;
2159 DEFUN (ipv6_nd_router_preference
,
2160 ipv6_nd_router_preference_cmd
,
2161 "ipv6 nd router-preference <high|medium|low>",
2162 "Interface IPv6 config commands\n"
2163 "Neighbor discovery\n"
2164 "Default router preference\n"
2165 "High default router preference\n"
2166 "Medium default router preference (default)\n"
2167 "Low default router preference\n")
2169 int idx_high_medium_low
= 3;
2170 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2171 struct zebra_if
*zif
= ifp
->info
;
2174 while (0 != rtadv_pref_strs
[i
]) {
2175 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
2178 zif
->rtadv
.DefaultPreference
= i
;
2184 return CMD_ERR_NO_MATCH
;
2187 DEFUN (no_ipv6_nd_router_preference
,
2188 no_ipv6_nd_router_preference_cmd
,
2189 "no ipv6 nd router-preference [<high|medium|low>]",
2191 "Interface IPv6 config commands\n"
2192 "Neighbor discovery\n"
2193 "Default router preference\n"
2194 "High default router preference\n"
2195 "Medium default router preference (default)\n"
2196 "Low default router preference\n")
2198 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2199 struct zebra_if
*zif
= ifp
->info
;
2201 zif
->rtadv
.DefaultPreference
=
2202 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
2209 "ipv6 nd mtu (1-65535)",
2210 "Interface IPv6 config commands\n"
2211 "Neighbor discovery\n"
2216 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2217 struct zebra_if
*zif
= ifp
->info
;
2218 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
2222 DEFUN (no_ipv6_nd_mtu
,
2224 "no ipv6 nd mtu [(1-65535)]",
2226 "Interface IPv6 config commands\n"
2227 "Neighbor discovery\n"
2231 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2232 struct zebra_if
*zif
= ifp
->info
;
2233 zif
->rtadv
.AdvLinkMTU
= 0;
2237 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
2239 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
2242 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
2244 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
2247 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
2248 struct rtadv_rdnss
*rdnss
)
2250 struct listnode
*node
;
2251 struct rtadv_rdnss
*p
;
2253 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2254 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
2259 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
2260 struct rtadv_rdnss
*rdnss
)
2262 struct rtadv_rdnss
*p
;
2264 p
= rtadv_rdnss_lookup(list
, rdnss
);
2268 p
= rtadv_rdnss_new();
2269 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
2270 listnode_add(list
, p
);
2275 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2277 struct rtadv_rdnss
*p
;
2279 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2280 p
->lifetime
= rdnss
->lifetime
;
2281 p
->lifetime_set
= rdnss
->lifetime_set
;
2284 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2286 struct rtadv_rdnss
*p
;
2288 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2290 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
2291 rtadv_rdnss_free(p
);
2298 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
2300 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
2303 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
2305 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
2308 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
2309 struct rtadv_dnssl
*dnssl
)
2311 struct listnode
*node
;
2312 struct rtadv_dnssl
*p
;
2314 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2315 if (!strcasecmp(p
->name
, dnssl
->name
))
2320 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
2321 struct rtadv_dnssl
*dnssl
)
2323 struct rtadv_dnssl
*p
;
2325 p
= rtadv_dnssl_lookup(list
, dnssl
);
2329 p
= rtadv_dnssl_new();
2330 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2331 listnode_add(list
, p
);
2336 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2338 struct rtadv_dnssl
*p
;
2340 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2341 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2344 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2346 struct rtadv_dnssl
*p
;
2348 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2350 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
2351 rtadv_dnssl_free(p
);
2359 * Convert dotted domain name (with or without trailing root zone dot) to
2360 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2361 * to strlen(in) + 2 octets to out.
2363 * Returns the number of octets written to out or -1 if in does not constitute
2364 * a valid domain name.
2366 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
2368 const char *label_start
, *label_end
;
2374 while (*label_start
) {
2377 label_end
= strchr(label_start
, '.');
2378 if (label_end
== NULL
)
2379 label_end
= label_start
+ strlen(label_start
);
2381 label_len
= label_end
- label_start
;
2382 if (label_len
>= 64)
2383 return -1; /* labels must be 63 octets or less */
2385 out
[outp
++] = (uint8_t)label_len
;
2386 memcpy(out
+ outp
, label_start
, label_len
);
2388 label_start
+= label_len
;
2389 if (*label_start
== '.')
2397 DEFUN(ipv6_nd_rdnss
,
2399 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2400 "Interface IPv6 config commands\n"
2401 "Neighbor discovery\n"
2402 "Recursive DNS server information\n"
2404 "Valid lifetime in seconds\n"
2405 "Infinite valid lifetime\n")
2407 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2408 struct zebra_if
*zif
= ifp
->info
;
2409 struct rtadv_rdnss rdnss
= {};
2411 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
2412 vty_out(vty
, "Malformed IPv6 address\n");
2413 return CMD_WARNING_CONFIG_FAILED
;
2416 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2418 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
2420 : strtoll(lifetime
, NULL
, 10);
2421 rdnss
.lifetime_set
= 1;
2424 rtadv_rdnss_set(zif
, &rdnss
);
2429 DEFUN(no_ipv6_nd_rdnss
,
2430 no_ipv6_nd_rdnss_cmd
,
2431 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2433 "Interface IPv6 config commands\n"
2434 "Neighbor discovery\n"
2435 "Recursive DNS server information\n"
2437 "Valid lifetime in seconds\n"
2438 "Infinite valid lifetime\n")
2440 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2441 struct zebra_if
*zif
= ifp
->info
;
2442 struct rtadv_rdnss rdnss
= {};
2444 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
2445 vty_out(vty
, "Malformed IPv6 address\n");
2446 return CMD_WARNING_CONFIG_FAILED
;
2448 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
2449 vty_out(vty
, "Non-existant RDNSS address\n");
2450 return CMD_WARNING_CONFIG_FAILED
;
2456 DEFUN(ipv6_nd_dnssl
,
2458 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2459 "Interface IPv6 config commands\n"
2460 "Neighbor discovery\n"
2461 "DNS search list information\n"
2462 "Domain name suffix\n"
2463 "Valid lifetime in seconds\n"
2464 "Infinite valid lifetime\n")
2466 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2467 struct zebra_if
*zif
= ifp
->info
;
2468 struct rtadv_dnssl dnssl
= {};
2472 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
2473 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2474 vty_out(vty
, "Malformed DNS search domain\n");
2475 return CMD_WARNING_CONFIG_FAILED
;
2477 if (dnssl
.name
[len
- 1] == '.') {
2479 * Allow, but don't require, a trailing dot signifying the root
2480 * zone. Canonicalize by cutting it off if present.
2482 dnssl
.name
[len
- 1] = '\0';
2486 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2488 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
2490 : strtoll(lifetime
, NULL
, 10);
2491 dnssl
.lifetime_set
= 1;
2494 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2496 vty_out(vty
, "Malformed DNS search domain\n");
2497 return CMD_WARNING_CONFIG_FAILED
;
2499 dnssl
.encoded_len
= ret
;
2500 rtadv_dnssl_set(zif
, &dnssl
);
2505 DEFUN(no_ipv6_nd_dnssl
,
2506 no_ipv6_nd_dnssl_cmd
,
2507 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2509 "Interface IPv6 config commands\n"
2510 "Neighbor discovery\n"
2511 "DNS search list information\n"
2512 "Domain name suffix\n"
2513 "Valid lifetime in seconds\n"
2514 "Infinite valid lifetime\n")
2516 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2517 struct zebra_if
*zif
= ifp
->info
;
2518 struct rtadv_dnssl dnssl
= {};
2521 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2522 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2523 vty_out(vty
, "Malformed DNS search domain\n");
2524 return CMD_WARNING_CONFIG_FAILED
;
2526 if (dnssl
.name
[len
- 1] == '.') {
2527 dnssl
.name
[len
- 1] = '\0';
2530 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2531 vty_out(vty
, "Non-existant DNS search domain\n");
2532 return CMD_WARNING_CONFIG_FAILED
;
2539 /* Dump interface ND information to vty. */
2540 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2542 struct zebra_if
*zif
;
2543 struct rtadvconf
*rtadv
;
2546 zif
= (struct zebra_if
*)ifp
->info
;
2547 rtadv
= &zif
->rtadv
;
2549 if (rtadv
->AdvSendAdvertisements
) {
2551 " ND advertised reachable time is %d milliseconds\n",
2552 rtadv
->AdvReachableTime
);
2554 " ND advertised retransmit interval is %u milliseconds\n",
2555 rtadv
->AdvRetransTimer
);
2556 vty_out(vty
, " ND advertised hop-count limit is %d hops\n",
2557 rtadv
->AdvCurHopLimit
);
2558 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2559 zif
->ra_sent
, zif
->ra_rcvd
);
2560 interval
= rtadv
->MaxRtrAdvInterval
;
2561 if (interval
% 1000)
2563 " ND router advertisements are sent every %d milliseconds\n",
2567 " ND router advertisements are sent every %d seconds\n",
2569 if (!rtadv
->UseFastRexmit
)
2571 " ND router advertisements do not use fast retransmit\n");
2573 if (rtadv
->AdvDefaultLifetime
!= -1)
2575 " ND router advertisements live for %d seconds\n",
2576 rtadv
->AdvDefaultLifetime
);
2579 " ND router advertisements lifetime tracks ra-interval\n");
2581 " ND router advertisement default router preference is %s\n",
2582 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2583 if (rtadv
->AdvManagedFlag
)
2585 " Hosts use DHCP to obtain routable addresses.\n");
2588 " Hosts use stateless autoconfig for addresses.\n");
2589 if (rtadv
->AdvHomeAgentFlag
) {
2591 " ND router advertisements with Home Agent flag bit set.\n");
2592 if (rtadv
->HomeAgentLifetime
!= -1)
2594 " Home Agent lifetime is %u seconds\n",
2595 rtadv
->HomeAgentLifetime
);
2598 " Home Agent lifetime tracks ra-lifetime\n");
2599 vty_out(vty
, " Home Agent preference is %u\n",
2600 rtadv
->HomeAgentPreference
);
2602 if (rtadv
->AdvIntervalOption
)
2604 " ND router advertisements with Adv. Interval option.\n");
2610 /* Write configuration about router advertisement. */
2611 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2613 struct zebra_if
*zif
;
2614 struct listnode
*node
;
2615 struct rtadv_prefix
*rprefix
;
2616 struct rtadv_rdnss
*rdnss
;
2617 struct rtadv_dnssl
*dnssl
;
2622 if (!if_is_loopback(ifp
)) {
2623 if (zif
->rtadv
.AdvSendAdvertisements
2624 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2625 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2628 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2629 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2630 if (interval
% 1000)
2631 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2633 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2634 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2638 if (zif
->rtadv
.AdvIntervalOption
)
2639 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2641 if (!zif
->rtadv
.UseFastRexmit
)
2642 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2644 if (zif
->rtadv
.AdvRetransTimer
!= 0)
2645 vty_out(vty
, " ipv6 nd ra-retrans-interval %u\n",
2646 zif
->rtadv
.AdvRetransTimer
);
2648 if (zif
->rtadv
.AdvCurHopLimit
!= RTADV_DEFAULT_HOPLIMIT
)
2649 vty_out(vty
, " ipv6 nd ra-hop-limit %d\n",
2650 zif
->rtadv
.AdvCurHopLimit
);
2652 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2653 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2654 zif
->rtadv
.AdvDefaultLifetime
);
2656 if (zif
->rtadv
.HomeAgentPreference
)
2657 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2658 zif
->rtadv
.HomeAgentPreference
);
2660 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2661 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2662 zif
->rtadv
.HomeAgentLifetime
);
2664 if (zif
->rtadv
.AdvHomeAgentFlag
)
2665 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2667 if (zif
->rtadv
.AdvReachableTime
)
2668 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2669 zif
->rtadv
.AdvReachableTime
);
2671 if (zif
->rtadv
.AdvManagedFlag
)
2672 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2674 if (zif
->rtadv
.AdvOtherConfigFlag
)
2675 vty_out(vty
, " ipv6 nd other-config-flag\n");
2677 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2678 vty_out(vty
, " ipv6 nd router-preference %s\n",
2679 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2681 if (zif
->rtadv
.AdvLinkMTU
)
2682 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2684 frr_each (rtadv_prefixes
, zif
->rtadv
.prefixes
, rprefix
) {
2685 if ((rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
2686 || (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
)) {
2687 vty_out(vty
, " ipv6 nd prefix %pFX", &rprefix
->prefix
);
2688 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2689 || (rprefix
->AdvPreferredLifetime
2690 != RTADV_PREFERRED_LIFETIME
)) {
2691 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2692 vty_out(vty
, " infinite");
2695 rprefix
->AdvValidLifetime
);
2696 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2697 vty_out(vty
, " infinite");
2700 rprefix
->AdvPreferredLifetime
);
2702 if (!rprefix
->AdvOnLinkFlag
)
2703 vty_out(vty
, " off-link");
2704 if (!rprefix
->AdvAutonomousFlag
)
2705 vty_out(vty
, " no-autoconfig");
2706 if (rprefix
->AdvRouterAddressFlag
)
2707 vty_out(vty
, " router-address");
2712 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2713 char buf
[INET6_ADDRSTRLEN
];
2715 vty_out(vty
, " ipv6 nd rdnss %s",
2716 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2717 if (rdnss
->lifetime_set
) {
2718 if (rdnss
->lifetime
== UINT32_MAX
)
2719 vty_out(vty
, " infinite");
2721 vty_out(vty
, " %u", rdnss
->lifetime
);
2725 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2726 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2727 if (dnssl
->lifetime_set
) {
2728 if (dnssl
->lifetime
== UINT32_MAX
)
2729 vty_out(vty
, " infinite");
2731 vty_out(vty
, " %u", dnssl
->lifetime
);
2739 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2741 struct rtadv
*rtadv
;
2743 if (IS_ZEBRA_DEBUG_EVENT
) {
2744 struct vrf
*vrf
= zvrf
->vrf
;
2746 zlog_debug("%s(%s) with event: %d and val: %d", __func__
,
2747 VRF_LOGNAME(vrf
), event
, val
);
2750 rtadv
= &zvrf
->rtadv
;
2754 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2756 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2760 THREAD_OFF(rtadv
->ra_timer
);
2761 THREAD_OFF(rtadv
->ra_read
);
2764 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2767 case RTADV_TIMER_MSEC
:
2768 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2772 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, rtadv
->sock
,
2781 void rtadv_if_up(struct zebra_if
*zif
)
2783 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
2784 if (zif
->rtadv
.AdvSendAdvertisements
&&
2785 (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) &&
2786 zif
->rtadv
.UseFastRexmit
) {
2787 zif
->rtadv
.inFastRexmit
= 1;
2788 zif
->rtadv
.NumFastReXmitsRemain
= RTADV_NUM_FAST_REXMITS
;
2792 void rtadv_if_init(struct zebra_if
*zif
)
2794 /* Set default router advertise values. */
2795 struct rtadvconf
*rtadv
;
2797 rtadv
= &zif
->rtadv
;
2799 rtadv
->AdvSendAdvertisements
= 0;
2800 rtadv
->MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
2801 rtadv
->MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
2802 rtadv
->AdvIntervalTimer
= 0;
2803 rtadv
->AdvManagedFlag
= 0;
2804 rtadv
->AdvOtherConfigFlag
= 0;
2805 rtadv
->AdvHomeAgentFlag
= 0;
2806 rtadv
->AdvLinkMTU
= 0;
2807 rtadv
->AdvReachableTime
= 0;
2808 rtadv
->AdvRetransTimer
= 0;
2809 rtadv
->AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
2810 memset(&rtadv
->lastadvcurhoplimit
, 0,
2811 sizeof(rtadv
->lastadvcurhoplimit
));
2812 memset(&rtadv
->lastadvmanagedflag
, 0,
2813 sizeof(rtadv
->lastadvmanagedflag
));
2814 memset(&rtadv
->lastadvotherconfigflag
, 0,
2815 sizeof(rtadv
->lastadvotherconfigflag
));
2816 memset(&rtadv
->lastadvreachabletime
, 0,
2817 sizeof(rtadv
->lastadvreachabletime
));
2818 memset(&rtadv
->lastadvretranstimer
, 0,
2819 sizeof(rtadv
->lastadvretranstimer
));
2820 rtadv
->AdvDefaultLifetime
= -1; /* derive from MaxRtrAdvInterval */
2821 rtadv
->HomeAgentPreference
= 0;
2822 rtadv
->HomeAgentLifetime
= -1; /* derive from AdvDefaultLifetime */
2823 rtadv
->AdvIntervalOption
= 0;
2824 rtadv
->UseFastRexmit
= true;
2825 rtadv
->DefaultPreference
= RTADV_PREF_MEDIUM
;
2827 rtadv_prefixes_init(rtadv
->prefixes
);
2829 rtadv
->AdvRDNSSList
= list_new();
2830 rtadv
->AdvDNSSLList
= list_new();
2833 void rtadv_if_fini(struct zebra_if
*zif
)
2835 struct rtadvconf
*rtadv
;
2836 struct rtadv_prefix
*rp
;
2838 rtadv
= &zif
->rtadv
;
2840 while ((rp
= rtadv_prefixes_pop(rtadv
->prefixes
)))
2841 rtadv_prefix_free(rp
);
2843 list_delete(&rtadv
->AdvRDNSSList
);
2844 list_delete(&rtadv
->AdvDNSSLList
);
2847 void rtadv_vrf_init(struct zebra_vrf
*zvrf
)
2849 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2852 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2855 void rtadv_vrf_terminate(struct zebra_vrf
*zvrf
)
2857 if (!vrf_is_backend_netns() && (zvrf_id(zvrf
) != VRF_DEFAULT
))
2860 rtadv_event(zvrf
, RTADV_STOP
, 0);
2861 if (zvrf
->rtadv
.sock
>= 0) {
2862 close(zvrf
->rtadv
.sock
);
2863 zvrf
->rtadv
.sock
= -1;
2867 adv_msec_if_clean(zvrf
);
2870 void rtadv_cmd_init(void)
2872 interfaces_configured_for_ra_from_bgp
= 0;
2874 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2875 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2877 install_element(VIEW_NODE
, &show_ipv6_nd_ra_if_cmd
);
2879 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2880 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2881 install_element(INTERFACE_NODE
, &ipv6_nd_ra_retrans_interval_cmd
);
2882 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_retrans_interval_cmd
);
2883 install_element(INTERFACE_NODE
, &ipv6_nd_ra_hop_limit_cmd
);
2884 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_hop_limit_cmd
);
2885 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2886 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2887 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2888 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2889 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2890 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2891 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2892 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2893 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2894 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2895 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2896 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2897 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2898 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2899 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2900 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2901 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2902 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2903 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2904 install_element(INTERFACE_NODE
,
2905 &ipv6_nd_adv_interval_config_option_cmd
);
2906 install_element(INTERFACE_NODE
,
2907 &no_ipv6_nd_adv_interval_config_option_cmd
);
2908 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2909 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2910 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2911 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2912 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2913 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2914 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2915 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2916 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2917 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2920 static int if_join_all_router(int sock
, struct interface
*ifp
)
2924 struct ipv6_mreq mreq
;
2926 memset(&mreq
, 0, sizeof(mreq
));
2927 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2928 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2930 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2933 flog_err_sys(EC_LIB_SOCKET
,
2934 "%s(%u): Failed to join group, socket %u error %s",
2935 ifp
->name
, ifp
->ifindex
, sock
,
2936 safe_strerror(errno
));
2938 if (IS_ZEBRA_DEBUG_EVENT
)
2940 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2941 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
2946 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2950 struct ipv6_mreq mreq
;
2952 memset(&mreq
, 0, sizeof(mreq
));
2953 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2954 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2956 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2961 "%s(%s:%u): Failed to leave group, socket %u error %s",
2962 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
,
2963 safe_strerror(errno
));
2965 if (IS_ZEBRA_DEBUG_EVENT
)
2967 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
2968 ifp
->name
, ifp
->vrf
->name
, ifp
->ifindex
, sock
);
2973 bool rtadv_compiled_in(void)
2978 #else /* !HAVE_RTADV */
2980 * If the end user does not have RADV enabled we should
2981 * handle this better
2983 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
2985 if (IS_ZEBRA_DEBUG_PACKET
)
2987 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
2988 zserv_command_string(hdr
->command
));
2993 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
2995 if (IS_ZEBRA_DEBUG_PACKET
)
2997 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
2998 zserv_command_string(hdr
->command
));
3003 bool rtadv_compiled_in(void)
3008 #endif /* HAVE_RTADV */
3010 uint32_t rtadv_get_interfaces_configured_from_bgp(void)
3012 return interfaces_configured_for_ra_from_bgp
;