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 #if defined(HAVE_RTADV)
52 #ifndef VTYSH_EXTRACT_PL
53 #include "zebra/rtadv_clippy.c"
56 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_PREFIX
, "Router Advertisement Prefix");
59 #include <netinet/icmp6.h>
62 /* If RFC2133 definition is used. */
63 #ifndef IPV6_JOIN_GROUP
64 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
66 #ifndef IPV6_LEAVE_GROUP
67 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
70 #define ALLNODE "ff02::1"
71 #define ALLROUTER "ff02::2"
73 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS");
74 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL");
76 /* Order is intentional. Matches RFC4191. This array is also used for
77 command matching, so only modify with care. */
78 static const char *const rtadv_pref_strs
[] = {
79 "medium", "high", "INVALID", "low", 0
90 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
92 static int if_join_all_router(int, struct interface
*);
93 static int if_leave_all_router(int, struct interface
*);
95 static int rtadv_get_socket(struct zebra_vrf
*zvrf
)
97 if (zvrf
->rtadv
.sock
> 0)
98 return zvrf
->rtadv
.sock
;
99 return zrouter
.rtadv_sock
;
102 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
105 struct interface
*iface
;
106 struct zebra_if
*zif
;
108 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
109 if (iface
&& iface
->info
) {
117 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
118 int buflen
, struct sockaddr_in6
*from
,
119 ifindex_t
*ifindex
, int *hoplimit
)
124 struct cmsghdr
*cmsgptr
;
129 /* Fill in message and iovec. */
130 memset(&msg
, 0, sizeof(msg
));
131 msg
.msg_name
= (void *)from
;
132 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
135 msg
.msg_control
= (void *)adata
;
136 msg
.msg_controllen
= sizeof(adata
);
138 iov
.iov_len
= buflen
;
140 /* If recvmsg fail return minus value. */
141 ret
= recvmsg(sock
, &msg
, 0);
145 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
146 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
147 /* I want interface index which this packet comes from. */
148 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
149 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
150 struct in6_pktinfo
*ptr
;
152 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
153 *ifindex
= ptr
->ipi6_ifindex
;
154 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
157 /* Incoming packet's hop limit. */
158 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
159 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
160 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
165 rtadv_increment_received(zvrf
, ifindex
);
169 #define RTADV_MSG_SIZE 4096
171 /* Send router advertisement packet. */
172 static void rtadv_send_packet(int sock
, struct interface
*ifp
,
173 enum ipv6_nd_suppress_ra_status stop
)
177 struct cmsghdr
*cmsgptr
;
178 struct in6_pktinfo
*pkt
;
179 struct sockaddr_in6 addr
;
180 static void *adata
= NULL
;
181 unsigned char buf
[RTADV_MSG_SIZE
];
182 struct nd_router_advert
*rtadv
;
185 struct zebra_if
*zif
;
186 struct rtadv_prefix
*rprefix
;
187 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0, 0, 0, 1};
189 struct listnode
*node
;
190 uint16_t pkt_RouterLifetime
;
193 * Allocate control message bufffer. This is dynamic because
194 * CMSG_SPACE is not guaranteed not to call a function. Note that
195 * the size will be different on different architectures due to
196 * differing alignment rules.
199 /* XXX Free on shutdown. */
200 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
204 "rtadv_send_packet: can't malloc control data");
209 /* Logging of packet. */
210 if (IS_ZEBRA_DEBUG_PACKET
) {
211 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
213 zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp
->name
,
214 VRF_LOGNAME(vrf
), ifp
->ifindex
, sock
);
217 /* Fill in sockaddr_in6. */
218 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
219 addr
.sin6_family
= AF_INET6
;
221 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
222 #endif /* SIN6_LEN */
223 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
224 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
226 /* Fetch interface information. */
229 /* Make router advertisement message. */
230 rtadv
= (struct nd_router_advert
*)buf
;
232 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
233 rtadv
->nd_ra_code
= 0;
234 rtadv
->nd_ra_cksum
= 0;
236 rtadv
->nd_ra_curhoplimit
= zif
->rtadv
.AdvCurHopLimit
;
238 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
239 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
241 : zif
->rtadv
.DefaultPreference
;
242 rtadv
->nd_ra_flags_reserved
<<= 3;
244 if (zif
->rtadv
.AdvManagedFlag
)
245 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
246 if (zif
->rtadv
.AdvOtherConfigFlag
)
247 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
248 if (zif
->rtadv
.AdvHomeAgentFlag
)
249 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
250 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
251 * AdvDefaultLifetime is by default based on the value of
252 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
253 * field of Router Advertisements. Given that this field is expressed
254 * in seconds, a small MaxRtrAdvInterval value can result in a zero
255 * value for this field. To prevent this, routers SHOULD keep
256 * AdvDefaultLifetime in at least one second, even if the use of
257 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
259 zif
->rtadv
.AdvDefaultLifetime
!= -1
260 ? zif
->rtadv
.AdvDefaultLifetime
261 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
263 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
264 rtadv
->nd_ra_router_lifetime
=
265 (stop
== RA_SUPPRESS
) ? htons(0) : htons(pkt_RouterLifetime
);
266 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
267 rtadv
->nd_ra_retransmit
= htonl(zif
->rtadv
.AdvRetransTimer
);
269 len
= sizeof(struct nd_router_advert
);
271 /* If both the Home Agent Preference and Home Agent Lifetime are set to
272 * their default values specified above, this option SHOULD NOT be
273 * included in the Router Advertisement messages sent by this home
274 * agent. -- RFC6275, 7.4 */
275 if (zif
->rtadv
.AdvHomeAgentFlag
276 && (zif
->rtadv
.HomeAgentPreference
277 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
278 struct nd_opt_homeagent_info
*ndopt_hai
=
279 (struct nd_opt_homeagent_info
*)(buf
+ len
);
280 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
281 ndopt_hai
->nd_opt_hai_len
= 1;
282 ndopt_hai
->nd_opt_hai_reserved
= 0;
283 ndopt_hai
->nd_opt_hai_preference
=
284 htons(zif
->rtadv
.HomeAgentPreference
);
285 /* 16-bit unsigned integer. The lifetime associated with the
287 * agent in units of seconds. The default value is the same as
289 * Router Lifetime, as specified in the main body of the Router
290 * Advertisement. The maximum value corresponds to 18.2 hours.
292 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
293 ndopt_hai
->nd_opt_hai_lifetime
=
294 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
295 ? zif
->rtadv
.HomeAgentLifetime
296 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
301 len
+= sizeof(struct nd_opt_homeagent_info
);
304 if (zif
->rtadv
.AdvIntervalOption
) {
305 struct nd_opt_adv_interval
*ndopt_adv
=
306 (struct nd_opt_adv_interval
*)(buf
+ len
);
307 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
308 ndopt_adv
->nd_opt_ai_len
= 1;
309 ndopt_adv
->nd_opt_ai_reserved
= 0;
310 ndopt_adv
->nd_opt_ai_interval
=
311 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
312 len
+= sizeof(struct nd_opt_adv_interval
);
315 /* Fill in prefix. */
316 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
317 struct nd_opt_prefix_info
*pinfo
;
319 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
321 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
322 pinfo
->nd_opt_pi_len
= 4;
323 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
325 pinfo
->nd_opt_pi_flags_reserved
= 0;
326 if (rprefix
->AdvOnLinkFlag
)
327 pinfo
->nd_opt_pi_flags_reserved
|=
328 ND_OPT_PI_FLAG_ONLINK
;
329 if (rprefix
->AdvAutonomousFlag
)
330 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
331 if (rprefix
->AdvRouterAddressFlag
)
332 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
334 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
335 pinfo
->nd_opt_pi_preferred_time
=
336 htonl(rprefix
->AdvPreferredLifetime
);
337 pinfo
->nd_opt_pi_reserved2
= 0;
339 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
340 &rprefix
->prefix
.prefix
);
342 len
+= sizeof(struct nd_opt_prefix_info
);
345 /* Hardware address. */
346 if (ifp
->hw_addr_len
!= 0) {
347 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
349 /* Option length should be rounded up to next octet if
350 the link address does not end on an octet boundary. */
351 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
353 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
354 len
+= ifp
->hw_addr_len
;
356 /* Pad option to end on an octet boundary. */
357 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
358 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
362 if (zif
->rtadv
.AdvLinkMTU
) {
363 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
364 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
365 opt
->nd_opt_mtu_len
= 1;
366 opt
->nd_opt_mtu_reserved
= 0;
367 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
368 len
+= sizeof(struct nd_opt_mtu
);
372 * There is no limit on the number of configurable recursive DNS
373 * servers or search list entries. We don't want the RA message
374 * to exceed the link's MTU (risking fragmentation) or even
375 * blow the stack buffer allocated for it.
377 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
379 /* Recursive DNS servers */
380 struct rtadv_rdnss
*rdnss
;
382 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
384 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
386 if (len
+ opt_len
> max_len
) {
387 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
390 "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
391 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
);
394 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
396 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
397 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
398 opt
->nd_opt_rdnss_reserved
= 0;
399 opt
->nd_opt_rdnss_lifetime
= htonl(
402 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
404 len
+= sizeof(struct nd_opt_rdnss
);
406 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
407 len
+= sizeof(struct in6_addr
);
410 /* DNS search list */
411 struct rtadv_dnssl
*dnssl
;
413 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
414 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
415 + ((dnssl
->encoded_len
+ 7) & ~7);
417 if (len
+ opt_len
> max_len
) {
419 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
420 ifp
->name
, ifp
->ifindex
);
423 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
425 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
426 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
427 opt
->nd_opt_dnssl_reserved
= 0;
428 opt
->nd_opt_dnssl_lifetime
= htonl(
431 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
433 len
+= sizeof(struct nd_opt_dnssl
);
435 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
436 len
+= dnssl
->encoded_len
;
438 /* Zero-pad to 8-octet boundary */
445 msg
.msg_name
= (void *)&addr
;
446 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
449 msg
.msg_control
= (void *)adata
;
450 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
455 cmsgptr
= CMSG_FIRSTHDR(&msg
);
456 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
457 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
458 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
460 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
461 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
462 pkt
->ipi6_ifindex
= ifp
->ifindex
;
464 ret
= sendmsg(sock
, &msg
, 0);
466 flog_err_sys(EC_LIB_SOCKET
,
467 "%s(%u): Tx RA failed, socket %u error %d (%s)",
468 ifp
->name
, ifp
->ifindex
, sock
, errno
,
469 safe_strerror(errno
));
474 static int rtadv_timer(struct thread
*thread
)
476 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
478 struct interface
*ifp
;
479 struct zebra_if
*zif
;
482 zvrf
->rtadv
.ra_timer
= NULL
;
483 if (zvrf
->rtadv
.adv_msec_if_count
== 0) {
484 period
= 1000; /* 1 s */
485 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
487 period
= 10; /* 10 ms */
488 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
491 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
492 FOR_ALL_INTERFACES (vrf
, ifp
) {
493 if (if_is_loopback(ifp
)
494 || CHECK_FLAG(ifp
->status
,
495 ZEBRA_INTERFACE_VRF_LOOPBACK
)
496 || !if_is_operative(ifp
))
501 if (zif
->rtadv
.AdvSendAdvertisements
) {
502 if (zif
->rtadv
.inFastRexmit
503 && zif
->rtadv
.UseFastRexmit
) {
504 /* We assume we fast rexmit every sec so
507 if (--zif
->rtadv
.NumFastReXmitsRemain
509 zif
->rtadv
.inFastRexmit
= 0;
511 if (IS_ZEBRA_DEBUG_SEND
) {
517 "Fast RA Rexmit on interface %s(%s:%u)",
523 rtadv_send_packet(rtadv_get_socket(zvrf
),
526 zif
->rtadv
.AdvIntervalTimer
-= period
;
527 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
529 MaxRtrAdvInterval each
530 time isn't what section
531 6.2.4 of RFC4861 tells to do.
533 zif
->rtadv
.AdvIntervalTimer
=
537 rtadv_get_socket(zvrf
),
547 static void rtadv_process_solicit(struct interface
*ifp
)
549 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
550 struct zebra_if
*zif
;
556 * If FastRetransmit is enabled, send the RA immediately.
557 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
558 * (3 seconds) since the last RA was sent, send it now and reset
559 * the timer to start at the max (configured) again.
560 * If not enabled and it is less than 3 seconds since the last
561 * RA packet was sent, set the timer for 3 seconds so the next
562 * one will be sent with a minimum of 3 seconds between RAs.
565 if ((zif
->rtadv
.UseFastRexmit
)
566 || (zif
->rtadv
.AdvIntervalTimer
<=
567 (zif
->rtadv
.MaxRtrAdvInterval
- MIN_DELAY_BETWEEN_RAS
))) {
568 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
, RA_ENABLE
);
569 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
571 zif
->rtadv
.AdvIntervalTimer
= MIN_DELAY_BETWEEN_RAS
;
575 * This function processes optional attributes off of
576 * end of a RA packet received. At this point in
577 * time we only care about this in one situation
578 * which is when a interface does not have a LL
579 * v6 address. We still need to be able to install
580 * the mac address for v4 to v6 resolution
582 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
583 struct interface
*ifp
,
584 struct sockaddr_in6
*addr
)
589 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
591 switch(opt_hdr
->nd_opt_type
) {
592 case ND_OPT_SOURCE_LINKADDR
:
593 mac
= (char *)(optional
+2);
594 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
595 &addr
->sin6_addr
, 1);
601 len
-= 8 * opt_hdr
->nd_opt_len
;
602 optional
+= 8 * opt_hdr
->nd_opt_len
;
606 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
607 struct interface
*ifp
,
608 struct sockaddr_in6
*addr
)
610 struct nd_router_advert
*radvert
;
611 char addr_str
[INET6_ADDRSTRLEN
];
612 struct zebra_if
*zif
;
617 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
619 if (len
< sizeof(struct nd_router_advert
)) {
620 if (IS_ZEBRA_DEBUG_PACKET
) {
621 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
624 "%s(%s:%u): Rx RA with invalid length %d from %s",
625 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, len
,
631 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
632 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
633 len
- sizeof(struct nd_router_advert
),
635 if (IS_ZEBRA_DEBUG_PACKET
) {
636 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
639 "%s(%s:%u): Rx RA with non-linklocal source address from %s",
640 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
,
646 radvert
= (struct nd_router_advert
*)msg
;
648 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
649 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
651 EC_ZEBRA_RA_PARAM_MISMATCH
,
652 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
653 ifp
->name
, ifp
->ifindex
, addr_str
);
656 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
657 && !zif
->rtadv
.AdvManagedFlag
) {
659 EC_ZEBRA_RA_PARAM_MISMATCH
,
660 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
661 ifp
->name
, ifp
->ifindex
, addr_str
);
664 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
665 && !zif
->rtadv
.AdvOtherConfigFlag
) {
667 EC_ZEBRA_RA_PARAM_MISMATCH
,
668 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
669 ifp
->name
, ifp
->ifindex
, addr_str
);
672 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
673 && (ntohl(radvert
->nd_ra_reachable
)
674 != zif
->rtadv
.AdvReachableTime
)) {
676 EC_ZEBRA_RA_PARAM_MISMATCH
,
677 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
678 ifp
->name
, ifp
->ifindex
, addr_str
);
681 if ((ntohl(radvert
->nd_ra_retransmit
)
682 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
684 EC_ZEBRA_RA_PARAM_MISMATCH
,
685 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
686 ifp
->name
, ifp
->ifindex
, addr_str
);
689 /* Create entry for neighbor if not known. */
691 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
692 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
694 if (!nbr_connected_check(ifp
, &p
))
695 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
699 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
700 ifindex_t ifindex
, int hoplimit
,
701 struct sockaddr_in6
*from
,
702 struct zebra_vrf
*zvrf
)
704 struct icmp6_hdr
*icmph
;
705 struct interface
*ifp
;
706 struct zebra_if
*zif
;
707 char addr_str
[INET6_ADDRSTRLEN
];
709 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
711 /* Interface search. */
712 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
714 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
715 "RA/RS received on unknown IF %u from %s", ifindex
,
720 if (IS_ZEBRA_DEBUG_PACKET
) {
721 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
723 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp
->name
,
724 VRF_LOGNAME(vrf
), ifp
->ifindex
, len
, addr_str
);
727 if (if_is_loopback(ifp
)
728 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
731 /* Check interface configuration. */
733 if (!zif
->rtadv
.AdvSendAdvertisements
)
736 /* ICMP message length check. */
737 if (len
< sizeof(struct icmp6_hdr
)) {
738 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
741 "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
742 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, len
);
746 icmph
= (struct icmp6_hdr
*)buf
;
748 /* ICMP message type check. */
749 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
750 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
751 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
753 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
754 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
,
759 /* Hoplimit check. */
760 if (hoplimit
>= 0 && hoplimit
!= 255) {
761 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
763 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
764 VRF_LOGNAME(vrf
), ifp
->ifindex
, hoplimit
);
768 /* Check ICMP message type. */
769 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
770 rtadv_process_solicit(ifp
);
771 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
772 rtadv_process_advert(buf
, len
, ifp
, from
);
777 static int rtadv_read(struct thread
*thread
)
781 uint8_t buf
[RTADV_MSG_SIZE
];
782 struct sockaddr_in6 from
;
783 ifindex_t ifindex
= 0;
785 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
787 sock
= THREAD_FD(thread
);
788 zvrf
->rtadv
.ra_read
= NULL
;
790 /* Register myself. */
791 rtadv_event(zvrf
, RTADV_READ
, sock
);
793 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
797 flog_err_sys(EC_LIB_SOCKET
,
798 "RA/RS recv failed, socket %u error %s", sock
,
799 safe_strerror(errno
));
803 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
808 static int rtadv_make_socket(ns_id_t ns_id
)
812 struct icmp6_filter filter
;
814 frr_with_privs(&zserv_privs
) {
816 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
824 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
829 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
834 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
839 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
844 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
850 ICMP6_FILTER_SETBLOCKALL(&filter
);
851 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
852 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
854 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
855 sizeof(struct icmp6_filter
));
857 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
865 static struct rtadv_prefix
*rtadv_prefix_new(void)
867 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
870 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
872 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
875 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
876 struct prefix_ipv6
*p
)
878 struct listnode
*node
;
879 struct rtadv_prefix
*rprefix
;
881 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
882 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
888 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
889 struct prefix_ipv6
*p
)
891 struct rtadv_prefix
*rprefix
;
893 rprefix
= rtadv_prefix_lookup(rplist
, p
);
897 rprefix
= rtadv_prefix_new();
898 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
899 listnode_add(rplist
, rprefix
);
904 static void rtadv_prefix_set_defaults(struct rtadv_prefix
*rp
)
906 rp
->AdvAutonomousFlag
= 1;
907 rp
->AdvOnLinkFlag
= 1;
908 rp
->AdvRouterAddressFlag
= 0;
909 rp
->AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
910 rp
->AdvValidLifetime
= RTADV_VALID_LIFETIME
;
913 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
915 struct rtadv_prefix
*rprefix
;
917 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
920 * Set parameters based on where the prefix is created.
921 * If auto-created based on kernel address addition, set the
922 * default values. If created from a manual "ipv6 nd prefix"
923 * command, take the parameters from the manual command. Note
924 * that if the manual command exists, the default values will
925 * not overwrite the manual values.
927 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
928 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_AUTO
)
929 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
931 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
933 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
934 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
935 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
936 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
937 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
938 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
939 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
940 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
942 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
943 rtadv_prefix_set_defaults(rprefix
);
948 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
950 struct rtadv_prefix
*rprefix
;
952 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
953 if (rprefix
!= NULL
) {
956 * When deleting an address from the list, need to take care
957 * it wasn't defined both automatically via kernel
958 * address addition as well as manually by vtysh cli. If both,
959 * we don't actually delete but may change the parameters
960 * back to default if a manually defined entry is deleted.
962 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
963 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
964 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
965 rtadv_prefix_set_defaults(rprefix
);
968 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
969 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
970 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
975 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
976 rtadv_prefix_free(rprefix
);
982 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
983 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
985 struct rtadv_prefix rp
;
988 apply_mask_ipv6(&rp
.prefix
);
989 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
990 rtadv_prefix_set(zif
, &rp
);
993 /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
994 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
996 struct rtadv_prefix rp
;
998 rp
.prefix
= *((struct prefix_ipv6
*)p
);
999 apply_mask_ipv6(&rp
.prefix
);
1000 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1001 rtadv_prefix_reset(zif
, &rp
);
1004 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
1005 enum ipv6_nd_suppress_ra_status status
)
1007 struct zebra_if
*zif
;
1008 struct zebra_vrf
*zvrf
;
1011 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1013 if (status
== RA_SUPPRESS
) {
1014 /* RA is currently enabled */
1015 if (zif
->rtadv
.AdvSendAdvertisements
) {
1016 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
,
1018 zif
->rtadv
.AdvSendAdvertisements
= 0;
1019 zif
->rtadv
.AdvIntervalTimer
= 0;
1020 zvrf
->rtadv
.adv_if_count
--;
1022 if_leave_all_router(rtadv_get_socket(zvrf
), ifp
);
1024 if (zvrf
->rtadv
.adv_if_count
== 0)
1025 rtadv_event(zvrf
, RTADV_STOP
, 0);
1028 if (!zif
->rtadv
.AdvSendAdvertisements
) {
1029 zif
->rtadv
.AdvSendAdvertisements
= 1;
1030 zif
->rtadv
.AdvIntervalTimer
= 0;
1031 zvrf
->rtadv
.adv_if_count
++;
1033 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
1034 && zif
->rtadv
.UseFastRexmit
) {
1036 * Enable Fast RA only when RA interval is in
1037 * secs and Fast RA retransmit is enabled
1039 zif
->rtadv
.inFastRexmit
= 1;
1040 zif
->rtadv
.NumFastReXmitsRemain
=
1041 RTADV_NUM_FAST_REXMITS
;
1044 if_join_all_router(rtadv_get_socket(zvrf
), ifp
);
1046 if (zvrf
->rtadv
.adv_if_count
== 1)
1047 rtadv_event(zvrf
, RTADV_START
,
1048 rtadv_get_socket(zvrf
));
1054 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1055 * Note that while the client could request RA on an interface on which the
1056 * operator has not enabled RA, RA won't be disabled upon client request
1057 * if the operator has explicitly enabled RA. The enable request can also
1058 * specify a RA interval (in seconds).
1060 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
1064 struct interface
*ifp
;
1065 struct zebra_if
*zif
;
1066 int ra_interval_rxd
;
1070 /* Get interface index and RA interval. */
1071 STREAM_GETL(s
, ifindex
);
1072 STREAM_GETL(s
, ra_interval_rxd
);
1074 if (ra_interval_rxd
< 0) {
1076 "Requested RA interval %d is garbage; ignoring request",
1081 unsigned int ra_interval
= ra_interval_rxd
;
1083 if (IS_ZEBRA_DEBUG_EVENT
) {
1084 struct vrf
*vrf
= zvrf
->vrf
;
1086 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1087 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1088 enable
? "enable" : "disable",
1089 zebra_route_string(client
->proto
), ra_interval
);
1092 /* Locate interface and check VRF match. */
1093 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
1095 struct vrf
*vrf
= zvrf
->vrf
;
1097 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
1098 "%s:%u: IF %u RA %s client %s - interface unknown",
1099 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1100 enable
? "enable" : "disable",
1101 zebra_route_string(client
->proto
));
1104 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
1105 struct vrf
*vrf
= zvrf
->vrf
;
1108 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1109 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1110 enable
? "enable" : "disable",
1111 zebra_route_string(client
->proto
), ifp
->vrf_id
);
1117 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1118 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1120 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1121 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1122 VTY_RA_INTERVAL_CONFIGURED
))
1123 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1125 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1126 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1127 VTY_RA_INTERVAL_CONFIGURED
))
1128 zif
->rtadv
.MaxRtrAdvInterval
=
1129 RTADV_MAX_RTR_ADV_INTERVAL
;
1130 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1131 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1138 * send router lifetime value of zero in RAs on this interface since we're
1139 * ceasing to advertise and want to let our neighbors know.
1140 * RFC 4861 secion 6.2.5
1142 void rtadv_stop_ra(struct interface
*ifp
)
1144 struct zebra_if
*zif
;
1145 struct zebra_vrf
*zvrf
;
1148 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1150 if (zif
->rtadv
.AdvSendAdvertisements
)
1151 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
, RA_SUPPRESS
);
1155 * Send router lifetime value of zero in RAs on all interfaces since we're
1156 * ceasing to advertise globally and want to let all of our neighbors know
1157 * RFC 4861 secion 6.2.5
1159 * Delete all ipv6 global prefixes added to the router advertisement prefix
1160 * lists prior to ceasing.
1162 void rtadv_stop_ra_all(void)
1165 struct interface
*ifp
;
1166 struct listnode
*node
, *nnode
;
1167 struct zebra_if
*zif
;
1168 struct rtadv_prefix
*rprefix
;
1170 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1171 FOR_ALL_INTERFACES (vrf
, ifp
) {
1174 for (ALL_LIST_ELEMENTS(zif
->rtadv
.AdvPrefixList
,
1175 node
, nnode
, rprefix
))
1176 rtadv_prefix_reset(zif
, rprefix
);
1182 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1184 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1186 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1188 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1191 DEFUN (ipv6_nd_ra_fast_retrans
,
1192 ipv6_nd_ra_fast_retrans_cmd
,
1193 "ipv6 nd ra-fast-retrans",
1194 "Interface IPv6 config commands\n"
1195 "Neighbor discovery\n"
1196 "Fast retransmit of RA packets\n")
1198 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1199 struct zebra_if
*zif
= ifp
->info
;
1201 if (if_is_loopback(ifp
)
1202 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1204 "Cannot configure IPv6 Router Advertisements on this interface\n");
1205 return CMD_WARNING_CONFIG_FAILED
;
1208 zif
->rtadv
.UseFastRexmit
= true;
1213 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1214 no_ipv6_nd_ra_fast_retrans_cmd
,
1215 "no ipv6 nd ra-fast-retrans",
1217 "Interface IPv6 config commands\n"
1218 "Neighbor discovery\n"
1219 "Fast retransmit of RA packets\n")
1221 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1222 struct zebra_if
*zif
= ifp
->info
;
1224 if (if_is_loopback(ifp
)
1225 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1227 "Cannot configure IPv6 Router Advertisements on this interface\n");
1228 return CMD_WARNING_CONFIG_FAILED
;
1231 zif
->rtadv
.UseFastRexmit
= false;
1236 DEFPY (ipv6_nd_ra_hop_limit
,
1237 ipv6_nd_ra_hop_limit_cmd
,
1238 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1239 "Interface IPv6 config commands\n"
1240 "Neighbor discovery\n"
1241 "Advertisement Hop Limit\n"
1242 "Advertisement Hop Limit in hops (default:64)\n")
1244 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1245 struct zebra_if
*zif
= ifp
->info
;
1247 if (if_is_loopback(ifp
)
1248 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1250 "Cannot configure IPv6 Router Advertisements on this interface\n");
1251 return CMD_WARNING_CONFIG_FAILED
;
1254 zif
->rtadv
.AdvCurHopLimit
= hopcount
;
1259 DEFPY (no_ipv6_nd_ra_hop_limit
,
1260 no_ipv6_nd_ra_hop_limit_cmd
,
1261 "no ipv6 nd ra-hop-limit [(0-255)]",
1263 "Interface IPv6 config commands\n"
1264 "Neighbor discovery\n"
1265 "Advertisement Hop Limit\n"
1266 "Advertisement Hop Limit in hops\n")
1268 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1269 struct zebra_if
*zif
= ifp
->info
;
1271 if (if_is_loopback(ifp
)
1272 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1274 "Cannot configure IPv6 Router Advertisements on this interface\n");
1275 return CMD_WARNING_CONFIG_FAILED
;
1278 zif
->rtadv
.AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
1283 DEFPY (ipv6_nd_ra_retrans_interval
,
1284 ipv6_nd_ra_retrans_interval_cmd
,
1285 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1286 "Interface IPv6 config commands\n"
1287 "Neighbor discovery\n"
1288 "Advertisement Retransmit Interval\n"
1289 "Advertisement Retransmit Interval in msec\n")
1291 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1292 struct zebra_if
*zif
= ifp
->info
;
1294 if (if_is_loopback(ifp
)
1295 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1297 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1298 return CMD_WARNING_CONFIG_FAILED
;
1301 zif
->rtadv
.AdvRetransTimer
= interval
;
1306 DEFPY (no_ipv6_nd_ra_retrans_interval
,
1307 no_ipv6_nd_ra_retrans_interval_cmd
,
1308 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1310 "Interface IPv6 config commands\n"
1311 "Neighbor discovery\n"
1312 "Advertisement Retransmit Interval\n"
1313 "Advertisement Retransmit Interval in msec\n")
1315 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1316 struct zebra_if
*zif
= ifp
->info
;
1318 if (if_is_loopback(ifp
)
1319 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1321 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1322 return CMD_WARNING_CONFIG_FAILED
;
1325 zif
->rtadv
.AdvRetransTimer
= 0;
1330 DEFUN (ipv6_nd_suppress_ra
,
1331 ipv6_nd_suppress_ra_cmd
,
1332 "ipv6 nd suppress-ra",
1333 "Interface IPv6 config commands\n"
1334 "Neighbor discovery\n"
1335 "Suppress Router Advertisement\n")
1337 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1338 struct zebra_if
*zif
= ifp
->info
;
1340 if (if_is_loopback(ifp
)
1341 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1343 "Cannot configure IPv6 Router Advertisements on this interface\n");
1344 return CMD_WARNING_CONFIG_FAILED
;
1347 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1348 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1350 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1354 DEFUN (no_ipv6_nd_suppress_ra
,
1355 no_ipv6_nd_suppress_ra_cmd
,
1356 "no ipv6 nd suppress-ra",
1358 "Interface IPv6 config commands\n"
1359 "Neighbor discovery\n"
1360 "Suppress Router Advertisement\n")
1362 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1363 struct zebra_if
*zif
= ifp
->info
;
1365 if (if_is_loopback(ifp
)
1366 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1368 "Cannot configure IPv6 Router Advertisements on this interface\n");
1369 return CMD_WARNING_CONFIG_FAILED
;
1372 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1373 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1377 DEFUN (ipv6_nd_ra_interval_msec
,
1378 ipv6_nd_ra_interval_msec_cmd
,
1379 "ipv6 nd ra-interval msec (70-1800000)",
1380 "Interface IPv6 config commands\n"
1381 "Neighbor discovery\n"
1382 "Router Advertisement interval\n"
1383 "Router Advertisement interval in milliseconds\n"
1384 "Router Advertisement interval in milliseconds\n")
1387 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1389 struct zebra_if
*zif
= ifp
->info
;
1390 struct zebra_vrf
*zvrf
;
1392 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1394 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1395 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1396 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1398 "This ra-interval would conflict with configured ra-lifetime!\n");
1399 return CMD_WARNING_CONFIG_FAILED
;
1402 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1403 zvrf
->rtadv
.adv_msec_if_count
--;
1405 if (interval
% 1000)
1406 zvrf
->rtadv
.adv_msec_if_count
++;
1408 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1409 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1410 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1411 zif
->rtadv
.AdvIntervalTimer
= 0;
1416 DEFUN (ipv6_nd_ra_interval
,
1417 ipv6_nd_ra_interval_cmd
,
1418 "ipv6 nd ra-interval (1-1800)",
1419 "Interface IPv6 config commands\n"
1420 "Neighbor discovery\n"
1421 "Router Advertisement interval\n"
1422 "Router Advertisement interval in seconds\n")
1425 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1427 struct zebra_if
*zif
= ifp
->info
;
1428 struct zebra_vrf
*zvrf
;
1430 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1432 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1433 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1434 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1436 "This ra-interval would conflict with configured ra-lifetime!\n");
1437 return CMD_WARNING_CONFIG_FAILED
;
1440 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1441 zvrf
->rtadv
.adv_msec_if_count
--;
1443 /* convert to milliseconds */
1444 interval
= interval
* 1000;
1446 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1447 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1448 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1449 zif
->rtadv
.AdvIntervalTimer
= 0;
1454 DEFUN (no_ipv6_nd_ra_interval
,
1455 no_ipv6_nd_ra_interval_cmd
,
1456 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1458 "Interface IPv6 config commands\n"
1459 "Neighbor discovery\n"
1460 "Router Advertisement interval\n"
1461 "Router Advertisement interval in seconds\n"
1462 "Specify millisecond router advertisement interval\n"
1463 "Router Advertisement interval in milliseconds\n")
1465 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1466 struct zebra_if
*zif
= ifp
->info
;
1467 struct zebra_vrf
*zvrf
= NULL
;
1469 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1471 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1472 zvrf
->rtadv
.adv_msec_if_count
--;
1474 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1476 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1477 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1479 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1481 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1482 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1487 DEFUN (ipv6_nd_ra_lifetime
,
1488 ipv6_nd_ra_lifetime_cmd
,
1489 "ipv6 nd ra-lifetime (0-9000)",
1490 "Interface IPv6 config commands\n"
1491 "Neighbor discovery\n"
1493 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1496 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1497 struct zebra_if
*zif
= ifp
->info
;
1500 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1502 /* The value to be placed in the Router Lifetime field
1503 * of Router Advertisements sent from the interface,
1504 * in seconds. MUST be either zero or between
1505 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1506 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1508 "This ra-lifetime would conflict with configured ra-interval\n");
1509 return CMD_WARNING_CONFIG_FAILED
;
1512 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1517 DEFUN (no_ipv6_nd_ra_lifetime
,
1518 no_ipv6_nd_ra_lifetime_cmd
,
1519 "no ipv6 nd ra-lifetime [(0-9000)]",
1521 "Interface IPv6 config commands\n"
1522 "Neighbor discovery\n"
1524 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1526 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1527 struct zebra_if
*zif
= ifp
->info
;
1529 zif
->rtadv
.AdvDefaultLifetime
= -1;
1534 DEFUN (ipv6_nd_reachable_time
,
1535 ipv6_nd_reachable_time_cmd
,
1536 "ipv6 nd reachable-time (1-3600000)",
1537 "Interface IPv6 config commands\n"
1538 "Neighbor discovery\n"
1540 "Reachable time in milliseconds\n")
1543 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1544 struct zebra_if
*zif
= ifp
->info
;
1545 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1549 DEFUN (no_ipv6_nd_reachable_time
,
1550 no_ipv6_nd_reachable_time_cmd
,
1551 "no ipv6 nd reachable-time [(1-3600000)]",
1553 "Interface IPv6 config commands\n"
1554 "Neighbor discovery\n"
1556 "Reachable time in milliseconds\n")
1558 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1559 struct zebra_if
*zif
= ifp
->info
;
1561 zif
->rtadv
.AdvReachableTime
= 0;
1566 DEFUN (ipv6_nd_homeagent_preference
,
1567 ipv6_nd_homeagent_preference_cmd
,
1568 "ipv6 nd home-agent-preference (0-65535)",
1569 "Interface IPv6 config commands\n"
1570 "Neighbor discovery\n"
1571 "Home Agent preference\n"
1572 "preference value (default is 0, least preferred)\n")
1575 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1576 struct zebra_if
*zif
= ifp
->info
;
1577 zif
->rtadv
.HomeAgentPreference
=
1578 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1582 DEFUN (no_ipv6_nd_homeagent_preference
,
1583 no_ipv6_nd_homeagent_preference_cmd
,
1584 "no ipv6 nd home-agent-preference [(0-65535)]",
1586 "Interface IPv6 config commands\n"
1587 "Neighbor discovery\n"
1588 "Home Agent preference\n"
1589 "preference value (default is 0, least preferred)\n")
1591 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1592 struct zebra_if
*zif
= ifp
->info
;
1594 zif
->rtadv
.HomeAgentPreference
= 0;
1599 DEFUN (ipv6_nd_homeagent_lifetime
,
1600 ipv6_nd_homeagent_lifetime_cmd
,
1601 "ipv6 nd home-agent-lifetime (0-65520)",
1602 "Interface IPv6 config commands\n"
1603 "Neighbor discovery\n"
1604 "Home Agent lifetime\n"
1605 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1608 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1609 struct zebra_if
*zif
= ifp
->info
;
1610 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1614 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1615 no_ipv6_nd_homeagent_lifetime_cmd
,
1616 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1618 "Interface IPv6 config commands\n"
1619 "Neighbor discovery\n"
1620 "Home Agent lifetime\n"
1621 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1623 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1624 struct zebra_if
*zif
= ifp
->info
;
1626 zif
->rtadv
.HomeAgentLifetime
= -1;
1631 DEFUN (ipv6_nd_managed_config_flag
,
1632 ipv6_nd_managed_config_flag_cmd
,
1633 "ipv6 nd managed-config-flag",
1634 "Interface IPv6 config commands\n"
1635 "Neighbor discovery\n"
1636 "Managed address configuration flag\n")
1638 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1639 struct zebra_if
*zif
= ifp
->info
;
1641 zif
->rtadv
.AdvManagedFlag
= 1;
1646 DEFUN (no_ipv6_nd_managed_config_flag
,
1647 no_ipv6_nd_managed_config_flag_cmd
,
1648 "no ipv6 nd managed-config-flag",
1650 "Interface IPv6 config commands\n"
1651 "Neighbor discovery\n"
1652 "Managed address configuration flag\n")
1654 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1655 struct zebra_if
*zif
= ifp
->info
;
1657 zif
->rtadv
.AdvManagedFlag
= 0;
1662 DEFUN (ipv6_nd_homeagent_config_flag
,
1663 ipv6_nd_homeagent_config_flag_cmd
,
1664 "ipv6 nd home-agent-config-flag",
1665 "Interface IPv6 config commands\n"
1666 "Neighbor discovery\n"
1667 "Home Agent configuration flag\n")
1669 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1670 struct zebra_if
*zif
= ifp
->info
;
1672 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1677 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1678 no_ipv6_nd_homeagent_config_flag_cmd
,
1679 "no ipv6 nd home-agent-config-flag",
1681 "Interface IPv6 config commands\n"
1682 "Neighbor discovery\n"
1683 "Home Agent configuration flag\n")
1685 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1686 struct zebra_if
*zif
= ifp
->info
;
1688 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1693 DEFUN (ipv6_nd_adv_interval_config_option
,
1694 ipv6_nd_adv_interval_config_option_cmd
,
1695 "ipv6 nd adv-interval-option",
1696 "Interface IPv6 config commands\n"
1697 "Neighbor discovery\n"
1698 "Advertisement Interval Option\n")
1700 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1701 struct zebra_if
*zif
= ifp
->info
;
1703 zif
->rtadv
.AdvIntervalOption
= 1;
1708 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1709 no_ipv6_nd_adv_interval_config_option_cmd
,
1710 "no ipv6 nd adv-interval-option",
1712 "Interface IPv6 config commands\n"
1713 "Neighbor discovery\n"
1714 "Advertisement Interval Option\n")
1716 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1717 struct zebra_if
*zif
= ifp
->info
;
1719 zif
->rtadv
.AdvIntervalOption
= 0;
1724 DEFUN (ipv6_nd_other_config_flag
,
1725 ipv6_nd_other_config_flag_cmd
,
1726 "ipv6 nd other-config-flag",
1727 "Interface IPv6 config commands\n"
1728 "Neighbor discovery\n"
1729 "Other statefull configuration flag\n")
1731 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1732 struct zebra_if
*zif
= ifp
->info
;
1734 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1739 DEFUN (no_ipv6_nd_other_config_flag
,
1740 no_ipv6_nd_other_config_flag_cmd
,
1741 "no ipv6 nd other-config-flag",
1743 "Interface IPv6 config commands\n"
1744 "Neighbor discovery\n"
1745 "Other statefull configuration flag\n")
1747 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1748 struct zebra_if
*zif
= ifp
->info
;
1750 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1755 DEFUN (ipv6_nd_prefix
,
1757 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1758 "Interface IPv6 config commands\n"
1759 "Neighbor discovery\n"
1760 "Prefix information\n"
1762 "Valid lifetime in seconds\n"
1763 "Infinite valid lifetime\n"
1764 "Preferred lifetime in seconds\n"
1765 "Infinite preferred lifetime\n"
1766 "Set Router Address flag\n"
1767 "Do not use prefix for onlink determination\n"
1768 "Do not use prefix for autoconfiguration\n"
1769 "Do not use prefix for autoconfiguration\n"
1770 "Do not use prefix for onlink determination\n")
1773 char *prefix
= argv
[3]->arg
;
1774 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1775 || strmatch(argv
[4]->text
, "infinite"));
1776 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1778 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1780 char *lifetime
= NULL
, *preflifetime
= NULL
;
1781 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1783 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1785 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1790 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1792 offlink
= (argc
> idx_routeropts
+ 1
1793 || strmatch(argv
[idx_routeropts
]->text
,
1795 noautoconf
= (argc
> idx_routeropts
+ 1
1796 || strmatch(argv
[idx_routeropts
]->text
,
1802 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1803 struct zebra_if
*zebra_if
= ifp
->info
;
1805 struct rtadv_prefix rp
;
1807 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1809 vty_out(vty
, "Malformed IPv6 prefix\n");
1810 return CMD_WARNING_CONFIG_FAILED
;
1812 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1813 rp
.AdvOnLinkFlag
= !offlink
;
1814 rp
.AdvAutonomousFlag
= !noautoconf
;
1815 rp
.AdvRouterAddressFlag
= routeraddr
;
1816 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1817 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1818 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1821 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1823 : strtoll(lifetime
, NULL
, 10);
1824 rp
.AdvPreferredLifetime
=
1825 strmatch(preflifetime
, "infinite")
1827 : strtoll(preflifetime
, NULL
, 10);
1828 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1829 vty_out(vty
, "Invalid preferred lifetime\n");
1830 return CMD_WARNING_CONFIG_FAILED
;
1834 rtadv_prefix_set(zebra_if
, &rp
);
1839 DEFUN (no_ipv6_nd_prefix
,
1840 no_ipv6_nd_prefix_cmd
,
1841 "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]>]",
1843 "Interface IPv6 config commands\n"
1844 "Neighbor discovery\n"
1845 "Prefix information\n"
1847 "Valid lifetime in seconds\n"
1848 "Infinite valid lifetime\n"
1849 "Preferred lifetime in seconds\n"
1850 "Infinite preferred lifetime\n"
1851 "Set Router Address flag\n"
1852 "Do not use prefix for onlink determination\n"
1853 "Do not use prefix for autoconfiguration\n"
1854 "Do not use prefix for autoconfiguration\n"
1855 "Do not use prefix for onlink determination\n")
1857 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1858 struct zebra_if
*zebra_if
= ifp
->info
;
1860 struct rtadv_prefix rp
;
1861 char *prefix
= argv
[4]->arg
;
1863 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1865 vty_out(vty
, "Malformed IPv6 prefix\n");
1866 return CMD_WARNING_CONFIG_FAILED
;
1868 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1869 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1871 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1873 vty_out(vty
, "Non-existant IPv6 prefix\n");
1874 return CMD_WARNING_CONFIG_FAILED
;
1880 DEFUN (ipv6_nd_router_preference
,
1881 ipv6_nd_router_preference_cmd
,
1882 "ipv6 nd router-preference <high|medium|low>",
1883 "Interface IPv6 config commands\n"
1884 "Neighbor discovery\n"
1885 "Default router preference\n"
1886 "High default router preference\n"
1887 "Medium default router preference (default)\n"
1888 "Low default router preference\n")
1890 int idx_high_medium_low
= 3;
1891 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1892 struct zebra_if
*zif
= ifp
->info
;
1895 while (0 != rtadv_pref_strs
[i
]) {
1896 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1899 zif
->rtadv
.DefaultPreference
= i
;
1905 return CMD_ERR_NO_MATCH
;
1908 DEFUN (no_ipv6_nd_router_preference
,
1909 no_ipv6_nd_router_preference_cmd
,
1910 "no ipv6 nd router-preference [<high|medium|low>]",
1912 "Interface IPv6 config commands\n"
1913 "Neighbor discovery\n"
1914 "Default router preference\n"
1915 "High default router preference\n"
1916 "Medium default router preference (default)\n"
1917 "Low default router preference\n")
1919 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1920 struct zebra_if
*zif
= ifp
->info
;
1922 zif
->rtadv
.DefaultPreference
=
1923 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1930 "ipv6 nd mtu (1-65535)",
1931 "Interface IPv6 config commands\n"
1932 "Neighbor discovery\n"
1937 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1938 struct zebra_if
*zif
= ifp
->info
;
1939 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1943 DEFUN (no_ipv6_nd_mtu
,
1945 "no ipv6 nd mtu [(1-65535)]",
1947 "Interface IPv6 config commands\n"
1948 "Neighbor discovery\n"
1952 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1953 struct zebra_if
*zif
= ifp
->info
;
1954 zif
->rtadv
.AdvLinkMTU
= 0;
1958 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
1960 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
1963 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
1965 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
1968 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
1969 struct rtadv_rdnss
*rdnss
)
1971 struct listnode
*node
;
1972 struct rtadv_rdnss
*p
;
1974 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1975 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
1980 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
1981 struct rtadv_rdnss
*rdnss
)
1983 struct rtadv_rdnss
*p
;
1985 p
= rtadv_rdnss_lookup(list
, rdnss
);
1989 p
= rtadv_rdnss_new();
1990 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
1991 listnode_add(list
, p
);
1996 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1998 struct rtadv_rdnss
*p
;
2000 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2001 p
->lifetime
= rdnss
->lifetime
;
2002 p
->lifetime_set
= rdnss
->lifetime_set
;
2005 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2007 struct rtadv_rdnss
*p
;
2009 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2011 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
2012 rtadv_rdnss_free(p
);
2019 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
2021 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
2024 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
2026 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
2029 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
2030 struct rtadv_dnssl
*dnssl
)
2032 struct listnode
*node
;
2033 struct rtadv_dnssl
*p
;
2035 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2036 if (!strcasecmp(p
->name
, dnssl
->name
))
2041 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
2042 struct rtadv_dnssl
*dnssl
)
2044 struct rtadv_dnssl
*p
;
2046 p
= rtadv_dnssl_lookup(list
, dnssl
);
2050 p
= rtadv_dnssl_new();
2051 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2052 listnode_add(list
, p
);
2057 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2059 struct rtadv_dnssl
*p
;
2061 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2062 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2065 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2067 struct rtadv_dnssl
*p
;
2069 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2071 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
2072 rtadv_dnssl_free(p
);
2080 * Convert dotted domain name (with or without trailing root zone dot) to
2081 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2082 * to strlen(in) + 2 octets to out.
2084 * Returns the number of octets written to out or -1 if in does not constitute
2085 * a valid domain name.
2087 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
2089 const char *label_start
, *label_end
;
2095 while (*label_start
) {
2098 label_end
= strchr(label_start
, '.');
2099 if (label_end
== NULL
)
2100 label_end
= label_start
+ strlen(label_start
);
2102 label_len
= label_end
- label_start
;
2103 if (label_len
>= 64)
2104 return -1; /* labels must be 63 octets or less */
2106 out
[outp
++] = (uint8_t)label_len
;
2107 memcpy(out
+ outp
, label_start
, label_len
);
2109 label_start
+= label_len
;
2110 if (*label_start
== '.')
2118 DEFUN(ipv6_nd_rdnss
,
2120 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2121 "Interface IPv6 config commands\n"
2122 "Neighbor discovery\n"
2123 "Recursive DNS server information\n"
2125 "Valid lifetime in seconds\n"
2126 "Infinite valid lifetime\n")
2128 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2129 struct zebra_if
*zif
= ifp
->info
;
2130 struct rtadv_rdnss rdnss
= {};
2132 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
2133 vty_out(vty
, "Malformed IPv6 address\n");
2134 return CMD_WARNING_CONFIG_FAILED
;
2137 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2139 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
2141 : strtoll(lifetime
, NULL
, 10);
2142 rdnss
.lifetime_set
= 1;
2145 rtadv_rdnss_set(zif
, &rdnss
);
2150 DEFUN(no_ipv6_nd_rdnss
,
2151 no_ipv6_nd_rdnss_cmd
,
2152 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2154 "Interface IPv6 config commands\n"
2155 "Neighbor discovery\n"
2156 "Recursive DNS server information\n"
2158 "Valid lifetime in seconds\n"
2159 "Infinite valid lifetime\n")
2161 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2162 struct zebra_if
*zif
= ifp
->info
;
2163 struct rtadv_rdnss rdnss
= {};
2165 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
2166 vty_out(vty
, "Malformed IPv6 address\n");
2167 return CMD_WARNING_CONFIG_FAILED
;
2169 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
2170 vty_out(vty
, "Non-existant RDNSS address\n");
2171 return CMD_WARNING_CONFIG_FAILED
;
2177 DEFUN(ipv6_nd_dnssl
,
2179 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2180 "Interface IPv6 config commands\n"
2181 "Neighbor discovery\n"
2182 "DNS search list information\n"
2183 "Domain name suffix\n"
2184 "Valid lifetime in seconds\n"
2185 "Infinite valid lifetime\n")
2187 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2188 struct zebra_if
*zif
= ifp
->info
;
2189 struct rtadv_dnssl dnssl
= {};
2193 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
2194 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2195 vty_out(vty
, "Malformed DNS search domain\n");
2196 return CMD_WARNING_CONFIG_FAILED
;
2198 if (dnssl
.name
[len
- 1] == '.') {
2200 * Allow, but don't require, a trailing dot signifying the root
2201 * zone. Canonicalize by cutting it off if present.
2203 dnssl
.name
[len
- 1] = '\0';
2207 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2209 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
2211 : strtoll(lifetime
, NULL
, 10);
2212 dnssl
.lifetime_set
= 1;
2215 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2217 vty_out(vty
, "Malformed DNS search domain\n");
2218 return CMD_WARNING_CONFIG_FAILED
;
2220 dnssl
.encoded_len
= ret
;
2221 rtadv_dnssl_set(zif
, &dnssl
);
2226 DEFUN(no_ipv6_nd_dnssl
,
2227 no_ipv6_nd_dnssl_cmd
,
2228 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2230 "Interface IPv6 config commands\n"
2231 "Neighbor discovery\n"
2232 "DNS search list information\n"
2233 "Domain name suffix\n"
2234 "Valid lifetime in seconds\n"
2235 "Infinite valid lifetime\n")
2237 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2238 struct zebra_if
*zif
= ifp
->info
;
2239 struct rtadv_dnssl dnssl
= {};
2242 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2243 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2244 vty_out(vty
, "Malformed DNS search domain\n");
2245 return CMD_WARNING_CONFIG_FAILED
;
2247 if (dnssl
.name
[len
- 1] == '.') {
2248 dnssl
.name
[len
- 1] = '\0';
2251 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2252 vty_out(vty
, "Non-existant DNS search domain\n");
2253 return CMD_WARNING_CONFIG_FAILED
;
2260 /* Dump interface ND information to vty. */
2261 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2263 struct zebra_if
*zif
;
2264 struct rtadvconf
*rtadv
;
2267 zif
= (struct zebra_if
*)ifp
->info
;
2268 rtadv
= &zif
->rtadv
;
2270 if (rtadv
->AdvSendAdvertisements
) {
2272 " ND advertised reachable time is %d milliseconds\n",
2273 rtadv
->AdvReachableTime
);
2275 " ND advertised retransmit interval is %u milliseconds\n",
2276 rtadv
->AdvRetransTimer
);
2277 vty_out(vty
, " ND advertised hop-count limit is %d hops\n",
2278 rtadv
->AdvCurHopLimit
);
2279 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2280 zif
->ra_sent
, zif
->ra_rcvd
);
2281 interval
= rtadv
->MaxRtrAdvInterval
;
2282 if (interval
% 1000)
2284 " ND router advertisements are sent every %d milliseconds\n",
2288 " ND router advertisements are sent every %d seconds\n",
2290 if (!rtadv
->UseFastRexmit
)
2292 " ND router advertisements do not use fast retransmit\n");
2294 if (rtadv
->AdvDefaultLifetime
!= -1)
2296 " ND router advertisements live for %d seconds\n",
2297 rtadv
->AdvDefaultLifetime
);
2300 " ND router advertisements lifetime tracks ra-interval\n");
2302 " ND router advertisement default router preference is %s\n",
2303 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2304 if (rtadv
->AdvManagedFlag
)
2306 " Hosts use DHCP to obtain routable addresses.\n");
2309 " Hosts use stateless autoconfig for addresses.\n");
2310 if (rtadv
->AdvHomeAgentFlag
) {
2312 " ND router advertisements with Home Agent flag bit set.\n");
2313 if (rtadv
->HomeAgentLifetime
!= -1)
2315 " Home Agent lifetime is %u seconds\n",
2316 rtadv
->HomeAgentLifetime
);
2319 " Home Agent lifetime tracks ra-lifetime\n");
2320 vty_out(vty
, " Home Agent preference is %u\n",
2321 rtadv
->HomeAgentPreference
);
2323 if (rtadv
->AdvIntervalOption
)
2325 " ND router advertisements with Adv. Interval option.\n");
2331 /* Write configuration about router advertisement. */
2332 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2334 struct zebra_if
*zif
;
2335 struct listnode
*node
;
2336 struct rtadv_prefix
*rprefix
;
2337 struct rtadv_rdnss
*rdnss
;
2338 struct rtadv_dnssl
*dnssl
;
2343 if (!(if_is_loopback(ifp
)
2344 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
2345 if (zif
->rtadv
.AdvSendAdvertisements
2346 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2347 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2350 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2351 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2352 if (interval
% 1000)
2353 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2355 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2356 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2360 if (zif
->rtadv
.AdvIntervalOption
)
2361 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2363 if (!zif
->rtadv
.UseFastRexmit
)
2364 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2366 if (zif
->rtadv
.AdvRetransTimer
!= 0)
2367 vty_out(vty
, " ipv6 nd ra-retrans-interval %u\n",
2368 zif
->rtadv
.AdvRetransTimer
);
2370 if (zif
->rtadv
.AdvCurHopLimit
!= RTADV_DEFAULT_HOPLIMIT
)
2371 vty_out(vty
, " ipv6 nd ra-hop-limit %d\n",
2372 zif
->rtadv
.AdvCurHopLimit
);
2374 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2375 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2376 zif
->rtadv
.AdvDefaultLifetime
);
2378 if (zif
->rtadv
.HomeAgentPreference
)
2379 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2380 zif
->rtadv
.HomeAgentPreference
);
2382 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2383 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2384 zif
->rtadv
.HomeAgentLifetime
);
2386 if (zif
->rtadv
.AdvHomeAgentFlag
)
2387 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2389 if (zif
->rtadv
.AdvReachableTime
)
2390 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2391 zif
->rtadv
.AdvReachableTime
);
2393 if (zif
->rtadv
.AdvManagedFlag
)
2394 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2396 if (zif
->rtadv
.AdvOtherConfigFlag
)
2397 vty_out(vty
, " ipv6 nd other-config-flag\n");
2399 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2400 vty_out(vty
, " ipv6 nd router-preference %s\n",
2401 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2403 if (zif
->rtadv
.AdvLinkMTU
)
2404 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2406 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
2407 if ((rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
2408 || (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
)) {
2409 vty_out(vty
, " ipv6 nd prefix %pFX", &rprefix
->prefix
);
2410 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2411 || (rprefix
->AdvPreferredLifetime
2412 != RTADV_PREFERRED_LIFETIME
)) {
2413 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2414 vty_out(vty
, " infinite");
2417 rprefix
->AdvValidLifetime
);
2418 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2419 vty_out(vty
, " infinite");
2422 rprefix
->AdvPreferredLifetime
);
2424 if (!rprefix
->AdvOnLinkFlag
)
2425 vty_out(vty
, " off-link");
2426 if (!rprefix
->AdvAutonomousFlag
)
2427 vty_out(vty
, " no-autoconfig");
2428 if (rprefix
->AdvRouterAddressFlag
)
2429 vty_out(vty
, " router-address");
2434 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2435 char buf
[INET6_ADDRSTRLEN
];
2437 vty_out(vty
, " ipv6 nd rdnss %s",
2438 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2439 if (rdnss
->lifetime_set
) {
2440 if (rdnss
->lifetime
== UINT32_MAX
)
2441 vty_out(vty
, " infinite");
2443 vty_out(vty
, " %u", rdnss
->lifetime
);
2447 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2448 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2449 if (dnssl
->lifetime_set
) {
2450 if (dnssl
->lifetime
== UINT32_MAX
)
2451 vty_out(vty
, " infinite");
2453 vty_out(vty
, " %u", dnssl
->lifetime
);
2461 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2463 struct rtadv
*rtadv
= &zvrf
->rtadv
;
2465 if (IS_ZEBRA_DEBUG_EVENT
) {
2466 struct vrf
*vrf
= zvrf
->vrf
;
2468 zlog_debug("%s(%s) with event: %d and val: %d", __func__
,
2469 VRF_LOGNAME(vrf
), event
, val
);
2474 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2476 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2480 THREAD_OFF(rtadv
->ra_timer
);
2481 THREAD_OFF(rtadv
->ra_read
);
2484 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2487 case RTADV_TIMER_MSEC
:
2488 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2492 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2501 void rtadv_init(struct zebra_vrf
*zvrf
)
2503 if (vrf_is_backend_netns()) {
2504 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2505 zrouter
.rtadv_sock
= -1;
2507 zvrf
->rtadv
.sock
= -1;
2508 if (zrouter
.rtadv_sock
< 0)
2509 zrouter
.rtadv_sock
=
2510 rtadv_make_socket(zvrf
->zns
->ns_id
);
2514 void rtadv_vrf_terminate(struct zebra_vrf
*zvrf
)
2516 rtadv_event(zvrf
, RTADV_STOP
, 0);
2517 if (zvrf
->rtadv
.sock
>= 0) {
2518 close(zvrf
->rtadv
.sock
);
2519 zvrf
->rtadv
.sock
= -1;
2522 zvrf
->rtadv
.adv_if_count
= 0;
2523 zvrf
->rtadv
.adv_msec_if_count
= 0;
2526 void rtadv_terminate(void)
2528 if (zrouter
.rtadv_sock
>= 0) {
2529 close(zrouter
.rtadv_sock
);
2530 zrouter
.rtadv_sock
= -1;
2534 void rtadv_cmd_init(void)
2536 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2537 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2539 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2540 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2541 install_element(INTERFACE_NODE
, &ipv6_nd_ra_retrans_interval_cmd
);
2542 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_retrans_interval_cmd
);
2543 install_element(INTERFACE_NODE
, &ipv6_nd_ra_hop_limit_cmd
);
2544 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_hop_limit_cmd
);
2545 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2546 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2547 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2548 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2549 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2550 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2551 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2552 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2553 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2554 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2555 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2556 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2557 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2558 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2559 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2560 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2561 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2562 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2563 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2564 install_element(INTERFACE_NODE
,
2565 &ipv6_nd_adv_interval_config_option_cmd
);
2566 install_element(INTERFACE_NODE
,
2567 &no_ipv6_nd_adv_interval_config_option_cmd
);
2568 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2569 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2570 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2571 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2572 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2573 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2574 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2575 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2576 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2577 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2580 static int if_join_all_router(int sock
, struct interface
*ifp
)
2584 struct ipv6_mreq mreq
;
2586 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2587 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2588 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2590 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2593 flog_err_sys(EC_LIB_SOCKET
,
2594 "%s(%u): Failed to join group, socket %u error %s",
2595 ifp
->name
, ifp
->ifindex
, sock
,
2596 safe_strerror(errno
));
2598 if (IS_ZEBRA_DEBUG_EVENT
) {
2599 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
2602 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2603 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, sock
);
2609 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2613 struct ipv6_mreq mreq
;
2615 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2616 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2617 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2619 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2622 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
2626 "%s(%s:%u): Failed to leave group, socket %u error %s",
2627 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, sock
,
2628 safe_strerror(errno
));
2630 if (IS_ZEBRA_DEBUG_EVENT
) {
2631 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
2634 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
2635 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, sock
);
2641 void rtadv_init(struct zebra_vrf
*zvrf
)
2645 void rtadv_terminate(void)
2649 void rtadv_cmd_init(void)
2654 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
2659 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
2664 void rtadv_stop_ra(struct interface
*ifp
)
2669 void rtadv_stop_ra_all(void)
2675 * If the end user does not have RADV enabled we should
2676 * handle this better
2678 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
2680 if (IS_ZEBRA_DEBUG_PACKET
)
2682 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
2683 zserv_command_string(hdr
->command
));
2688 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
2690 if (IS_ZEBRA_DEBUG_PACKET
)
2692 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
2693 zserv_command_string(hdr
->command
));
2698 #endif /* HAVE_RTADV */