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
26 #include "zebra_memory.h"
38 #include "lib_errors.h"
40 #include "zebra/interface.h"
41 #include "zebra/rtadv.h"
42 #include "zebra/debug.h"
43 #include "zebra/rib.h"
44 #include "zebra/zapi_msg.h"
45 #include "zebra/zebra_vrf.h"
46 #include "zebra/zebra_errors.h"
47 #include "zebra/zebra_router.h"
49 extern struct zebra_privs_t zserv_privs
;
51 #if defined(HAVE_RTADV)
53 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_PREFIX
, "Router Advertisement Prefix")
56 #include <netinet/icmp6.h>
59 /* If RFC2133 definition is used. */
60 #ifndef IPV6_JOIN_GROUP
61 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
63 #ifndef IPV6_LEAVE_GROUP
64 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
67 #define ALLNODE "ff02::1"
68 #define ALLROUTER "ff02::2"
70 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS")
71 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL")
73 /* Order is intentional. Matches RFC4191. This array is also used for
74 command matching, so only modify with care. */
75 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
85 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
87 static int if_join_all_router(int, struct interface
*);
88 static int if_leave_all_router(int, struct interface
*);
90 static int rtadv_get_socket(struct zebra_vrf
*zvrf
)
92 if (zvrf
->rtadv
.sock
> 0)
93 return zvrf
->rtadv
.sock
;
94 return zrouter
.rtadv_sock
;
97 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
100 struct interface
*iface
;
101 struct zebra_if
*zif
;
103 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
104 if (iface
&& iface
->info
) {
112 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
113 int buflen
, struct sockaddr_in6
*from
,
114 ifindex_t
*ifindex
, int *hoplimit
)
119 struct cmsghdr
*cmsgptr
;
124 /* Fill in message and iovec. */
125 memset(&msg
, 0, sizeof(msg
));
126 msg
.msg_name
= (void *)from
;
127 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
130 msg
.msg_control
= (void *)adata
;
131 msg
.msg_controllen
= sizeof adata
;
133 iov
.iov_len
= buflen
;
135 /* If recvmsg fail return minus value. */
136 ret
= recvmsg(sock
, &msg
, 0);
140 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
141 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
142 /* I want interface index which this packet comes from. */
143 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
144 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
145 struct in6_pktinfo
*ptr
;
147 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
148 *ifindex
= ptr
->ipi6_ifindex
;
149 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
152 /* Incoming packet's hop limit. */
153 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
154 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
155 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
160 rtadv_increment_received(zvrf
, ifindex
);
164 #define RTADV_MSG_SIZE 4096
166 /* Send router advertisement packet. */
167 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
171 struct cmsghdr
*cmsgptr
;
172 struct in6_pktinfo
*pkt
;
173 struct sockaddr_in6 addr
;
174 static void *adata
= NULL
;
175 unsigned char buf
[RTADV_MSG_SIZE
];
176 struct nd_router_advert
*rtadv
;
179 struct zebra_if
*zif
;
180 struct rtadv_prefix
*rprefix
;
181 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
182 0, 0, 0, 0, 0, 0, 0, 1};
183 struct listnode
*node
;
184 uint16_t pkt_RouterLifetime
;
187 * Allocate control message bufffer. This is dynamic because
188 * CMSG_SPACE is not guaranteed not to call a function. Note that
189 * the size will be different on different architectures due to
190 * differing alignment rules.
193 /* XXX Free on shutdown. */
194 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
198 "rtadv_send_packet: can't malloc control data");
203 /* Logging of packet. */
204 if (IS_ZEBRA_DEBUG_PACKET
)
205 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
208 /* Fill in sockaddr_in6. */
209 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
210 addr
.sin6_family
= AF_INET6
;
212 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
213 #endif /* SIN6_LEN */
214 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
215 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
217 /* Fetch interface information. */
220 /* Make router advertisement message. */
221 rtadv
= (struct nd_router_advert
*)buf
;
223 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
224 rtadv
->nd_ra_code
= 0;
225 rtadv
->nd_ra_cksum
= 0;
227 rtadv
->nd_ra_curhoplimit
= 64;
229 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
230 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
232 : zif
->rtadv
.DefaultPreference
;
233 rtadv
->nd_ra_flags_reserved
<<= 3;
235 if (zif
->rtadv
.AdvManagedFlag
)
236 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
237 if (zif
->rtadv
.AdvOtherConfigFlag
)
238 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
239 if (zif
->rtadv
.AdvHomeAgentFlag
)
240 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
241 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
242 * AdvDefaultLifetime is by default based on the value of
243 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
244 * field of Router Advertisements. Given that this field is expressed
245 * in seconds, a small MaxRtrAdvInterval value can result in a zero
246 * value for this field. To prevent this, routers SHOULD keep
247 * AdvDefaultLifetime in at least one second, even if the use of
248 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
250 zif
->rtadv
.AdvDefaultLifetime
!= -1
251 ? zif
->rtadv
.AdvDefaultLifetime
252 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
253 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
254 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
255 rtadv
->nd_ra_retransmit
= htonl(0);
257 len
= sizeof(struct nd_router_advert
);
259 /* If both the Home Agent Preference and Home Agent Lifetime are set to
260 * their default values specified above, this option SHOULD NOT be
261 * included in the Router Advertisement messages sent by this home
262 * agent. -- RFC6275, 7.4 */
263 if (zif
->rtadv
.AdvHomeAgentFlag
264 && (zif
->rtadv
.HomeAgentPreference
265 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
266 struct nd_opt_homeagent_info
*ndopt_hai
=
267 (struct nd_opt_homeagent_info
*)(buf
+ len
);
268 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
269 ndopt_hai
->nd_opt_hai_len
= 1;
270 ndopt_hai
->nd_opt_hai_reserved
= 0;
271 ndopt_hai
->nd_opt_hai_preference
=
272 htons(zif
->rtadv
.HomeAgentPreference
);
273 /* 16-bit unsigned integer. The lifetime associated with the
275 * agent in units of seconds. The default value is the same as
277 * Router Lifetime, as specified in the main body of the Router
278 * Advertisement. The maximum value corresponds to 18.2 hours.
280 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
281 ndopt_hai
->nd_opt_hai_lifetime
=
282 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
283 ? zif
->rtadv
.HomeAgentLifetime
284 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
289 len
+= sizeof(struct nd_opt_homeagent_info
);
292 if (zif
->rtadv
.AdvIntervalOption
) {
293 struct nd_opt_adv_interval
*ndopt_adv
=
294 (struct nd_opt_adv_interval
*)(buf
+ len
);
295 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
296 ndopt_adv
->nd_opt_ai_len
= 1;
297 ndopt_adv
->nd_opt_ai_reserved
= 0;
298 ndopt_adv
->nd_opt_ai_interval
=
299 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
300 len
+= sizeof(struct nd_opt_adv_interval
);
303 /* Fill in prefix. */
304 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
305 struct nd_opt_prefix_info
*pinfo
;
307 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
309 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
310 pinfo
->nd_opt_pi_len
= 4;
311 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
313 pinfo
->nd_opt_pi_flags_reserved
= 0;
314 if (rprefix
->AdvOnLinkFlag
)
315 pinfo
->nd_opt_pi_flags_reserved
|=
316 ND_OPT_PI_FLAG_ONLINK
;
317 if (rprefix
->AdvAutonomousFlag
)
318 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
319 if (rprefix
->AdvRouterAddressFlag
)
320 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
322 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
323 pinfo
->nd_opt_pi_preferred_time
=
324 htonl(rprefix
->AdvPreferredLifetime
);
325 pinfo
->nd_opt_pi_reserved2
= 0;
327 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
328 &rprefix
->prefix
.prefix
);
332 uint8_t buf
[INET6_ADDRSTRLEN
];
334 zlog_debug("DEBUG %s",
335 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
336 buf
, INET6_ADDRSTRLEN
));
340 len
+= sizeof(struct nd_opt_prefix_info
);
343 /* Hardware address. */
344 if (ifp
->hw_addr_len
!= 0) {
345 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
347 /* Option length should be rounded up to next octet if
348 the link address does not end on an octet boundary. */
349 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
351 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
352 len
+= ifp
->hw_addr_len
;
354 /* Pad option to end on an octet boundary. */
355 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
356 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
360 if (zif
->rtadv
.AdvLinkMTU
) {
361 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
362 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
363 opt
->nd_opt_mtu_len
= 1;
364 opt
->nd_opt_mtu_reserved
= 0;
365 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
366 len
+= sizeof(struct nd_opt_mtu
);
370 * There is no limit on the number of configurable recursive DNS
371 * servers or search list entries. We don't want the RA message
372 * to exceed the link's MTU (risking fragmentation) or even
373 * blow the stack buffer allocated for it.
375 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
377 /* Recursive DNS servers */
378 struct rtadv_rdnss
*rdnss
;
380 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
382 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
384 if (len
+ opt_len
> max_len
) {
386 "%s(%u): Tx RA: RDNSS option would exceed MTU, omitting it",
387 ifp
->name
, ifp
->ifindex
);
390 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
392 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
393 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
394 opt
->nd_opt_rdnss_reserved
= 0;
395 opt
->nd_opt_rdnss_lifetime
= htonl(
398 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
400 len
+= sizeof(struct nd_opt_rdnss
);
402 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
403 len
+= sizeof(struct in6_addr
);
406 /* DNS search list */
407 struct rtadv_dnssl
*dnssl
;
409 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
410 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
411 + ((dnssl
->encoded_len
+ 7) & ~7);
413 if (len
+ opt_len
> max_len
) {
415 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
416 ifp
->name
, ifp
->ifindex
);
419 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
421 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
422 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
423 opt
->nd_opt_dnssl_reserved
= 0;
424 opt
->nd_opt_dnssl_lifetime
= htonl(
427 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
429 len
+= sizeof(struct nd_opt_dnssl
);
431 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
432 len
+= dnssl
->encoded_len
;
434 /* Zero-pad to 8-octet boundary */
441 msg
.msg_name
= (void *)&addr
;
442 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
445 msg
.msg_control
= (void *)adata
;
446 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
451 cmsgptr
= CMSG_FIRSTHDR(&msg
);
452 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
453 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
454 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
456 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
457 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
458 pkt
->ipi6_ifindex
= ifp
->ifindex
;
460 ret
= sendmsg(sock
, &msg
, 0);
462 flog_err_sys(EC_LIB_SOCKET
,
463 "%s(%u): Tx RA failed, socket %u error %d (%s)",
464 ifp
->name
, ifp
->ifindex
, sock
, errno
,
465 safe_strerror(errno
));
470 static int rtadv_timer(struct thread
*thread
)
472 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
474 struct interface
*ifp
;
475 struct zebra_if
*zif
;
478 zvrf
->rtadv
.ra_timer
= NULL
;
479 if (zvrf
->rtadv
.adv_msec_if_count
== 0) {
480 period
= 1000; /* 1 s */
481 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
483 period
= 10; /* 10 ms */
484 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
487 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
488 FOR_ALL_INTERFACES (vrf
, ifp
) {
489 if (if_is_loopback(ifp
)
490 || CHECK_FLAG(ifp
->status
,
491 ZEBRA_INTERFACE_VRF_LOOPBACK
)
492 || !if_is_operative(ifp
))
497 if (zif
->rtadv
.AdvSendAdvertisements
) {
498 if (zif
->rtadv
.inFastRexmit
499 && zif
->rtadv
.UseFastRexmit
) {
500 /* We assume we fast rexmit every sec so
503 if (--zif
->rtadv
.NumFastReXmitsRemain
505 zif
->rtadv
.inFastRexmit
= 0;
507 if (IS_ZEBRA_DEBUG_SEND
)
509 "Fast RA Rexmit on interface %s",
512 rtadv_send_packet(rtadv_get_socket(zvrf
),
515 zif
->rtadv
.AdvIntervalTimer
-= period
;
516 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
518 MaxRtrAdvInterval each
519 time isn't what section
520 6.2.4 of RFC4861 tells to do.
522 zif
->rtadv
.AdvIntervalTimer
=
526 rtadv_get_socket(zvrf
),
536 static void rtadv_process_solicit(struct interface
*ifp
)
538 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
539 struct zebra_if
*zif
;
545 * If FastRetransmit is enabled, send the RA immediately.
546 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
547 * (3 seconds) since the last RA was sent, send it now and reset
548 * the timer to start at the max (configured) again.
549 * If not enabled and it is less than 3 seconds since the last
550 * RA packet was sent, set the timer for 3 seconds so the next
551 * one will be sent with a minimum of 3 seconds between RAs.
554 if ((zif
->rtadv
.UseFastRexmit
)
555 || (zif
->rtadv
.AdvIntervalTimer
<=
556 (zif
->rtadv
.MaxRtrAdvInterval
- MIN_DELAY_BETWEEN_RAS
))) {
557 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
);
558 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
560 zif
->rtadv
.AdvIntervalTimer
= MIN_DELAY_BETWEEN_RAS
;
564 * This function processes optional attributes off of
565 * end of a RA packet received. At this point in
566 * time we only care about this in one situation
567 * which is when a interface does not have a LL
568 * v6 address. We still need to be able to install
569 * the mac address for v4 to v6 resolution
571 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
572 struct interface
*ifp
,
573 struct sockaddr_in6
*addr
)
578 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
580 switch(opt_hdr
->nd_opt_type
) {
581 case ND_OPT_SOURCE_LINKADDR
:
582 mac
= (char *)(optional
+2);
583 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
584 &addr
->sin6_addr
, 1);
590 len
-= 8 * opt_hdr
->nd_opt_len
;
591 optional
+= 8 * opt_hdr
->nd_opt_len
;
595 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
596 struct interface
*ifp
,
597 struct sockaddr_in6
*addr
)
599 struct nd_router_advert
*radvert
;
600 char addr_str
[INET6_ADDRSTRLEN
];
601 struct zebra_if
*zif
;
606 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
608 if (len
< sizeof(struct nd_router_advert
)) {
609 if (IS_ZEBRA_DEBUG_PACKET
)
610 zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
611 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
615 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
616 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
617 len
- sizeof(struct nd_router_advert
),
619 if (IS_ZEBRA_DEBUG_PACKET
)
620 zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s",
621 ifp
->name
, ifp
->ifindex
, addr_str
);
625 radvert
= (struct nd_router_advert
*)msg
;
627 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
628 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
630 EC_ZEBRA_RA_PARAM_MISMATCH
,
631 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
632 ifp
->name
, ifp
->ifindex
, addr_str
);
635 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
636 && !zif
->rtadv
.AdvManagedFlag
) {
638 EC_ZEBRA_RA_PARAM_MISMATCH
,
639 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
640 ifp
->name
, ifp
->ifindex
, addr_str
);
643 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
644 && !zif
->rtadv
.AdvOtherConfigFlag
) {
646 EC_ZEBRA_RA_PARAM_MISMATCH
,
647 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
648 ifp
->name
, ifp
->ifindex
, addr_str
);
651 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
652 && (ntohl(radvert
->nd_ra_reachable
)
653 != zif
->rtadv
.AdvReachableTime
)) {
655 EC_ZEBRA_RA_PARAM_MISMATCH
,
656 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
657 ifp
->name
, ifp
->ifindex
, addr_str
);
660 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
661 && (ntohl(radvert
->nd_ra_retransmit
)
662 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
664 EC_ZEBRA_RA_PARAM_MISMATCH
,
665 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
666 ifp
->name
, ifp
->ifindex
, addr_str
);
669 /* Create entry for neighbor if not known. */
671 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
672 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
674 if (!nbr_connected_check(ifp
, &p
))
675 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
679 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
680 ifindex_t ifindex
, int hoplimit
,
681 struct sockaddr_in6
*from
,
682 struct zebra_vrf
*zvrf
)
684 struct icmp6_hdr
*icmph
;
685 struct interface
*ifp
;
686 struct zebra_if
*zif
;
687 char addr_str
[INET6_ADDRSTRLEN
];
689 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
691 /* Interface search. */
692 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
694 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
695 "RA/RS received on unknown IF %u from %s", ifindex
,
700 if (IS_ZEBRA_DEBUG_PACKET
)
701 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
702 ifp
->ifindex
, len
, addr_str
);
704 if (if_is_loopback(ifp
)
705 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
708 /* Check interface configuration. */
710 if (!zif
->rtadv
.AdvSendAdvertisements
)
713 /* ICMP message length check. */
714 if (len
< sizeof(struct icmp6_hdr
)) {
715 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
716 ifp
->name
, ifp
->ifindex
, len
);
720 icmph
= (struct icmp6_hdr
*)buf
;
722 /* ICMP message type check. */
723 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
724 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
725 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
726 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
730 /* Hoplimit check. */
731 if (hoplimit
>= 0 && hoplimit
!= 255) {
732 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
733 ifp
->ifindex
, hoplimit
);
737 /* Check ICMP message type. */
738 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
739 rtadv_process_solicit(ifp
);
740 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
741 rtadv_process_advert(buf
, len
, ifp
, from
);
746 static int rtadv_read(struct thread
*thread
)
750 uint8_t buf
[RTADV_MSG_SIZE
];
751 struct sockaddr_in6 from
;
752 ifindex_t ifindex
= 0;
754 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
756 sock
= THREAD_FD(thread
);
757 zvrf
->rtadv
.ra_read
= NULL
;
759 /* Register myself. */
760 rtadv_event(zvrf
, RTADV_READ
, sock
);
762 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
766 flog_err_sys(EC_LIB_SOCKET
,
767 "RA/RS recv failed, socket %u error %s", sock
,
768 safe_strerror(errno
));
772 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
777 static int rtadv_make_socket(ns_id_t ns_id
)
781 struct icmp6_filter filter
;
783 frr_with_privs(&zserv_privs
) {
785 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
793 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
798 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
803 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
808 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
813 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
819 ICMP6_FILTER_SETBLOCKALL(&filter
);
820 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
821 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
823 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
824 sizeof(struct icmp6_filter
));
826 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
834 static struct rtadv_prefix
*rtadv_prefix_new(void)
836 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
839 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
841 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
844 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
845 struct prefix_ipv6
*p
)
847 struct listnode
*node
;
848 struct rtadv_prefix
*rprefix
;
850 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
851 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
857 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
858 struct prefix_ipv6
*p
)
860 struct rtadv_prefix
*rprefix
;
862 rprefix
= rtadv_prefix_lookup(rplist
, p
);
866 rprefix
= rtadv_prefix_new();
867 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
868 listnode_add(rplist
, rprefix
);
873 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
875 struct rtadv_prefix
*rprefix
;
877 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
879 /* Set parameters. */
880 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
881 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
882 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
883 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
884 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
887 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
889 struct rtadv_prefix
*rprefix
;
891 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
892 if (rprefix
!= NULL
) {
893 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
894 rtadv_prefix_free(rprefix
);
900 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
901 ipv6_nd_suppress_ra_status status
)
903 struct zebra_if
*zif
;
904 struct zebra_vrf
*zvrf
;
907 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
909 if (status
== RA_SUPPRESS
) {
910 /* RA is currently enabled */
911 if (zif
->rtadv
.AdvSendAdvertisements
) {
912 zif
->rtadv
.AdvSendAdvertisements
= 0;
913 zif
->rtadv
.AdvIntervalTimer
= 0;
914 zvrf
->rtadv
.adv_if_count
--;
916 if_leave_all_router(rtadv_get_socket(zvrf
), ifp
);
918 if (zvrf
->rtadv
.adv_if_count
== 0)
919 rtadv_event(zvrf
, RTADV_STOP
, 0);
922 if (!zif
->rtadv
.AdvSendAdvertisements
) {
923 zif
->rtadv
.AdvSendAdvertisements
= 1;
924 zif
->rtadv
.AdvIntervalTimer
= 0;
925 zvrf
->rtadv
.adv_if_count
++;
927 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
928 && zif
->rtadv
.UseFastRexmit
) {
930 * Enable Fast RA only when RA interval is in
931 * secs and Fast RA retransmit is enabled
933 zif
->rtadv
.inFastRexmit
= 1;
934 zif
->rtadv
.NumFastReXmitsRemain
=
935 RTADV_NUM_FAST_REXMITS
;
938 if_join_all_router(rtadv_get_socket(zvrf
), ifp
);
940 if (zvrf
->rtadv
.adv_if_count
== 1)
941 rtadv_event(zvrf
, RTADV_START
,
942 rtadv_get_socket(zvrf
));
948 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
949 * Note that while the client could request RA on an interface on which the
950 * operator has not enabled RA, RA won't be disabled upon client request
951 * if the operator has explicitly enabled RA. The enable request can also
952 * specify a RA interval (in seconds).
954 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
958 struct interface
*ifp
;
959 struct zebra_if
*zif
;
964 /* Get interface index and RA interval. */
965 STREAM_GETL(s
, ifindex
);
966 STREAM_GETL(s
, ra_interval
);
968 if (IS_ZEBRA_DEBUG_EVENT
)
969 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
970 zvrf_id(zvrf
), ifindex
,
971 enable
? "enable" : "disable",
972 zebra_route_string(client
->proto
), ra_interval
);
974 /* Locate interface and check VRF match. */
975 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
977 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
978 "%u: IF %u RA %s client %s - interface unknown",
979 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
980 zebra_route_string(client
->proto
));
983 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
985 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
986 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
987 zebra_route_string(client
->proto
), ifp
->vrf_id
);
993 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
994 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
996 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
997 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
998 VTY_RA_INTERVAL_CONFIGURED
))
999 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1001 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1002 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1003 VTY_RA_INTERVAL_CONFIGURED
))
1004 zif
->rtadv
.MaxRtrAdvInterval
=
1005 RTADV_MAX_RTR_ADV_INTERVAL
;
1006 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1007 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1013 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1015 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1017 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1019 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1022 DEFUN (ipv6_nd_ra_fast_retrans
,
1023 ipv6_nd_ra_fast_retrans_cmd
,
1024 "ipv6 nd ra-fast-retrans",
1025 "Interface IPv6 config commands\n"
1026 "Neighbor discovery\n"
1027 "Fast retransmit of RA packets\n")
1029 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1030 struct zebra_if
*zif
= ifp
->info
;
1032 if (if_is_loopback(ifp
)
1033 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1035 "Cannot configure IPv6 Router Advertisements on this interface\n");
1036 return CMD_WARNING_CONFIG_FAILED
;
1039 zif
->rtadv
.UseFastRexmit
= true;
1044 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1045 no_ipv6_nd_ra_fast_retrans_cmd
,
1046 "no ipv6 nd ra-fast-retrans",
1048 "Interface IPv6 config commands\n"
1049 "Neighbor discovery\n"
1050 "Fast retransmit of RA packets\n")
1052 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1053 struct zebra_if
*zif
= ifp
->info
;
1055 if (if_is_loopback(ifp
)
1056 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1058 "Cannot configure IPv6 Router Advertisements on this interface\n");
1059 return CMD_WARNING_CONFIG_FAILED
;
1062 zif
->rtadv
.UseFastRexmit
= false;
1067 DEFUN (ipv6_nd_suppress_ra
,
1068 ipv6_nd_suppress_ra_cmd
,
1069 "ipv6 nd suppress-ra",
1070 "Interface IPv6 config commands\n"
1071 "Neighbor discovery\n"
1072 "Suppress Router Advertisement\n")
1074 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1075 struct zebra_if
*zif
= ifp
->info
;
1077 if (if_is_loopback(ifp
)
1078 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1080 "Cannot configure IPv6 Router Advertisements on this interface\n");
1081 return CMD_WARNING_CONFIG_FAILED
;
1084 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1085 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1087 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1091 DEFUN (no_ipv6_nd_suppress_ra
,
1092 no_ipv6_nd_suppress_ra_cmd
,
1093 "no ipv6 nd suppress-ra",
1095 "Interface IPv6 config commands\n"
1096 "Neighbor discovery\n"
1097 "Suppress Router Advertisement\n")
1099 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1100 struct zebra_if
*zif
= ifp
->info
;
1102 if (if_is_loopback(ifp
)
1103 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1105 "Cannot configure IPv6 Router Advertisements on this interface\n");
1106 return CMD_WARNING_CONFIG_FAILED
;
1109 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1110 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1114 DEFUN (ipv6_nd_ra_interval_msec
,
1115 ipv6_nd_ra_interval_msec_cmd
,
1116 "ipv6 nd ra-interval msec (70-1800000)",
1117 "Interface IPv6 config commands\n"
1118 "Neighbor discovery\n"
1119 "Router Advertisement interval\n"
1120 "Router Advertisement interval in milliseconds\n"
1121 "Router Advertisement interval in milliseconds\n")
1124 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1126 struct zebra_if
*zif
= ifp
->info
;
1127 struct zebra_vrf
*zvrf
;
1129 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1131 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1132 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1133 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1135 "This ra-interval would conflict with configured ra-lifetime!\n");
1136 return CMD_WARNING_CONFIG_FAILED
;
1139 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1140 zvrf
->rtadv
.adv_msec_if_count
--;
1142 if (interval
% 1000)
1143 zvrf
->rtadv
.adv_msec_if_count
++;
1145 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1146 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1147 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1148 zif
->rtadv
.AdvIntervalTimer
= 0;
1153 DEFUN (ipv6_nd_ra_interval
,
1154 ipv6_nd_ra_interval_cmd
,
1155 "ipv6 nd ra-interval (1-1800)",
1156 "Interface IPv6 config commands\n"
1157 "Neighbor discovery\n"
1158 "Router Advertisement interval\n"
1159 "Router Advertisement interval in seconds\n")
1162 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1164 struct zebra_if
*zif
= ifp
->info
;
1165 struct zebra_vrf
*zvrf
;
1167 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1169 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1170 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1171 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1173 "This ra-interval would conflict with configured ra-lifetime!\n");
1174 return CMD_WARNING_CONFIG_FAILED
;
1177 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1178 zvrf
->rtadv
.adv_msec_if_count
--;
1180 /* convert to milliseconds */
1181 interval
= interval
* 1000;
1183 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1184 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1185 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1186 zif
->rtadv
.AdvIntervalTimer
= 0;
1191 DEFUN (no_ipv6_nd_ra_interval
,
1192 no_ipv6_nd_ra_interval_cmd
,
1193 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1195 "Interface IPv6 config commands\n"
1196 "Neighbor discovery\n"
1197 "Router Advertisement interval\n"
1198 "Router Advertisement interval in seconds\n"
1199 "Specify millisecond router advertisement interval\n"
1200 "Router Advertisement interval in milliseconds\n")
1202 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1203 struct zebra_if
*zif
= ifp
->info
;
1204 struct zebra_vrf
*zvrf
= NULL
;
1206 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1208 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1209 zvrf
->rtadv
.adv_msec_if_count
--;
1211 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1213 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1214 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1216 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1218 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1219 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1224 DEFUN (ipv6_nd_ra_lifetime
,
1225 ipv6_nd_ra_lifetime_cmd
,
1226 "ipv6 nd ra-lifetime (0-9000)",
1227 "Interface IPv6 config commands\n"
1228 "Neighbor discovery\n"
1230 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1233 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1234 struct zebra_if
*zif
= ifp
->info
;
1237 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1239 /* The value to be placed in the Router Lifetime field
1240 * of Router Advertisements sent from the interface,
1241 * in seconds. MUST be either zero or between
1242 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1243 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1245 "This ra-lifetime would conflict with configured ra-interval\n");
1246 return CMD_WARNING_CONFIG_FAILED
;
1249 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1254 DEFUN (no_ipv6_nd_ra_lifetime
,
1255 no_ipv6_nd_ra_lifetime_cmd
,
1256 "no ipv6 nd ra-lifetime [(0-9000)]",
1258 "Interface IPv6 config commands\n"
1259 "Neighbor discovery\n"
1261 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1263 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1264 struct zebra_if
*zif
= ifp
->info
;
1266 zif
->rtadv
.AdvDefaultLifetime
= -1;
1271 DEFUN (ipv6_nd_reachable_time
,
1272 ipv6_nd_reachable_time_cmd
,
1273 "ipv6 nd reachable-time (1-3600000)",
1274 "Interface IPv6 config commands\n"
1275 "Neighbor discovery\n"
1277 "Reachable time in milliseconds\n")
1280 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1281 struct zebra_if
*zif
= ifp
->info
;
1282 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1286 DEFUN (no_ipv6_nd_reachable_time
,
1287 no_ipv6_nd_reachable_time_cmd
,
1288 "no ipv6 nd reachable-time [(1-3600000)]",
1290 "Interface IPv6 config commands\n"
1291 "Neighbor discovery\n"
1293 "Reachable time in milliseconds\n")
1295 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1296 struct zebra_if
*zif
= ifp
->info
;
1298 zif
->rtadv
.AdvReachableTime
= 0;
1303 DEFUN (ipv6_nd_homeagent_preference
,
1304 ipv6_nd_homeagent_preference_cmd
,
1305 "ipv6 nd home-agent-preference (0-65535)",
1306 "Interface IPv6 config commands\n"
1307 "Neighbor discovery\n"
1308 "Home Agent preference\n"
1309 "preference value (default is 0, least preferred)\n")
1312 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1313 struct zebra_if
*zif
= ifp
->info
;
1314 zif
->rtadv
.HomeAgentPreference
=
1315 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1319 DEFUN (no_ipv6_nd_homeagent_preference
,
1320 no_ipv6_nd_homeagent_preference_cmd
,
1321 "no ipv6 nd home-agent-preference [(0-65535)]",
1323 "Interface IPv6 config commands\n"
1324 "Neighbor discovery\n"
1325 "Home Agent preference\n"
1326 "preference value (default is 0, least preferred)\n")
1328 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1329 struct zebra_if
*zif
= ifp
->info
;
1331 zif
->rtadv
.HomeAgentPreference
= 0;
1336 DEFUN (ipv6_nd_homeagent_lifetime
,
1337 ipv6_nd_homeagent_lifetime_cmd
,
1338 "ipv6 nd home-agent-lifetime (0-65520)",
1339 "Interface IPv6 config commands\n"
1340 "Neighbor discovery\n"
1341 "Home Agent lifetime\n"
1342 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1345 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1346 struct zebra_if
*zif
= ifp
->info
;
1347 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1351 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1352 no_ipv6_nd_homeagent_lifetime_cmd
,
1353 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1355 "Interface IPv6 config commands\n"
1356 "Neighbor discovery\n"
1357 "Home Agent lifetime\n"
1358 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1360 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1361 struct zebra_if
*zif
= ifp
->info
;
1363 zif
->rtadv
.HomeAgentLifetime
= -1;
1368 DEFUN (ipv6_nd_managed_config_flag
,
1369 ipv6_nd_managed_config_flag_cmd
,
1370 "ipv6 nd managed-config-flag",
1371 "Interface IPv6 config commands\n"
1372 "Neighbor discovery\n"
1373 "Managed address configuration flag\n")
1375 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1376 struct zebra_if
*zif
= ifp
->info
;
1378 zif
->rtadv
.AdvManagedFlag
= 1;
1383 DEFUN (no_ipv6_nd_managed_config_flag
,
1384 no_ipv6_nd_managed_config_flag_cmd
,
1385 "no ipv6 nd managed-config-flag",
1387 "Interface IPv6 config commands\n"
1388 "Neighbor discovery\n"
1389 "Managed address configuration flag\n")
1391 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1392 struct zebra_if
*zif
= ifp
->info
;
1394 zif
->rtadv
.AdvManagedFlag
= 0;
1399 DEFUN (ipv6_nd_homeagent_config_flag
,
1400 ipv6_nd_homeagent_config_flag_cmd
,
1401 "ipv6 nd home-agent-config-flag",
1402 "Interface IPv6 config commands\n"
1403 "Neighbor discovery\n"
1404 "Home Agent configuration flag\n")
1406 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1407 struct zebra_if
*zif
= ifp
->info
;
1409 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1414 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1415 no_ipv6_nd_homeagent_config_flag_cmd
,
1416 "no ipv6 nd home-agent-config-flag",
1418 "Interface IPv6 config commands\n"
1419 "Neighbor discovery\n"
1420 "Home Agent configuration flag\n")
1422 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1423 struct zebra_if
*zif
= ifp
->info
;
1425 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1430 DEFUN (ipv6_nd_adv_interval_config_option
,
1431 ipv6_nd_adv_interval_config_option_cmd
,
1432 "ipv6 nd adv-interval-option",
1433 "Interface IPv6 config commands\n"
1434 "Neighbor discovery\n"
1435 "Advertisement Interval Option\n")
1437 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1438 struct zebra_if
*zif
= ifp
->info
;
1440 zif
->rtadv
.AdvIntervalOption
= 1;
1445 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1446 no_ipv6_nd_adv_interval_config_option_cmd
,
1447 "no ipv6 nd adv-interval-option",
1449 "Interface IPv6 config commands\n"
1450 "Neighbor discovery\n"
1451 "Advertisement Interval Option\n")
1453 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1454 struct zebra_if
*zif
= ifp
->info
;
1456 zif
->rtadv
.AdvIntervalOption
= 0;
1461 DEFUN (ipv6_nd_other_config_flag
,
1462 ipv6_nd_other_config_flag_cmd
,
1463 "ipv6 nd other-config-flag",
1464 "Interface IPv6 config commands\n"
1465 "Neighbor discovery\n"
1466 "Other statefull configuration flag\n")
1468 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1469 struct zebra_if
*zif
= ifp
->info
;
1471 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1476 DEFUN (no_ipv6_nd_other_config_flag
,
1477 no_ipv6_nd_other_config_flag_cmd
,
1478 "no ipv6 nd other-config-flag",
1480 "Interface IPv6 config commands\n"
1481 "Neighbor discovery\n"
1482 "Other statefull configuration flag\n")
1484 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1485 struct zebra_if
*zif
= ifp
->info
;
1487 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1492 DEFUN (ipv6_nd_prefix
,
1494 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1495 "Interface IPv6 config commands\n"
1496 "Neighbor discovery\n"
1497 "Prefix information\n"
1499 "Valid lifetime in seconds\n"
1500 "Infinite valid lifetime\n"
1501 "Preferred lifetime in seconds\n"
1502 "Infinite preferred lifetime\n"
1503 "Set Router Address flag\n"
1504 "Do not use prefix for onlink determination\n"
1505 "Do not use prefix for autoconfiguration\n"
1506 "Do not use prefix for autoconfiguration\n"
1507 "Do not use prefix for onlink determination\n")
1510 char *prefix
= argv
[3]->arg
;
1511 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1512 || strmatch(argv
[4]->text
, "infinite"));
1513 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1515 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1517 char *lifetime
= NULL
, *preflifetime
= NULL
;
1518 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1520 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1522 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1527 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1529 offlink
= (argc
> idx_routeropts
+ 1
1530 || strmatch(argv
[idx_routeropts
]->text
,
1532 noautoconf
= (argc
> idx_routeropts
+ 1
1533 || strmatch(argv
[idx_routeropts
]->text
,
1539 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1540 struct zebra_if
*zebra_if
= ifp
->info
;
1542 struct rtadv_prefix rp
;
1544 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1546 vty_out(vty
, "Malformed IPv6 prefix\n");
1547 return CMD_WARNING_CONFIG_FAILED
;
1549 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1550 rp
.AdvOnLinkFlag
= !offlink
;
1551 rp
.AdvAutonomousFlag
= !noautoconf
;
1552 rp
.AdvRouterAddressFlag
= routeraddr
;
1553 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1554 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1557 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1559 : strtoll(lifetime
, NULL
, 10);
1560 rp
.AdvPreferredLifetime
=
1561 strmatch(preflifetime
, "infinite")
1563 : strtoll(preflifetime
, NULL
, 10);
1564 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1565 vty_out(vty
, "Invalid preferred lifetime\n");
1566 return CMD_WARNING_CONFIG_FAILED
;
1570 rtadv_prefix_set(zebra_if
, &rp
);
1575 DEFUN (no_ipv6_nd_prefix
,
1576 no_ipv6_nd_prefix_cmd
,
1577 "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]>]",
1579 "Interface IPv6 config commands\n"
1580 "Neighbor discovery\n"
1581 "Prefix information\n"
1583 "Valid lifetime in seconds\n"
1584 "Infinite valid lifetime\n"
1585 "Preferred lifetime in seconds\n"
1586 "Infinite preferred lifetime\n"
1587 "Set Router Address flag\n"
1588 "Do not use prefix for onlink determination\n"
1589 "Do not use prefix for autoconfiguration\n"
1590 "Do not use prefix for autoconfiguration\n"
1591 "Do not use prefix for onlink determination\n")
1593 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1594 struct zebra_if
*zebra_if
= ifp
->info
;
1596 struct rtadv_prefix rp
;
1597 char *prefix
= argv
[4]->arg
;
1599 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1601 vty_out(vty
, "Malformed IPv6 prefix\n");
1602 return CMD_WARNING_CONFIG_FAILED
;
1604 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1606 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1608 vty_out(vty
, "Non-existant IPv6 prefix\n");
1609 return CMD_WARNING_CONFIG_FAILED
;
1615 DEFUN (ipv6_nd_router_preference
,
1616 ipv6_nd_router_preference_cmd
,
1617 "ipv6 nd router-preference <high|medium|low>",
1618 "Interface IPv6 config commands\n"
1619 "Neighbor discovery\n"
1620 "Default router preference\n"
1621 "High default router preference\n"
1622 "Medium default router preference (default)\n"
1623 "Low default router preference\n")
1625 int idx_high_medium_low
= 3;
1626 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1627 struct zebra_if
*zif
= ifp
->info
;
1630 while (0 != rtadv_pref_strs
[i
]) {
1631 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1634 zif
->rtadv
.DefaultPreference
= i
;
1640 return CMD_ERR_NO_MATCH
;
1643 DEFUN (no_ipv6_nd_router_preference
,
1644 no_ipv6_nd_router_preference_cmd
,
1645 "no ipv6 nd router-preference [<high|medium|low>]",
1647 "Interface IPv6 config commands\n"
1648 "Neighbor discovery\n"
1649 "Default router preference\n"
1650 "High default router preference\n"
1651 "Medium default router preference (default)\n"
1652 "Low default router preference\n")
1654 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1655 struct zebra_if
*zif
= ifp
->info
;
1657 zif
->rtadv
.DefaultPreference
=
1658 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1665 "ipv6 nd mtu (1-65535)",
1666 "Interface IPv6 config commands\n"
1667 "Neighbor discovery\n"
1672 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1673 struct zebra_if
*zif
= ifp
->info
;
1674 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1678 DEFUN (no_ipv6_nd_mtu
,
1680 "no ipv6 nd mtu [(1-65535)]",
1682 "Interface IPv6 config commands\n"
1683 "Neighbor discovery\n"
1687 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1688 struct zebra_if
*zif
= ifp
->info
;
1689 zif
->rtadv
.AdvLinkMTU
= 0;
1693 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
1695 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
1698 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
1700 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
1703 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
1704 struct rtadv_rdnss
*rdnss
)
1706 struct listnode
*node
;
1707 struct rtadv_rdnss
*p
;
1709 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1710 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
1715 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
1716 struct rtadv_rdnss
*rdnss
)
1718 struct rtadv_rdnss
*p
;
1720 p
= rtadv_rdnss_lookup(list
, rdnss
);
1724 p
= rtadv_rdnss_new();
1725 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
1726 listnode_add(list
, p
);
1731 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1733 struct rtadv_rdnss
*p
;
1735 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1736 p
->lifetime
= rdnss
->lifetime
;
1737 p
->lifetime_set
= rdnss
->lifetime_set
;
1740 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1742 struct rtadv_rdnss
*p
;
1744 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1746 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
1747 rtadv_rdnss_free(p
);
1754 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
1756 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
1759 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
1761 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
1764 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
1765 struct rtadv_dnssl
*dnssl
)
1767 struct listnode
*node
;
1768 struct rtadv_dnssl
*p
;
1770 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1771 if (!strcasecmp(p
->name
, dnssl
->name
))
1776 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
1777 struct rtadv_dnssl
*dnssl
)
1779 struct rtadv_dnssl
*p
;
1781 p
= rtadv_dnssl_lookup(list
, dnssl
);
1785 p
= rtadv_dnssl_new();
1786 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1787 listnode_add(list
, p
);
1792 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1794 struct rtadv_dnssl
*p
;
1796 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1797 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1800 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1802 struct rtadv_dnssl
*p
;
1804 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1806 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
1807 rtadv_dnssl_free(p
);
1815 * Convert dotted domain name (with or without trailing root zone dot) to
1816 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
1817 * to strlen(in) + 2 octets to out.
1819 * Returns the number of octets written to out or -1 if in does not constitute
1820 * a valid domain name.
1822 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
1824 const char *label_start
, *label_end
;
1830 while (*label_start
) {
1833 label_end
= strchr(label_start
, '.');
1834 if (label_end
== NULL
)
1835 label_end
= label_start
+ strlen(label_start
);
1837 label_len
= label_end
- label_start
;
1838 if (label_len
>= 64)
1839 return -1; /* labels must be 63 octets or less */
1841 out
[outp
++] = (uint8_t)label_len
;
1842 memcpy(out
+ outp
, label_start
, label_len
);
1844 label_start
+= label_len
;
1845 if (*label_start
== '.')
1853 DEFUN(ipv6_nd_rdnss
,
1855 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1856 "Interface IPv6 config commands\n"
1857 "Neighbor discovery\n"
1858 "Recursive DNS server information\n"
1860 "Valid lifetime in seconds\n"
1861 "Infinite valid lifetime\n")
1863 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1864 struct zebra_if
*zif
= ifp
->info
;
1865 struct rtadv_rdnss rdnss
= {};
1867 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
1868 vty_out(vty
, "Malformed IPv6 address\n");
1869 return CMD_WARNING_CONFIG_FAILED
;
1872 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1874 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
1876 : strtoll(lifetime
, NULL
, 10);
1877 rdnss
.lifetime_set
= 1;
1880 rtadv_rdnss_set(zif
, &rdnss
);
1885 DEFUN(no_ipv6_nd_rdnss
,
1886 no_ipv6_nd_rdnss_cmd
,
1887 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1889 "Interface IPv6 config commands\n"
1890 "Neighbor discovery\n"
1891 "Recursive DNS server information\n"
1893 "Valid lifetime in seconds\n"
1894 "Infinite valid lifetime\n")
1896 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1897 struct zebra_if
*zif
= ifp
->info
;
1898 struct rtadv_rdnss rdnss
= {};
1900 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
1901 vty_out(vty
, "Malformed IPv6 address\n");
1902 return CMD_WARNING_CONFIG_FAILED
;
1904 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
1905 vty_out(vty
, "Non-existant RDNSS address\n");
1906 return CMD_WARNING_CONFIG_FAILED
;
1912 DEFUN(ipv6_nd_dnssl
,
1914 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1915 "Interface IPv6 config commands\n"
1916 "Neighbor discovery\n"
1917 "DNS search list information\n"
1918 "Domain name suffix\n"
1919 "Valid lifetime in seconds\n"
1920 "Infinite valid lifetime\n")
1922 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1923 struct zebra_if
*zif
= ifp
->info
;
1924 struct rtadv_dnssl dnssl
= {};
1928 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
1929 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1930 vty_out(vty
, "Malformed DNS search domain\n");
1931 return CMD_WARNING_CONFIG_FAILED
;
1933 if (dnssl
.name
[len
- 1] == '.') {
1935 * Allow, but don't require, a trailing dot signifying the root
1936 * zone. Canonicalize by cutting it off if present.
1938 dnssl
.name
[len
- 1] = '\0';
1942 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1944 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
1946 : strtoll(lifetime
, NULL
, 10);
1947 dnssl
.lifetime_set
= 1;
1950 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
1952 vty_out(vty
, "Malformed DNS search domain\n");
1953 return CMD_WARNING_CONFIG_FAILED
;
1955 dnssl
.encoded_len
= ret
;
1956 rtadv_dnssl_set(zif
, &dnssl
);
1961 DEFUN(no_ipv6_nd_dnssl
,
1962 no_ipv6_nd_dnssl_cmd
,
1963 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1965 "Interface IPv6 config commands\n"
1966 "Neighbor discovery\n"
1967 "DNS search list information\n"
1968 "Domain name suffix\n"
1969 "Valid lifetime in seconds\n"
1970 "Infinite valid lifetime\n")
1972 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1973 struct zebra_if
*zif
= ifp
->info
;
1974 struct rtadv_dnssl dnssl
= {};
1977 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
1978 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1979 vty_out(vty
, "Malformed DNS search domain\n");
1980 return CMD_WARNING_CONFIG_FAILED
;
1982 if (dnssl
.name
[len
- 1] == '.') {
1983 dnssl
.name
[len
- 1] = '\0';
1986 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
1987 vty_out(vty
, "Non-existant DNS search domain\n");
1988 return CMD_WARNING_CONFIG_FAILED
;
1995 /* Dump interface ND information to vty. */
1996 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1998 struct zebra_if
*zif
;
1999 struct rtadvconf
*rtadv
;
2002 zif
= (struct zebra_if
*)ifp
->info
;
2003 rtadv
= &zif
->rtadv
;
2005 if (rtadv
->AdvSendAdvertisements
) {
2007 " ND advertised reachable time is %d milliseconds\n",
2008 rtadv
->AdvReachableTime
);
2010 " ND advertised retransmit interval is %d milliseconds\n",
2011 rtadv
->AdvRetransTimer
);
2012 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2013 zif
->ra_sent
, zif
->ra_rcvd
);
2014 interval
= rtadv
->MaxRtrAdvInterval
;
2015 if (interval
% 1000)
2017 " ND router advertisements are sent every "
2018 "%d milliseconds\n",
2022 " ND router advertisements are sent every "
2025 if (!rtadv
->UseFastRexmit
)
2027 " ND router advertisements do not use fast retransmit\n");
2029 if (rtadv
->AdvDefaultLifetime
!= -1)
2031 " ND router advertisements live for %d seconds\n",
2032 rtadv
->AdvDefaultLifetime
);
2035 " ND router advertisements lifetime tracks ra-interval\n");
2037 " ND router advertisement default router preference is "
2039 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2040 if (rtadv
->AdvManagedFlag
)
2042 " Hosts use DHCP to obtain routable addresses.\n");
2045 " Hosts use stateless autoconfig for addresses.\n");
2046 if (rtadv
->AdvHomeAgentFlag
) {
2048 " ND router advertisements with Home Agent flag bit set.\n");
2049 if (rtadv
->HomeAgentLifetime
!= -1)
2051 " Home Agent lifetime is %u seconds\n",
2052 rtadv
->HomeAgentLifetime
);
2055 " Home Agent lifetime tracks ra-lifetime\n");
2056 vty_out(vty
, " Home Agent preference is %u\n",
2057 rtadv
->HomeAgentPreference
);
2059 if (rtadv
->AdvIntervalOption
)
2061 " ND router advertisements with Adv. Interval option.\n");
2067 /* Write configuration about router advertisement. */
2068 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2070 struct zebra_if
*zif
;
2071 struct listnode
*node
;
2072 struct rtadv_prefix
*rprefix
;
2073 struct rtadv_rdnss
*rdnss
;
2074 struct rtadv_dnssl
*dnssl
;
2075 char buf
[PREFIX_STRLEN
];
2080 if (!(if_is_loopback(ifp
)
2081 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
2082 if (zif
->rtadv
.AdvSendAdvertisements
2083 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2084 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2087 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2088 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2089 if (interval
% 1000)
2090 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2092 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2093 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2097 if (zif
->rtadv
.AdvIntervalOption
)
2098 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2100 if (!zif
->rtadv
.UseFastRexmit
)
2101 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2103 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2104 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2105 zif
->rtadv
.AdvDefaultLifetime
);
2107 if (zif
->rtadv
.HomeAgentPreference
)
2108 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2109 zif
->rtadv
.HomeAgentPreference
);
2111 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2112 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2113 zif
->rtadv
.HomeAgentLifetime
);
2115 if (zif
->rtadv
.AdvHomeAgentFlag
)
2116 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2118 if (zif
->rtadv
.AdvReachableTime
)
2119 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2120 zif
->rtadv
.AdvReachableTime
);
2122 if (zif
->rtadv
.AdvManagedFlag
)
2123 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2125 if (zif
->rtadv
.AdvOtherConfigFlag
)
2126 vty_out(vty
, " ipv6 nd other-config-flag\n");
2128 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2129 vty_out(vty
, " ipv6 nd router-preference %s\n",
2130 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2132 if (zif
->rtadv
.AdvLinkMTU
)
2133 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2135 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
2136 vty_out(vty
, " ipv6 nd prefix %s",
2137 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
2138 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2139 || (rprefix
->AdvPreferredLifetime
2140 != RTADV_PREFERRED_LIFETIME
)) {
2141 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2142 vty_out(vty
, " infinite");
2144 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
2145 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2146 vty_out(vty
, " infinite");
2149 rprefix
->AdvPreferredLifetime
);
2151 if (!rprefix
->AdvOnLinkFlag
)
2152 vty_out(vty
, " off-link");
2153 if (!rprefix
->AdvAutonomousFlag
)
2154 vty_out(vty
, " no-autoconfig");
2155 if (rprefix
->AdvRouterAddressFlag
)
2156 vty_out(vty
, " router-address");
2159 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2160 char buf
[INET6_ADDRSTRLEN
];
2162 vty_out(vty
, " ipv6 nd rdnss %s",
2163 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2164 if (rdnss
->lifetime_set
) {
2165 if (rdnss
->lifetime
== UINT32_MAX
)
2166 vty_out(vty
, " infinite");
2168 vty_out(vty
, " %u", rdnss
->lifetime
);
2172 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2173 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2174 if (dnssl
->lifetime_set
) {
2175 if (dnssl
->lifetime
== UINT32_MAX
)
2176 vty_out(vty
, " infinite");
2178 vty_out(vty
, " %u", dnssl
->lifetime
);
2186 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2188 struct rtadv
*rtadv
= &zvrf
->rtadv
;
2192 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2194 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2198 THREAD_OFF(rtadv
->ra_timer
);
2199 THREAD_OFF(rtadv
->ra_read
);
2202 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2205 case RTADV_TIMER_MSEC
:
2206 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2210 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2219 void rtadv_init(struct zebra_vrf
*zvrf
)
2221 if (vrf_is_backend_netns()) {
2222 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2223 zrouter
.rtadv_sock
= -1;
2225 zvrf
->rtadv
.sock
= -1;
2226 if (zrouter
.rtadv_sock
< 0)
2227 zrouter
.rtadv_sock
=
2228 rtadv_make_socket(zvrf
->zns
->ns_id
);
2232 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2234 rtadv_event(zvrf
, RTADV_STOP
, 0);
2235 if (zvrf
->rtadv
.sock
>= 0) {
2236 close(zvrf
->rtadv
.sock
);
2237 zvrf
->rtadv
.sock
= -1;
2238 } else if (zrouter
.rtadv_sock
>= 0) {
2239 close(zrouter
.rtadv_sock
);
2240 zrouter
.rtadv_sock
= -1;
2242 zvrf
->rtadv
.adv_if_count
= 0;
2243 zvrf
->rtadv
.adv_msec_if_count
= 0;
2246 void rtadv_cmd_init(void)
2248 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2249 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2251 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2252 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2253 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2254 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2255 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2256 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2257 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2258 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2259 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2260 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2261 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2262 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2263 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2264 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2265 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2266 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2267 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2268 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2269 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2270 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2271 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2272 install_element(INTERFACE_NODE
,
2273 &ipv6_nd_adv_interval_config_option_cmd
);
2274 install_element(INTERFACE_NODE
,
2275 &no_ipv6_nd_adv_interval_config_option_cmd
);
2276 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2277 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2278 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2279 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2280 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2281 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2282 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2283 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2284 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2285 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2288 static int if_join_all_router(int sock
, struct interface
*ifp
)
2292 struct ipv6_mreq mreq
;
2294 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2295 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2296 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2298 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2301 flog_err_sys(EC_LIB_SOCKET
,
2302 "%s(%u): Failed to join group, socket %u error %s",
2303 ifp
->name
, ifp
->ifindex
, sock
,
2304 safe_strerror(errno
));
2306 if (IS_ZEBRA_DEBUG_EVENT
)
2308 "%s(%u): Join All-Routers multicast group, socket %u",
2309 ifp
->name
, ifp
->ifindex
, sock
);
2314 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2318 struct ipv6_mreq mreq
;
2320 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2321 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2322 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2324 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2329 "%s(%u): Failed to leave group, socket %u error %s",
2330 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
2332 if (IS_ZEBRA_DEBUG_EVENT
)
2334 "%s(%u): Leave All-Routers multicast group, socket %u",
2335 ifp
->name
, ifp
->ifindex
, sock
);
2341 void rtadv_init(struct zebra_vrf
*zvrf
)
2345 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2349 void rtadv_cmd_init(void)
2353 #endif /* HAVE_RTADV */