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 static const char *const rtadv_pref_strs
[] = {
76 "medium", "high", "INVALID", "low", 0
87 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
89 static int if_join_all_router(int, struct interface
*);
90 static int if_leave_all_router(int, struct interface
*);
92 static int rtadv_get_socket(struct zebra_vrf
*zvrf
)
94 if (zvrf
->rtadv
.sock
> 0)
95 return zvrf
->rtadv
.sock
;
96 return zrouter
.rtadv_sock
;
99 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
102 struct interface
*iface
;
103 struct zebra_if
*zif
;
105 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
106 if (iface
&& iface
->info
) {
114 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
115 int buflen
, struct sockaddr_in6
*from
,
116 ifindex_t
*ifindex
, int *hoplimit
)
121 struct cmsghdr
*cmsgptr
;
126 /* Fill in message and iovec. */
127 memset(&msg
, 0, sizeof(msg
));
128 msg
.msg_name
= (void *)from
;
129 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
132 msg
.msg_control
= (void *)adata
;
133 msg
.msg_controllen
= sizeof adata
;
135 iov
.iov_len
= buflen
;
137 /* If recvmsg fail return minus value. */
138 ret
= recvmsg(sock
, &msg
, 0);
142 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
143 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
144 /* I want interface index which this packet comes from. */
145 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
146 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
147 struct in6_pktinfo
*ptr
;
149 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
150 *ifindex
= ptr
->ipi6_ifindex
;
151 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
154 /* Incoming packet's hop limit. */
155 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
156 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
157 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
162 rtadv_increment_received(zvrf
, ifindex
);
166 #define RTADV_MSG_SIZE 4096
168 /* Send router advertisement packet. */
169 static void rtadv_send_packet(int sock
, struct interface
*ifp
,
170 ipv6_nd_suppress_ra_status stop
)
174 struct cmsghdr
*cmsgptr
;
175 struct in6_pktinfo
*pkt
;
176 struct sockaddr_in6 addr
;
177 static void *adata
= NULL
;
178 unsigned char buf
[RTADV_MSG_SIZE
];
179 struct nd_router_advert
*rtadv
;
182 struct zebra_if
*zif
;
183 struct rtadv_prefix
*rprefix
;
184 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
185 0, 0, 0, 0, 0, 0, 0, 1};
186 struct listnode
*node
;
187 uint16_t pkt_RouterLifetime
;
190 * Allocate control message bufffer. This is dynamic because
191 * CMSG_SPACE is not guaranteed not to call a function. Note that
192 * the size will be different on different architectures due to
193 * differing alignment rules.
196 /* XXX Free on shutdown. */
197 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
201 "rtadv_send_packet: can't malloc control data");
206 /* Logging of packet. */
207 if (IS_ZEBRA_DEBUG_PACKET
)
208 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
211 /* Fill in sockaddr_in6. */
212 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
213 addr
.sin6_family
= AF_INET6
;
215 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
216 #endif /* SIN6_LEN */
217 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
218 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
220 /* Fetch interface information. */
223 /* Make router advertisement message. */
224 rtadv
= (struct nd_router_advert
*)buf
;
226 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
227 rtadv
->nd_ra_code
= 0;
228 rtadv
->nd_ra_cksum
= 0;
230 rtadv
->nd_ra_curhoplimit
= 64;
232 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
233 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
235 : zif
->rtadv
.DefaultPreference
;
236 rtadv
->nd_ra_flags_reserved
<<= 3;
238 if (zif
->rtadv
.AdvManagedFlag
)
239 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
240 if (zif
->rtadv
.AdvOtherConfigFlag
)
241 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
242 if (zif
->rtadv
.AdvHomeAgentFlag
)
243 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
244 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
245 * AdvDefaultLifetime is by default based on the value of
246 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
247 * field of Router Advertisements. Given that this field is expressed
248 * in seconds, a small MaxRtrAdvInterval value can result in a zero
249 * value for this field. To prevent this, routers SHOULD keep
250 * AdvDefaultLifetime in at least one second, even if the use of
251 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
253 zif
->rtadv
.AdvDefaultLifetime
!= -1
254 ? zif
->rtadv
.AdvDefaultLifetime
255 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
257 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
258 rtadv
->nd_ra_router_lifetime
=
259 (stop
== RA_SUPPRESS
) ? htons(0) : htons(pkt_RouterLifetime
);
260 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
261 rtadv
->nd_ra_retransmit
= htonl(0);
263 len
= sizeof(struct nd_router_advert
);
265 /* If both the Home Agent Preference and Home Agent Lifetime are set to
266 * their default values specified above, this option SHOULD NOT be
267 * included in the Router Advertisement messages sent by this home
268 * agent. -- RFC6275, 7.4 */
269 if (zif
->rtadv
.AdvHomeAgentFlag
270 && (zif
->rtadv
.HomeAgentPreference
271 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
272 struct nd_opt_homeagent_info
*ndopt_hai
=
273 (struct nd_opt_homeagent_info
*)(buf
+ len
);
274 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
275 ndopt_hai
->nd_opt_hai_len
= 1;
276 ndopt_hai
->nd_opt_hai_reserved
= 0;
277 ndopt_hai
->nd_opt_hai_preference
=
278 htons(zif
->rtadv
.HomeAgentPreference
);
279 /* 16-bit unsigned integer. The lifetime associated with the
281 * agent in units of seconds. The default value is the same as
283 * Router Lifetime, as specified in the main body of the Router
284 * Advertisement. The maximum value corresponds to 18.2 hours.
286 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
287 ndopt_hai
->nd_opt_hai_lifetime
=
288 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
289 ? zif
->rtadv
.HomeAgentLifetime
290 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
295 len
+= sizeof(struct nd_opt_homeagent_info
);
298 if (zif
->rtadv
.AdvIntervalOption
) {
299 struct nd_opt_adv_interval
*ndopt_adv
=
300 (struct nd_opt_adv_interval
*)(buf
+ len
);
301 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
302 ndopt_adv
->nd_opt_ai_len
= 1;
303 ndopt_adv
->nd_opt_ai_reserved
= 0;
304 ndopt_adv
->nd_opt_ai_interval
=
305 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
306 len
+= sizeof(struct nd_opt_adv_interval
);
309 /* Fill in prefix. */
310 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
311 struct nd_opt_prefix_info
*pinfo
;
313 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
315 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
316 pinfo
->nd_opt_pi_len
= 4;
317 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
319 pinfo
->nd_opt_pi_flags_reserved
= 0;
320 if (rprefix
->AdvOnLinkFlag
)
321 pinfo
->nd_opt_pi_flags_reserved
|=
322 ND_OPT_PI_FLAG_ONLINK
;
323 if (rprefix
->AdvAutonomousFlag
)
324 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
325 if (rprefix
->AdvRouterAddressFlag
)
326 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
328 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
329 pinfo
->nd_opt_pi_preferred_time
=
330 htonl(rprefix
->AdvPreferredLifetime
);
331 pinfo
->nd_opt_pi_reserved2
= 0;
333 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
334 &rprefix
->prefix
.prefix
);
338 uint8_t buf
[INET6_ADDRSTRLEN
];
340 zlog_debug("DEBUG %s",
341 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
342 buf
, INET6_ADDRSTRLEN
));
346 len
+= sizeof(struct nd_opt_prefix_info
);
349 /* Hardware address. */
350 if (ifp
->hw_addr_len
!= 0) {
351 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
353 /* Option length should be rounded up to next octet if
354 the link address does not end on an octet boundary. */
355 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
357 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
358 len
+= ifp
->hw_addr_len
;
360 /* Pad option to end on an octet boundary. */
361 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
362 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
366 if (zif
->rtadv
.AdvLinkMTU
) {
367 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
368 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
369 opt
->nd_opt_mtu_len
= 1;
370 opt
->nd_opt_mtu_reserved
= 0;
371 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
372 len
+= sizeof(struct nd_opt_mtu
);
376 * There is no limit on the number of configurable recursive DNS
377 * servers or search list entries. We don't want the RA message
378 * to exceed the link's MTU (risking fragmentation) or even
379 * blow the stack buffer allocated for it.
381 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
383 /* Recursive DNS servers */
384 struct rtadv_rdnss
*rdnss
;
386 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
388 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
390 if (len
+ opt_len
> max_len
) {
392 "%s(%u): Tx RA: RDNSS option would exceed MTU, omitting it",
393 ifp
->name
, ifp
->ifindex
);
396 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
398 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
399 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
400 opt
->nd_opt_rdnss_reserved
= 0;
401 opt
->nd_opt_rdnss_lifetime
= htonl(
404 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
406 len
+= sizeof(struct nd_opt_rdnss
);
408 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
409 len
+= sizeof(struct in6_addr
);
412 /* DNS search list */
413 struct rtadv_dnssl
*dnssl
;
415 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
416 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
417 + ((dnssl
->encoded_len
+ 7) & ~7);
419 if (len
+ opt_len
> max_len
) {
421 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
422 ifp
->name
, ifp
->ifindex
);
425 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
427 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
428 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
429 opt
->nd_opt_dnssl_reserved
= 0;
430 opt
->nd_opt_dnssl_lifetime
= htonl(
433 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
435 len
+= sizeof(struct nd_opt_dnssl
);
437 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
438 len
+= dnssl
->encoded_len
;
440 /* Zero-pad to 8-octet boundary */
447 msg
.msg_name
= (void *)&addr
;
448 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
451 msg
.msg_control
= (void *)adata
;
452 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
457 cmsgptr
= CMSG_FIRSTHDR(&msg
);
458 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
459 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
460 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
462 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
463 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
464 pkt
->ipi6_ifindex
= ifp
->ifindex
;
466 ret
= sendmsg(sock
, &msg
, 0);
468 flog_err_sys(EC_LIB_SOCKET
,
469 "%s(%u): Tx RA failed, socket %u error %d (%s)",
470 ifp
->name
, ifp
->ifindex
, sock
, errno
,
471 safe_strerror(errno
));
476 static int rtadv_timer(struct thread
*thread
)
478 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
480 struct interface
*ifp
;
481 struct zebra_if
*zif
;
484 zvrf
->rtadv
.ra_timer
= NULL
;
485 if (zvrf
->rtadv
.adv_msec_if_count
== 0) {
486 period
= 1000; /* 1 s */
487 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
489 period
= 10; /* 10 ms */
490 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
493 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
494 FOR_ALL_INTERFACES (vrf
, ifp
) {
495 if (if_is_loopback(ifp
)
496 || CHECK_FLAG(ifp
->status
,
497 ZEBRA_INTERFACE_VRF_LOOPBACK
)
498 || !if_is_operative(ifp
))
503 if (zif
->rtadv
.AdvSendAdvertisements
) {
504 if (zif
->rtadv
.inFastRexmit
505 && zif
->rtadv
.UseFastRexmit
) {
506 /* We assume we fast rexmit every sec so
509 if (--zif
->rtadv
.NumFastReXmitsRemain
511 zif
->rtadv
.inFastRexmit
= 0;
513 if (IS_ZEBRA_DEBUG_SEND
)
515 "Fast RA Rexmit on interface %s",
518 rtadv_send_packet(rtadv_get_socket(zvrf
),
521 zif
->rtadv
.AdvIntervalTimer
-= period
;
522 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
524 MaxRtrAdvInterval each
525 time isn't what section
526 6.2.4 of RFC4861 tells to do.
528 zif
->rtadv
.AdvIntervalTimer
=
532 rtadv_get_socket(zvrf
),
542 static void rtadv_process_solicit(struct interface
*ifp
)
544 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
545 struct zebra_if
*zif
;
551 * If FastRetransmit is enabled, send the RA immediately.
552 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
553 * (3 seconds) since the last RA was sent, send it now and reset
554 * the timer to start at the max (configured) again.
555 * If not enabled and it is less than 3 seconds since the last
556 * RA packet was sent, set the timer for 3 seconds so the next
557 * one will be sent with a minimum of 3 seconds between RAs.
560 if ((zif
->rtadv
.UseFastRexmit
)
561 || (zif
->rtadv
.AdvIntervalTimer
<=
562 (zif
->rtadv
.MaxRtrAdvInterval
- MIN_DELAY_BETWEEN_RAS
))) {
563 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
, RA_ENABLE
);
564 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
566 zif
->rtadv
.AdvIntervalTimer
= MIN_DELAY_BETWEEN_RAS
;
570 * This function processes optional attributes off of
571 * end of a RA packet received. At this point in
572 * time we only care about this in one situation
573 * which is when a interface does not have a LL
574 * v6 address. We still need to be able to install
575 * the mac address for v4 to v6 resolution
577 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
578 struct interface
*ifp
,
579 struct sockaddr_in6
*addr
)
584 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
586 switch(opt_hdr
->nd_opt_type
) {
587 case ND_OPT_SOURCE_LINKADDR
:
588 mac
= (char *)(optional
+2);
589 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
590 &addr
->sin6_addr
, 1);
596 len
-= 8 * opt_hdr
->nd_opt_len
;
597 optional
+= 8 * opt_hdr
->nd_opt_len
;
601 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
602 struct interface
*ifp
,
603 struct sockaddr_in6
*addr
)
605 struct nd_router_advert
*radvert
;
606 char addr_str
[INET6_ADDRSTRLEN
];
607 struct zebra_if
*zif
;
612 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
614 if (len
< sizeof(struct nd_router_advert
)) {
615 if (IS_ZEBRA_DEBUG_PACKET
)
616 zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
617 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
621 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
622 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
623 len
- sizeof(struct nd_router_advert
),
625 if (IS_ZEBRA_DEBUG_PACKET
)
626 zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s",
627 ifp
->name
, ifp
->ifindex
, addr_str
);
631 radvert
= (struct nd_router_advert
*)msg
;
633 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
634 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
636 EC_ZEBRA_RA_PARAM_MISMATCH
,
637 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
638 ifp
->name
, ifp
->ifindex
, addr_str
);
641 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
642 && !zif
->rtadv
.AdvManagedFlag
) {
644 EC_ZEBRA_RA_PARAM_MISMATCH
,
645 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
646 ifp
->name
, ifp
->ifindex
, addr_str
);
649 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
650 && !zif
->rtadv
.AdvOtherConfigFlag
) {
652 EC_ZEBRA_RA_PARAM_MISMATCH
,
653 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
654 ifp
->name
, ifp
->ifindex
, addr_str
);
657 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
658 && (ntohl(radvert
->nd_ra_reachable
)
659 != zif
->rtadv
.AdvReachableTime
)) {
661 EC_ZEBRA_RA_PARAM_MISMATCH
,
662 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
663 ifp
->name
, ifp
->ifindex
, addr_str
);
666 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
667 && (ntohl(radvert
->nd_ra_retransmit
)
668 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
670 EC_ZEBRA_RA_PARAM_MISMATCH
,
671 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
672 ifp
->name
, ifp
->ifindex
, addr_str
);
675 /* Create entry for neighbor if not known. */
677 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
678 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
680 if (!nbr_connected_check(ifp
, &p
))
681 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
685 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
686 ifindex_t ifindex
, int hoplimit
,
687 struct sockaddr_in6
*from
,
688 struct zebra_vrf
*zvrf
)
690 struct icmp6_hdr
*icmph
;
691 struct interface
*ifp
;
692 struct zebra_if
*zif
;
693 char addr_str
[INET6_ADDRSTRLEN
];
695 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
697 /* Interface search. */
698 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
700 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
701 "RA/RS received on unknown IF %u from %s", ifindex
,
706 if (IS_ZEBRA_DEBUG_PACKET
)
707 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
708 ifp
->ifindex
, len
, addr_str
);
710 if (if_is_loopback(ifp
)
711 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
714 /* Check interface configuration. */
716 if (!zif
->rtadv
.AdvSendAdvertisements
)
719 /* ICMP message length check. */
720 if (len
< sizeof(struct icmp6_hdr
)) {
721 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
722 ifp
->name
, ifp
->ifindex
, len
);
726 icmph
= (struct icmp6_hdr
*)buf
;
728 /* ICMP message type check. */
729 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
730 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
731 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
732 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
736 /* Hoplimit check. */
737 if (hoplimit
>= 0 && hoplimit
!= 255) {
738 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
739 ifp
->ifindex
, hoplimit
);
743 /* Check ICMP message type. */
744 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
745 rtadv_process_solicit(ifp
);
746 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
747 rtadv_process_advert(buf
, len
, ifp
, from
);
752 static int rtadv_read(struct thread
*thread
)
756 uint8_t buf
[RTADV_MSG_SIZE
];
757 struct sockaddr_in6 from
;
758 ifindex_t ifindex
= 0;
760 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
762 sock
= THREAD_FD(thread
);
763 zvrf
->rtadv
.ra_read
= NULL
;
765 /* Register myself. */
766 rtadv_event(zvrf
, RTADV_READ
, sock
);
768 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
772 flog_err_sys(EC_LIB_SOCKET
,
773 "RA/RS recv failed, socket %u error %s", sock
,
774 safe_strerror(errno
));
778 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
783 static int rtadv_make_socket(ns_id_t ns_id
)
787 struct icmp6_filter filter
;
789 frr_with_privs(&zserv_privs
) {
791 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
799 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
804 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
809 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
814 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
819 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
825 ICMP6_FILTER_SETBLOCKALL(&filter
);
826 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
827 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
829 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
830 sizeof(struct icmp6_filter
));
832 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
840 static struct rtadv_prefix
*rtadv_prefix_new(void)
842 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
845 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
847 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
850 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
851 struct prefix_ipv6
*p
)
853 struct listnode
*node
;
854 struct rtadv_prefix
*rprefix
;
856 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
857 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
863 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
864 struct prefix_ipv6
*p
)
866 struct rtadv_prefix
*rprefix
;
868 rprefix
= rtadv_prefix_lookup(rplist
, p
);
872 rprefix
= rtadv_prefix_new();
873 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
874 listnode_add(rplist
, rprefix
);
879 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
881 struct rtadv_prefix
*rprefix
;
883 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
885 /* Set parameters. */
886 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
887 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
888 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
889 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
890 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
893 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
895 struct rtadv_prefix
*rprefix
;
897 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
898 if (rprefix
!= NULL
) {
899 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
900 rtadv_prefix_free(rprefix
);
906 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
907 ipv6_nd_suppress_ra_status status
)
909 struct zebra_if
*zif
;
910 struct zebra_vrf
*zvrf
;
913 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
915 if (status
== RA_SUPPRESS
) {
916 /* RA is currently enabled */
917 if (zif
->rtadv
.AdvSendAdvertisements
) {
918 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
,
920 zif
->rtadv
.AdvSendAdvertisements
= 0;
921 zif
->rtadv
.AdvIntervalTimer
= 0;
922 zvrf
->rtadv
.adv_if_count
--;
924 if_leave_all_router(rtadv_get_socket(zvrf
), ifp
);
926 if (zvrf
->rtadv
.adv_if_count
== 0)
927 rtadv_event(zvrf
, RTADV_STOP
, 0);
930 if (!zif
->rtadv
.AdvSendAdvertisements
) {
931 zif
->rtadv
.AdvSendAdvertisements
= 1;
932 zif
->rtadv
.AdvIntervalTimer
= 0;
933 zvrf
->rtadv
.adv_if_count
++;
935 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
936 && zif
->rtadv
.UseFastRexmit
) {
938 * Enable Fast RA only when RA interval is in
939 * secs and Fast RA retransmit is enabled
941 zif
->rtadv
.inFastRexmit
= 1;
942 zif
->rtadv
.NumFastReXmitsRemain
=
943 RTADV_NUM_FAST_REXMITS
;
946 if_join_all_router(rtadv_get_socket(zvrf
), ifp
);
948 if (zvrf
->rtadv
.adv_if_count
== 1)
949 rtadv_event(zvrf
, RTADV_START
,
950 rtadv_get_socket(zvrf
));
956 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
957 * Note that while the client could request RA on an interface on which the
958 * operator has not enabled RA, RA won't be disabled upon client request
959 * if the operator has explicitly enabled RA. The enable request can also
960 * specify a RA interval (in seconds).
962 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
966 struct interface
*ifp
;
967 struct zebra_if
*zif
;
972 /* Get interface index and RA interval. */
973 STREAM_GETL(s
, ifindex
);
974 STREAM_GETL(s
, ra_interval_rxd
);
976 if (ra_interval_rxd
< 0) {
978 "Requested RA interval %d is garbage; ignoring request",
983 unsigned int ra_interval
= ra_interval_rxd
;
985 if (IS_ZEBRA_DEBUG_EVENT
)
986 zlog_debug("%u: IF %u RA %s from client %s, interval %ums",
987 zvrf_id(zvrf
), ifindex
,
988 enable
? "enable" : "disable",
989 zebra_route_string(client
->proto
), ra_interval
);
991 /* Locate interface and check VRF match. */
992 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
994 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
995 "%u: IF %u RA %s client %s - interface unknown",
996 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
997 zebra_route_string(client
->proto
));
1000 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
1002 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1003 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
1004 zebra_route_string(client
->proto
), ifp
->vrf_id
);
1010 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1011 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1013 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1014 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1015 VTY_RA_INTERVAL_CONFIGURED
))
1016 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1018 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1019 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1020 VTY_RA_INTERVAL_CONFIGURED
))
1021 zif
->rtadv
.MaxRtrAdvInterval
=
1022 RTADV_MAX_RTR_ADV_INTERVAL
;
1023 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1024 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1031 * send router lifetime value of zero in RAs on this interface since we're
1032 * ceasing to advertise and want to let our neighbors know.
1033 * RFC 4861 secion 6.2.5
1035 void rtadv_stop_ra(struct interface
*ifp
)
1037 struct zebra_if
*zif
;
1038 struct zebra_vrf
*zvrf
;
1041 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1043 if (zif
->rtadv
.AdvSendAdvertisements
)
1044 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
, RA_SUPPRESS
);
1048 * send router lifetime value of zero in RAs on all interfaces since we're
1049 * ceasing to advertise globally and want to let all of our neighbors know
1050 * RFC 4861 secion 6.2.5
1052 void rtadv_stop_ra_all(void)
1055 struct interface
*ifp
;
1057 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1058 FOR_ALL_INTERFACES (vrf
, ifp
)
1062 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1064 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1066 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1068 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1071 DEFUN (ipv6_nd_ra_fast_retrans
,
1072 ipv6_nd_ra_fast_retrans_cmd
,
1073 "ipv6 nd ra-fast-retrans",
1074 "Interface IPv6 config commands\n"
1075 "Neighbor discovery\n"
1076 "Fast retransmit of RA packets\n")
1078 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1079 struct zebra_if
*zif
= ifp
->info
;
1081 if (if_is_loopback(ifp
)
1082 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1084 "Cannot configure IPv6 Router Advertisements on this interface\n");
1085 return CMD_WARNING_CONFIG_FAILED
;
1088 zif
->rtadv
.UseFastRexmit
= true;
1093 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1094 no_ipv6_nd_ra_fast_retrans_cmd
,
1095 "no ipv6 nd ra-fast-retrans",
1097 "Interface IPv6 config commands\n"
1098 "Neighbor discovery\n"
1099 "Fast retransmit of RA packets\n")
1101 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1102 struct zebra_if
*zif
= ifp
->info
;
1104 if (if_is_loopback(ifp
)
1105 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1107 "Cannot configure IPv6 Router Advertisements on this interface\n");
1108 return CMD_WARNING_CONFIG_FAILED
;
1111 zif
->rtadv
.UseFastRexmit
= false;
1116 DEFUN (ipv6_nd_suppress_ra
,
1117 ipv6_nd_suppress_ra_cmd
,
1118 "ipv6 nd suppress-ra",
1119 "Interface IPv6 config commands\n"
1120 "Neighbor discovery\n"
1121 "Suppress Router Advertisement\n")
1123 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1124 struct zebra_if
*zif
= ifp
->info
;
1126 if (if_is_loopback(ifp
)
1127 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1129 "Cannot configure IPv6 Router Advertisements on this interface\n");
1130 return CMD_WARNING_CONFIG_FAILED
;
1133 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1134 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1136 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1140 DEFUN (no_ipv6_nd_suppress_ra
,
1141 no_ipv6_nd_suppress_ra_cmd
,
1142 "no ipv6 nd suppress-ra",
1144 "Interface IPv6 config commands\n"
1145 "Neighbor discovery\n"
1146 "Suppress Router Advertisement\n")
1148 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1149 struct zebra_if
*zif
= ifp
->info
;
1151 if (if_is_loopback(ifp
)
1152 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1154 "Cannot configure IPv6 Router Advertisements on this interface\n");
1155 return CMD_WARNING_CONFIG_FAILED
;
1158 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1159 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1163 DEFUN (ipv6_nd_ra_interval_msec
,
1164 ipv6_nd_ra_interval_msec_cmd
,
1165 "ipv6 nd ra-interval msec (70-1800000)",
1166 "Interface IPv6 config commands\n"
1167 "Neighbor discovery\n"
1168 "Router Advertisement interval\n"
1169 "Router Advertisement interval in milliseconds\n"
1170 "Router Advertisement interval in milliseconds\n")
1173 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1175 struct zebra_if
*zif
= ifp
->info
;
1176 struct zebra_vrf
*zvrf
;
1178 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1180 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1181 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1182 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1184 "This ra-interval would conflict with configured ra-lifetime!\n");
1185 return CMD_WARNING_CONFIG_FAILED
;
1188 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1189 zvrf
->rtadv
.adv_msec_if_count
--;
1191 if (interval
% 1000)
1192 zvrf
->rtadv
.adv_msec_if_count
++;
1194 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1195 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1196 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1197 zif
->rtadv
.AdvIntervalTimer
= 0;
1202 DEFUN (ipv6_nd_ra_interval
,
1203 ipv6_nd_ra_interval_cmd
,
1204 "ipv6 nd ra-interval (1-1800)",
1205 "Interface IPv6 config commands\n"
1206 "Neighbor discovery\n"
1207 "Router Advertisement interval\n"
1208 "Router Advertisement interval in seconds\n")
1211 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1213 struct zebra_if
*zif
= ifp
->info
;
1214 struct zebra_vrf
*zvrf
;
1216 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1218 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1219 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1220 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1222 "This ra-interval would conflict with configured ra-lifetime!\n");
1223 return CMD_WARNING_CONFIG_FAILED
;
1226 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1227 zvrf
->rtadv
.adv_msec_if_count
--;
1229 /* convert to milliseconds */
1230 interval
= interval
* 1000;
1232 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1233 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1234 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1235 zif
->rtadv
.AdvIntervalTimer
= 0;
1240 DEFUN (no_ipv6_nd_ra_interval
,
1241 no_ipv6_nd_ra_interval_cmd
,
1242 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1244 "Interface IPv6 config commands\n"
1245 "Neighbor discovery\n"
1246 "Router Advertisement interval\n"
1247 "Router Advertisement interval in seconds\n"
1248 "Specify millisecond router advertisement interval\n"
1249 "Router Advertisement interval in milliseconds\n")
1251 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1252 struct zebra_if
*zif
= ifp
->info
;
1253 struct zebra_vrf
*zvrf
= NULL
;
1255 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1257 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1258 zvrf
->rtadv
.adv_msec_if_count
--;
1260 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1262 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1263 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1265 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1267 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1268 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1273 DEFUN (ipv6_nd_ra_lifetime
,
1274 ipv6_nd_ra_lifetime_cmd
,
1275 "ipv6 nd ra-lifetime (0-9000)",
1276 "Interface IPv6 config commands\n"
1277 "Neighbor discovery\n"
1279 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1282 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1283 struct zebra_if
*zif
= ifp
->info
;
1286 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1288 /* The value to be placed in the Router Lifetime field
1289 * of Router Advertisements sent from the interface,
1290 * in seconds. MUST be either zero or between
1291 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1292 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1294 "This ra-lifetime would conflict with configured ra-interval\n");
1295 return CMD_WARNING_CONFIG_FAILED
;
1298 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1303 DEFUN (no_ipv6_nd_ra_lifetime
,
1304 no_ipv6_nd_ra_lifetime_cmd
,
1305 "no ipv6 nd ra-lifetime [(0-9000)]",
1307 "Interface IPv6 config commands\n"
1308 "Neighbor discovery\n"
1310 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1312 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1313 struct zebra_if
*zif
= ifp
->info
;
1315 zif
->rtadv
.AdvDefaultLifetime
= -1;
1320 DEFUN (ipv6_nd_reachable_time
,
1321 ipv6_nd_reachable_time_cmd
,
1322 "ipv6 nd reachable-time (1-3600000)",
1323 "Interface IPv6 config commands\n"
1324 "Neighbor discovery\n"
1326 "Reachable time in milliseconds\n")
1329 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1330 struct zebra_if
*zif
= ifp
->info
;
1331 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1335 DEFUN (no_ipv6_nd_reachable_time
,
1336 no_ipv6_nd_reachable_time_cmd
,
1337 "no ipv6 nd reachable-time [(1-3600000)]",
1339 "Interface IPv6 config commands\n"
1340 "Neighbor discovery\n"
1342 "Reachable time in milliseconds\n")
1344 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1345 struct zebra_if
*zif
= ifp
->info
;
1347 zif
->rtadv
.AdvReachableTime
= 0;
1352 DEFUN (ipv6_nd_homeagent_preference
,
1353 ipv6_nd_homeagent_preference_cmd
,
1354 "ipv6 nd home-agent-preference (0-65535)",
1355 "Interface IPv6 config commands\n"
1356 "Neighbor discovery\n"
1357 "Home Agent preference\n"
1358 "preference value (default is 0, least preferred)\n")
1361 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1362 struct zebra_if
*zif
= ifp
->info
;
1363 zif
->rtadv
.HomeAgentPreference
=
1364 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1368 DEFUN (no_ipv6_nd_homeagent_preference
,
1369 no_ipv6_nd_homeagent_preference_cmd
,
1370 "no ipv6 nd home-agent-preference [(0-65535)]",
1372 "Interface IPv6 config commands\n"
1373 "Neighbor discovery\n"
1374 "Home Agent preference\n"
1375 "preference value (default is 0, least preferred)\n")
1377 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1378 struct zebra_if
*zif
= ifp
->info
;
1380 zif
->rtadv
.HomeAgentPreference
= 0;
1385 DEFUN (ipv6_nd_homeagent_lifetime
,
1386 ipv6_nd_homeagent_lifetime_cmd
,
1387 "ipv6 nd home-agent-lifetime (0-65520)",
1388 "Interface IPv6 config commands\n"
1389 "Neighbor discovery\n"
1390 "Home Agent lifetime\n"
1391 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1394 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1395 struct zebra_if
*zif
= ifp
->info
;
1396 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1400 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1401 no_ipv6_nd_homeagent_lifetime_cmd
,
1402 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1404 "Interface IPv6 config commands\n"
1405 "Neighbor discovery\n"
1406 "Home Agent lifetime\n"
1407 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1409 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1410 struct zebra_if
*zif
= ifp
->info
;
1412 zif
->rtadv
.HomeAgentLifetime
= -1;
1417 DEFUN (ipv6_nd_managed_config_flag
,
1418 ipv6_nd_managed_config_flag_cmd
,
1419 "ipv6 nd managed-config-flag",
1420 "Interface IPv6 config commands\n"
1421 "Neighbor discovery\n"
1422 "Managed address configuration flag\n")
1424 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1425 struct zebra_if
*zif
= ifp
->info
;
1427 zif
->rtadv
.AdvManagedFlag
= 1;
1432 DEFUN (no_ipv6_nd_managed_config_flag
,
1433 no_ipv6_nd_managed_config_flag_cmd
,
1434 "no ipv6 nd managed-config-flag",
1436 "Interface IPv6 config commands\n"
1437 "Neighbor discovery\n"
1438 "Managed address configuration flag\n")
1440 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1441 struct zebra_if
*zif
= ifp
->info
;
1443 zif
->rtadv
.AdvManagedFlag
= 0;
1448 DEFUN (ipv6_nd_homeagent_config_flag
,
1449 ipv6_nd_homeagent_config_flag_cmd
,
1450 "ipv6 nd home-agent-config-flag",
1451 "Interface IPv6 config commands\n"
1452 "Neighbor discovery\n"
1453 "Home Agent configuration flag\n")
1455 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1456 struct zebra_if
*zif
= ifp
->info
;
1458 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1463 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1464 no_ipv6_nd_homeagent_config_flag_cmd
,
1465 "no ipv6 nd home-agent-config-flag",
1467 "Interface IPv6 config commands\n"
1468 "Neighbor discovery\n"
1469 "Home Agent configuration flag\n")
1471 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1472 struct zebra_if
*zif
= ifp
->info
;
1474 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1479 DEFUN (ipv6_nd_adv_interval_config_option
,
1480 ipv6_nd_adv_interval_config_option_cmd
,
1481 "ipv6 nd adv-interval-option",
1482 "Interface IPv6 config commands\n"
1483 "Neighbor discovery\n"
1484 "Advertisement Interval Option\n")
1486 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1487 struct zebra_if
*zif
= ifp
->info
;
1489 zif
->rtadv
.AdvIntervalOption
= 1;
1494 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1495 no_ipv6_nd_adv_interval_config_option_cmd
,
1496 "no ipv6 nd adv-interval-option",
1498 "Interface IPv6 config commands\n"
1499 "Neighbor discovery\n"
1500 "Advertisement Interval Option\n")
1502 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1503 struct zebra_if
*zif
= ifp
->info
;
1505 zif
->rtadv
.AdvIntervalOption
= 0;
1510 DEFUN (ipv6_nd_other_config_flag
,
1511 ipv6_nd_other_config_flag_cmd
,
1512 "ipv6 nd other-config-flag",
1513 "Interface IPv6 config commands\n"
1514 "Neighbor discovery\n"
1515 "Other statefull configuration flag\n")
1517 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1518 struct zebra_if
*zif
= ifp
->info
;
1520 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1525 DEFUN (no_ipv6_nd_other_config_flag
,
1526 no_ipv6_nd_other_config_flag_cmd
,
1527 "no ipv6 nd other-config-flag",
1529 "Interface IPv6 config commands\n"
1530 "Neighbor discovery\n"
1531 "Other statefull configuration flag\n")
1533 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1534 struct zebra_if
*zif
= ifp
->info
;
1536 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1541 DEFUN (ipv6_nd_prefix
,
1543 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1544 "Interface IPv6 config commands\n"
1545 "Neighbor discovery\n"
1546 "Prefix information\n"
1548 "Valid lifetime in seconds\n"
1549 "Infinite valid lifetime\n"
1550 "Preferred lifetime in seconds\n"
1551 "Infinite preferred lifetime\n"
1552 "Set Router Address flag\n"
1553 "Do not use prefix for onlink determination\n"
1554 "Do not use prefix for autoconfiguration\n"
1555 "Do not use prefix for autoconfiguration\n"
1556 "Do not use prefix for onlink determination\n")
1559 char *prefix
= argv
[3]->arg
;
1560 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1561 || strmatch(argv
[4]->text
, "infinite"));
1562 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1564 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1566 char *lifetime
= NULL
, *preflifetime
= NULL
;
1567 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1569 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1571 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1576 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1578 offlink
= (argc
> idx_routeropts
+ 1
1579 || strmatch(argv
[idx_routeropts
]->text
,
1581 noautoconf
= (argc
> idx_routeropts
+ 1
1582 || strmatch(argv
[idx_routeropts
]->text
,
1588 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1589 struct zebra_if
*zebra_if
= ifp
->info
;
1591 struct rtadv_prefix rp
;
1593 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1595 vty_out(vty
, "Malformed IPv6 prefix\n");
1596 return CMD_WARNING_CONFIG_FAILED
;
1598 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1599 rp
.AdvOnLinkFlag
= !offlink
;
1600 rp
.AdvAutonomousFlag
= !noautoconf
;
1601 rp
.AdvRouterAddressFlag
= routeraddr
;
1602 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1603 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1606 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1608 : strtoll(lifetime
, NULL
, 10);
1609 rp
.AdvPreferredLifetime
=
1610 strmatch(preflifetime
, "infinite")
1612 : strtoll(preflifetime
, NULL
, 10);
1613 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1614 vty_out(vty
, "Invalid preferred lifetime\n");
1615 return CMD_WARNING_CONFIG_FAILED
;
1619 rtadv_prefix_set(zebra_if
, &rp
);
1624 DEFUN (no_ipv6_nd_prefix
,
1625 no_ipv6_nd_prefix_cmd
,
1626 "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]>]",
1628 "Interface IPv6 config commands\n"
1629 "Neighbor discovery\n"
1630 "Prefix information\n"
1632 "Valid lifetime in seconds\n"
1633 "Infinite valid lifetime\n"
1634 "Preferred lifetime in seconds\n"
1635 "Infinite preferred lifetime\n"
1636 "Set Router Address flag\n"
1637 "Do not use prefix for onlink determination\n"
1638 "Do not use prefix for autoconfiguration\n"
1639 "Do not use prefix for autoconfiguration\n"
1640 "Do not use prefix for onlink determination\n")
1642 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1643 struct zebra_if
*zebra_if
= ifp
->info
;
1645 struct rtadv_prefix rp
;
1646 char *prefix
= argv
[4]->arg
;
1648 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1650 vty_out(vty
, "Malformed IPv6 prefix\n");
1651 return CMD_WARNING_CONFIG_FAILED
;
1653 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1655 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1657 vty_out(vty
, "Non-existant IPv6 prefix\n");
1658 return CMD_WARNING_CONFIG_FAILED
;
1664 DEFUN (ipv6_nd_router_preference
,
1665 ipv6_nd_router_preference_cmd
,
1666 "ipv6 nd router-preference <high|medium|low>",
1667 "Interface IPv6 config commands\n"
1668 "Neighbor discovery\n"
1669 "Default router preference\n"
1670 "High default router preference\n"
1671 "Medium default router preference (default)\n"
1672 "Low default router preference\n")
1674 int idx_high_medium_low
= 3;
1675 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1676 struct zebra_if
*zif
= ifp
->info
;
1679 while (0 != rtadv_pref_strs
[i
]) {
1680 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1683 zif
->rtadv
.DefaultPreference
= i
;
1689 return CMD_ERR_NO_MATCH
;
1692 DEFUN (no_ipv6_nd_router_preference
,
1693 no_ipv6_nd_router_preference_cmd
,
1694 "no ipv6 nd router-preference [<high|medium|low>]",
1696 "Interface IPv6 config commands\n"
1697 "Neighbor discovery\n"
1698 "Default router preference\n"
1699 "High default router preference\n"
1700 "Medium default router preference (default)\n"
1701 "Low default router preference\n")
1703 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1704 struct zebra_if
*zif
= ifp
->info
;
1706 zif
->rtadv
.DefaultPreference
=
1707 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1714 "ipv6 nd mtu (1-65535)",
1715 "Interface IPv6 config commands\n"
1716 "Neighbor discovery\n"
1721 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1722 struct zebra_if
*zif
= ifp
->info
;
1723 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1727 DEFUN (no_ipv6_nd_mtu
,
1729 "no ipv6 nd mtu [(1-65535)]",
1731 "Interface IPv6 config commands\n"
1732 "Neighbor discovery\n"
1736 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1737 struct zebra_if
*zif
= ifp
->info
;
1738 zif
->rtadv
.AdvLinkMTU
= 0;
1742 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
1744 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
1747 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
1749 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
1752 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
1753 struct rtadv_rdnss
*rdnss
)
1755 struct listnode
*node
;
1756 struct rtadv_rdnss
*p
;
1758 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1759 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
1764 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
1765 struct rtadv_rdnss
*rdnss
)
1767 struct rtadv_rdnss
*p
;
1769 p
= rtadv_rdnss_lookup(list
, rdnss
);
1773 p
= rtadv_rdnss_new();
1774 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
1775 listnode_add(list
, p
);
1780 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1782 struct rtadv_rdnss
*p
;
1784 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1785 p
->lifetime
= rdnss
->lifetime
;
1786 p
->lifetime_set
= rdnss
->lifetime_set
;
1789 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1791 struct rtadv_rdnss
*p
;
1793 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1795 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
1796 rtadv_rdnss_free(p
);
1803 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
1805 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
1808 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
1810 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
1813 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
1814 struct rtadv_dnssl
*dnssl
)
1816 struct listnode
*node
;
1817 struct rtadv_dnssl
*p
;
1819 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1820 if (!strcasecmp(p
->name
, dnssl
->name
))
1825 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
1826 struct rtadv_dnssl
*dnssl
)
1828 struct rtadv_dnssl
*p
;
1830 p
= rtadv_dnssl_lookup(list
, dnssl
);
1834 p
= rtadv_dnssl_new();
1835 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1836 listnode_add(list
, p
);
1841 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1843 struct rtadv_dnssl
*p
;
1845 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1846 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1849 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1851 struct rtadv_dnssl
*p
;
1853 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1855 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
1856 rtadv_dnssl_free(p
);
1864 * Convert dotted domain name (with or without trailing root zone dot) to
1865 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
1866 * to strlen(in) + 2 octets to out.
1868 * Returns the number of octets written to out or -1 if in does not constitute
1869 * a valid domain name.
1871 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
1873 const char *label_start
, *label_end
;
1879 while (*label_start
) {
1882 label_end
= strchr(label_start
, '.');
1883 if (label_end
== NULL
)
1884 label_end
= label_start
+ strlen(label_start
);
1886 label_len
= label_end
- label_start
;
1887 if (label_len
>= 64)
1888 return -1; /* labels must be 63 octets or less */
1890 out
[outp
++] = (uint8_t)label_len
;
1891 memcpy(out
+ outp
, label_start
, label_len
);
1893 label_start
+= label_len
;
1894 if (*label_start
== '.')
1902 DEFUN(ipv6_nd_rdnss
,
1904 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1905 "Interface IPv6 config commands\n"
1906 "Neighbor discovery\n"
1907 "Recursive DNS server information\n"
1909 "Valid lifetime in seconds\n"
1910 "Infinite valid lifetime\n")
1912 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1913 struct zebra_if
*zif
= ifp
->info
;
1914 struct rtadv_rdnss rdnss
= {};
1916 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
1917 vty_out(vty
, "Malformed IPv6 address\n");
1918 return CMD_WARNING_CONFIG_FAILED
;
1921 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1923 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
1925 : strtoll(lifetime
, NULL
, 10);
1926 rdnss
.lifetime_set
= 1;
1929 rtadv_rdnss_set(zif
, &rdnss
);
1934 DEFUN(no_ipv6_nd_rdnss
,
1935 no_ipv6_nd_rdnss_cmd
,
1936 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1938 "Interface IPv6 config commands\n"
1939 "Neighbor discovery\n"
1940 "Recursive DNS server information\n"
1942 "Valid lifetime in seconds\n"
1943 "Infinite valid lifetime\n")
1945 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1946 struct zebra_if
*zif
= ifp
->info
;
1947 struct rtadv_rdnss rdnss
= {};
1949 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
1950 vty_out(vty
, "Malformed IPv6 address\n");
1951 return CMD_WARNING_CONFIG_FAILED
;
1953 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
1954 vty_out(vty
, "Non-existant RDNSS address\n");
1955 return CMD_WARNING_CONFIG_FAILED
;
1961 DEFUN(ipv6_nd_dnssl
,
1963 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1964 "Interface IPv6 config commands\n"
1965 "Neighbor discovery\n"
1966 "DNS search list information\n"
1967 "Domain name suffix\n"
1968 "Valid lifetime in seconds\n"
1969 "Infinite valid lifetime\n")
1971 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1972 struct zebra_if
*zif
= ifp
->info
;
1973 struct rtadv_dnssl dnssl
= {};
1977 len
= strlcpy(dnssl
.name
, argv
[3]->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] == '.') {
1984 * Allow, but don't require, a trailing dot signifying the root
1985 * zone. Canonicalize by cutting it off if present.
1987 dnssl
.name
[len
- 1] = '\0';
1991 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1993 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
1995 : strtoll(lifetime
, NULL
, 10);
1996 dnssl
.lifetime_set
= 1;
1999 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2001 vty_out(vty
, "Malformed DNS search domain\n");
2002 return CMD_WARNING_CONFIG_FAILED
;
2004 dnssl
.encoded_len
= ret
;
2005 rtadv_dnssl_set(zif
, &dnssl
);
2010 DEFUN(no_ipv6_nd_dnssl
,
2011 no_ipv6_nd_dnssl_cmd
,
2012 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2014 "Interface IPv6 config commands\n"
2015 "Neighbor discovery\n"
2016 "DNS search list information\n"
2017 "Domain name suffix\n"
2018 "Valid lifetime in seconds\n"
2019 "Infinite valid lifetime\n")
2021 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2022 struct zebra_if
*zif
= ifp
->info
;
2023 struct rtadv_dnssl dnssl
= {};
2026 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2027 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2028 vty_out(vty
, "Malformed DNS search domain\n");
2029 return CMD_WARNING_CONFIG_FAILED
;
2031 if (dnssl
.name
[len
- 1] == '.') {
2032 dnssl
.name
[len
- 1] = '\0';
2035 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2036 vty_out(vty
, "Non-existant DNS search domain\n");
2037 return CMD_WARNING_CONFIG_FAILED
;
2044 /* Dump interface ND information to vty. */
2045 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2047 struct zebra_if
*zif
;
2048 struct rtadvconf
*rtadv
;
2051 zif
= (struct zebra_if
*)ifp
->info
;
2052 rtadv
= &zif
->rtadv
;
2054 if (rtadv
->AdvSendAdvertisements
) {
2056 " ND advertised reachable time is %d milliseconds\n",
2057 rtadv
->AdvReachableTime
);
2059 " ND advertised retransmit interval is %d milliseconds\n",
2060 rtadv
->AdvRetransTimer
);
2061 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2062 zif
->ra_sent
, zif
->ra_rcvd
);
2063 interval
= rtadv
->MaxRtrAdvInterval
;
2064 if (interval
% 1000)
2066 " ND router advertisements are sent every "
2067 "%d milliseconds\n",
2071 " ND router advertisements are sent every "
2074 if (!rtadv
->UseFastRexmit
)
2076 " ND router advertisements do not use fast retransmit\n");
2078 if (rtadv
->AdvDefaultLifetime
!= -1)
2080 " ND router advertisements live for %d seconds\n",
2081 rtadv
->AdvDefaultLifetime
);
2084 " ND router advertisements lifetime tracks ra-interval\n");
2086 " ND router advertisement default router preference is "
2088 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2089 if (rtadv
->AdvManagedFlag
)
2091 " Hosts use DHCP to obtain routable addresses.\n");
2094 " Hosts use stateless autoconfig for addresses.\n");
2095 if (rtadv
->AdvHomeAgentFlag
) {
2097 " ND router advertisements with Home Agent flag bit set.\n");
2098 if (rtadv
->HomeAgentLifetime
!= -1)
2100 " Home Agent lifetime is %u seconds\n",
2101 rtadv
->HomeAgentLifetime
);
2104 " Home Agent lifetime tracks ra-lifetime\n");
2105 vty_out(vty
, " Home Agent preference is %u\n",
2106 rtadv
->HomeAgentPreference
);
2108 if (rtadv
->AdvIntervalOption
)
2110 " ND router advertisements with Adv. Interval option.\n");
2116 /* Write configuration about router advertisement. */
2117 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2119 struct zebra_if
*zif
;
2120 struct listnode
*node
;
2121 struct rtadv_prefix
*rprefix
;
2122 struct rtadv_rdnss
*rdnss
;
2123 struct rtadv_dnssl
*dnssl
;
2124 char buf
[PREFIX_STRLEN
];
2129 if (!(if_is_loopback(ifp
)
2130 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
2131 if (zif
->rtadv
.AdvSendAdvertisements
2132 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2133 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2136 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2137 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2138 if (interval
% 1000)
2139 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2141 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2142 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2146 if (zif
->rtadv
.AdvIntervalOption
)
2147 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2149 if (!zif
->rtadv
.UseFastRexmit
)
2150 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2152 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2153 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2154 zif
->rtadv
.AdvDefaultLifetime
);
2156 if (zif
->rtadv
.HomeAgentPreference
)
2157 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2158 zif
->rtadv
.HomeAgentPreference
);
2160 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2161 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2162 zif
->rtadv
.HomeAgentLifetime
);
2164 if (zif
->rtadv
.AdvHomeAgentFlag
)
2165 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2167 if (zif
->rtadv
.AdvReachableTime
)
2168 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2169 zif
->rtadv
.AdvReachableTime
);
2171 if (zif
->rtadv
.AdvManagedFlag
)
2172 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2174 if (zif
->rtadv
.AdvOtherConfigFlag
)
2175 vty_out(vty
, " ipv6 nd other-config-flag\n");
2177 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2178 vty_out(vty
, " ipv6 nd router-preference %s\n",
2179 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2181 if (zif
->rtadv
.AdvLinkMTU
)
2182 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2184 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
2185 vty_out(vty
, " ipv6 nd prefix %s",
2186 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
2187 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2188 || (rprefix
->AdvPreferredLifetime
2189 != RTADV_PREFERRED_LIFETIME
)) {
2190 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2191 vty_out(vty
, " infinite");
2193 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
2194 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2195 vty_out(vty
, " infinite");
2198 rprefix
->AdvPreferredLifetime
);
2200 if (!rprefix
->AdvOnLinkFlag
)
2201 vty_out(vty
, " off-link");
2202 if (!rprefix
->AdvAutonomousFlag
)
2203 vty_out(vty
, " no-autoconfig");
2204 if (rprefix
->AdvRouterAddressFlag
)
2205 vty_out(vty
, " router-address");
2208 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2209 char buf
[INET6_ADDRSTRLEN
];
2211 vty_out(vty
, " ipv6 nd rdnss %s",
2212 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2213 if (rdnss
->lifetime_set
) {
2214 if (rdnss
->lifetime
== UINT32_MAX
)
2215 vty_out(vty
, " infinite");
2217 vty_out(vty
, " %u", rdnss
->lifetime
);
2221 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2222 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2223 if (dnssl
->lifetime_set
) {
2224 if (dnssl
->lifetime
== UINT32_MAX
)
2225 vty_out(vty
, " infinite");
2227 vty_out(vty
, " %u", dnssl
->lifetime
);
2235 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2237 struct rtadv
*rtadv
= &zvrf
->rtadv
;
2241 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2243 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2247 THREAD_OFF(rtadv
->ra_timer
);
2248 THREAD_OFF(rtadv
->ra_read
);
2251 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2254 case RTADV_TIMER_MSEC
:
2255 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2259 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2268 void rtadv_init(struct zebra_vrf
*zvrf
)
2270 if (vrf_is_backend_netns()) {
2271 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2272 zrouter
.rtadv_sock
= -1;
2274 zvrf
->rtadv
.sock
= -1;
2275 if (zrouter
.rtadv_sock
< 0)
2276 zrouter
.rtadv_sock
=
2277 rtadv_make_socket(zvrf
->zns
->ns_id
);
2281 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2283 rtadv_event(zvrf
, RTADV_STOP
, 0);
2284 if (zvrf
->rtadv
.sock
>= 0) {
2285 close(zvrf
->rtadv
.sock
);
2286 zvrf
->rtadv
.sock
= -1;
2287 } else if (zrouter
.rtadv_sock
>= 0) {
2288 close(zrouter
.rtadv_sock
);
2289 zrouter
.rtadv_sock
= -1;
2291 zvrf
->rtadv
.adv_if_count
= 0;
2292 zvrf
->rtadv
.adv_msec_if_count
= 0;
2295 void rtadv_cmd_init(void)
2297 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2298 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2300 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2301 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2302 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2303 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2304 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2305 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2306 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2307 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2308 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2309 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2310 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2311 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2312 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2313 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2314 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2315 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2316 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2317 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2318 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2319 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2320 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2321 install_element(INTERFACE_NODE
,
2322 &ipv6_nd_adv_interval_config_option_cmd
);
2323 install_element(INTERFACE_NODE
,
2324 &no_ipv6_nd_adv_interval_config_option_cmd
);
2325 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2326 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2327 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2328 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2329 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2330 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2331 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2332 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2333 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2334 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2337 static int if_join_all_router(int sock
, struct interface
*ifp
)
2341 struct ipv6_mreq mreq
;
2343 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2344 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2345 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2347 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2350 flog_err_sys(EC_LIB_SOCKET
,
2351 "%s(%u): Failed to join group, socket %u error %s",
2352 ifp
->name
, ifp
->ifindex
, sock
,
2353 safe_strerror(errno
));
2355 if (IS_ZEBRA_DEBUG_EVENT
)
2357 "%s(%u): Join All-Routers multicast group, socket %u",
2358 ifp
->name
, ifp
->ifindex
, sock
);
2363 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2367 struct ipv6_mreq mreq
;
2369 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2370 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2371 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2373 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2378 "%s(%u): Failed to leave group, socket %u error %s",
2379 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
2381 if (IS_ZEBRA_DEBUG_EVENT
)
2383 "%s(%u): Leave All-Routers multicast group, socket %u",
2384 ifp
->name
, ifp
->ifindex
, sock
);
2390 void rtadv_init(struct zebra_vrf
*zvrf
)
2394 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2398 void rtadv_cmd_init(void)
2402 #endif /* HAVE_RTADV */