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
)
173 struct cmsghdr
*cmsgptr
;
174 struct in6_pktinfo
*pkt
;
175 struct sockaddr_in6 addr
;
176 static void *adata
= NULL
;
177 unsigned char buf
[RTADV_MSG_SIZE
];
178 struct nd_router_advert
*rtadv
;
181 struct zebra_if
*zif
;
182 struct rtadv_prefix
*rprefix
;
183 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
184 0, 0, 0, 0, 0, 0, 0, 1};
185 struct listnode
*node
;
186 uint16_t pkt_RouterLifetime
;
189 * Allocate control message bufffer. This is dynamic because
190 * CMSG_SPACE is not guaranteed not to call a function. Note that
191 * the size will be different on different architectures due to
192 * differing alignment rules.
195 /* XXX Free on shutdown. */
196 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
200 "rtadv_send_packet: can't malloc control data");
205 /* Logging of packet. */
206 if (IS_ZEBRA_DEBUG_PACKET
)
207 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
210 /* Fill in sockaddr_in6. */
211 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
212 addr
.sin6_family
= AF_INET6
;
214 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
215 #endif /* SIN6_LEN */
216 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
217 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
219 /* Fetch interface information. */
222 /* Make router advertisement message. */
223 rtadv
= (struct nd_router_advert
*)buf
;
225 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
226 rtadv
->nd_ra_code
= 0;
227 rtadv
->nd_ra_cksum
= 0;
229 rtadv
->nd_ra_curhoplimit
= 64;
231 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
232 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
234 : zif
->rtadv
.DefaultPreference
;
235 rtadv
->nd_ra_flags_reserved
<<= 3;
237 if (zif
->rtadv
.AdvManagedFlag
)
238 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
239 if (zif
->rtadv
.AdvOtherConfigFlag
)
240 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
241 if (zif
->rtadv
.AdvHomeAgentFlag
)
242 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
243 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
244 * AdvDefaultLifetime is by default based on the value of
245 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
246 * field of Router Advertisements. Given that this field is expressed
247 * in seconds, a small MaxRtrAdvInterval value can result in a zero
248 * value for this field. To prevent this, routers SHOULD keep
249 * AdvDefaultLifetime in at least one second, even if the use of
250 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
252 zif
->rtadv
.AdvDefaultLifetime
!= -1
253 ? zif
->rtadv
.AdvDefaultLifetime
254 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
255 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
256 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
257 rtadv
->nd_ra_retransmit
= htonl(0);
259 len
= sizeof(struct nd_router_advert
);
261 /* If both the Home Agent Preference and Home Agent Lifetime are set to
262 * their default values specified above, this option SHOULD NOT be
263 * included in the Router Advertisement messages sent by this home
264 * agent. -- RFC6275, 7.4 */
265 if (zif
->rtadv
.AdvHomeAgentFlag
266 && (zif
->rtadv
.HomeAgentPreference
267 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
268 struct nd_opt_homeagent_info
*ndopt_hai
=
269 (struct nd_opt_homeagent_info
*)(buf
+ len
);
270 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
271 ndopt_hai
->nd_opt_hai_len
= 1;
272 ndopt_hai
->nd_opt_hai_reserved
= 0;
273 ndopt_hai
->nd_opt_hai_preference
=
274 htons(zif
->rtadv
.HomeAgentPreference
);
275 /* 16-bit unsigned integer. The lifetime associated with the
277 * agent in units of seconds. The default value is the same as
279 * Router Lifetime, as specified in the main body of the Router
280 * Advertisement. The maximum value corresponds to 18.2 hours.
282 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
283 ndopt_hai
->nd_opt_hai_lifetime
=
284 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
285 ? zif
->rtadv
.HomeAgentLifetime
286 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
291 len
+= sizeof(struct nd_opt_homeagent_info
);
294 if (zif
->rtadv
.AdvIntervalOption
) {
295 struct nd_opt_adv_interval
*ndopt_adv
=
296 (struct nd_opt_adv_interval
*)(buf
+ len
);
297 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
298 ndopt_adv
->nd_opt_ai_len
= 1;
299 ndopt_adv
->nd_opt_ai_reserved
= 0;
300 ndopt_adv
->nd_opt_ai_interval
=
301 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
302 len
+= sizeof(struct nd_opt_adv_interval
);
305 /* Fill in prefix. */
306 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
307 struct nd_opt_prefix_info
*pinfo
;
309 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
311 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
312 pinfo
->nd_opt_pi_len
= 4;
313 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
315 pinfo
->nd_opt_pi_flags_reserved
= 0;
316 if (rprefix
->AdvOnLinkFlag
)
317 pinfo
->nd_opt_pi_flags_reserved
|=
318 ND_OPT_PI_FLAG_ONLINK
;
319 if (rprefix
->AdvAutonomousFlag
)
320 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
321 if (rprefix
->AdvRouterAddressFlag
)
322 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
324 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
325 pinfo
->nd_opt_pi_preferred_time
=
326 htonl(rprefix
->AdvPreferredLifetime
);
327 pinfo
->nd_opt_pi_reserved2
= 0;
329 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
330 &rprefix
->prefix
.prefix
);
334 uint8_t buf
[INET6_ADDRSTRLEN
];
336 zlog_debug("DEBUG %s",
337 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
338 buf
, INET6_ADDRSTRLEN
));
342 len
+= sizeof(struct nd_opt_prefix_info
);
345 /* Hardware address. */
346 if (ifp
->hw_addr_len
!= 0) {
347 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
349 /* Option length should be rounded up to next octet if
350 the link address does not end on an octet boundary. */
351 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
353 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
354 len
+= ifp
->hw_addr_len
;
356 /* Pad option to end on an octet boundary. */
357 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
358 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
362 if (zif
->rtadv
.AdvLinkMTU
) {
363 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
364 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
365 opt
->nd_opt_mtu_len
= 1;
366 opt
->nd_opt_mtu_reserved
= 0;
367 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
368 len
+= sizeof(struct nd_opt_mtu
);
372 * There is no limit on the number of configurable recursive DNS
373 * servers or search list entries. We don't want the RA message
374 * to exceed the link's MTU (risking fragmentation) or even
375 * blow the stack buffer allocated for it.
377 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
379 /* Recursive DNS servers */
380 struct rtadv_rdnss
*rdnss
;
382 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
384 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
386 if (len
+ opt_len
> max_len
) {
388 "%s(%u): Tx RA: RDNSS option would exceed MTU, omitting it",
389 ifp
->name
, ifp
->ifindex
);
392 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
394 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
395 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
396 opt
->nd_opt_rdnss_reserved
= 0;
397 opt
->nd_opt_rdnss_lifetime
= htonl(
400 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
402 len
+= sizeof(struct nd_opt_rdnss
);
404 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
405 len
+= sizeof(struct in6_addr
);
408 /* DNS search list */
409 struct rtadv_dnssl
*dnssl
;
411 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
412 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
413 + ((dnssl
->encoded_len
+ 7) & ~7);
415 if (len
+ opt_len
> max_len
) {
417 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
418 ifp
->name
, ifp
->ifindex
);
421 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
423 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
424 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
425 opt
->nd_opt_dnssl_reserved
= 0;
426 opt
->nd_opt_dnssl_lifetime
= htonl(
429 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
431 len
+= sizeof(struct nd_opt_dnssl
);
433 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
434 len
+= dnssl
->encoded_len
;
436 /* Zero-pad to 8-octet boundary */
443 msg
.msg_name
= (void *)&addr
;
444 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
447 msg
.msg_control
= (void *)adata
;
448 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
453 cmsgptr
= CMSG_FIRSTHDR(&msg
);
454 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
455 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
456 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
458 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
459 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
460 pkt
->ipi6_ifindex
= ifp
->ifindex
;
462 ret
= sendmsg(sock
, &msg
, 0);
464 flog_err_sys(EC_LIB_SOCKET
,
465 "%s(%u): Tx RA failed, socket %u error %d (%s)",
466 ifp
->name
, ifp
->ifindex
, sock
, errno
,
467 safe_strerror(errno
));
472 static int rtadv_timer(struct thread
*thread
)
474 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
476 struct interface
*ifp
;
477 struct zebra_if
*zif
;
480 zvrf
->rtadv
.ra_timer
= NULL
;
481 if (zvrf
->rtadv
.adv_msec_if_count
== 0) {
482 period
= 1000; /* 1 s */
483 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
485 period
= 10; /* 10 ms */
486 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
489 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
490 FOR_ALL_INTERFACES (vrf
, ifp
) {
491 if (if_is_loopback(ifp
)
492 || CHECK_FLAG(ifp
->status
,
493 ZEBRA_INTERFACE_VRF_LOOPBACK
)
494 || !if_is_operative(ifp
))
499 if (zif
->rtadv
.AdvSendAdvertisements
) {
500 if (zif
->rtadv
.inFastRexmit
501 && zif
->rtadv
.UseFastRexmit
) {
502 /* We assume we fast rexmit every sec so
505 if (--zif
->rtadv
.NumFastReXmitsRemain
507 zif
->rtadv
.inFastRexmit
= 0;
509 if (IS_ZEBRA_DEBUG_SEND
)
511 "Fast RA Rexmit on interface %s",
514 rtadv_send_packet(rtadv_get_socket(zvrf
),
517 zif
->rtadv
.AdvIntervalTimer
-= period
;
518 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
520 MaxRtrAdvInterval each
521 time isn't what section
522 6.2.4 of RFC4861 tells to do.
524 zif
->rtadv
.AdvIntervalTimer
=
528 rtadv_get_socket(zvrf
),
538 static void rtadv_process_solicit(struct interface
*ifp
)
540 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
541 struct zebra_if
*zif
;
547 * If FastRetransmit is enabled, send the RA immediately.
548 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
549 * (3 seconds) since the last RA was sent, send it now and reset
550 * the timer to start at the max (configured) again.
551 * If not enabled and it is less than 3 seconds since the last
552 * RA packet was sent, set the timer for 3 seconds so the next
553 * one will be sent with a minimum of 3 seconds between RAs.
556 if ((zif
->rtadv
.UseFastRexmit
)
557 || (zif
->rtadv
.AdvIntervalTimer
<=
558 (zif
->rtadv
.MaxRtrAdvInterval
- MIN_DELAY_BETWEEN_RAS
))) {
559 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
);
560 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
562 zif
->rtadv
.AdvIntervalTimer
= MIN_DELAY_BETWEEN_RAS
;
566 * This function processes optional attributes off of
567 * end of a RA packet received. At this point in
568 * time we only care about this in one situation
569 * which is when a interface does not have a LL
570 * v6 address. We still need to be able to install
571 * the mac address for v4 to v6 resolution
573 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
574 struct interface
*ifp
,
575 struct sockaddr_in6
*addr
)
580 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
582 switch(opt_hdr
->nd_opt_type
) {
583 case ND_OPT_SOURCE_LINKADDR
:
584 mac
= (char *)(optional
+2);
585 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
586 &addr
->sin6_addr
, 1);
592 len
-= 8 * opt_hdr
->nd_opt_len
;
593 optional
+= 8 * opt_hdr
->nd_opt_len
;
597 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
598 struct interface
*ifp
,
599 struct sockaddr_in6
*addr
)
601 struct nd_router_advert
*radvert
;
602 char addr_str
[INET6_ADDRSTRLEN
];
603 struct zebra_if
*zif
;
608 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
610 if (len
< sizeof(struct nd_router_advert
)) {
611 if (IS_ZEBRA_DEBUG_PACKET
)
612 zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
613 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
617 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
618 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
619 len
- sizeof(struct nd_router_advert
),
621 if (IS_ZEBRA_DEBUG_PACKET
)
622 zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s",
623 ifp
->name
, ifp
->ifindex
, addr_str
);
627 radvert
= (struct nd_router_advert
*)msg
;
629 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
630 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
632 EC_ZEBRA_RA_PARAM_MISMATCH
,
633 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
634 ifp
->name
, ifp
->ifindex
, addr_str
);
637 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
638 && !zif
->rtadv
.AdvManagedFlag
) {
640 EC_ZEBRA_RA_PARAM_MISMATCH
,
641 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
642 ifp
->name
, ifp
->ifindex
, addr_str
);
645 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
646 && !zif
->rtadv
.AdvOtherConfigFlag
) {
648 EC_ZEBRA_RA_PARAM_MISMATCH
,
649 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
650 ifp
->name
, ifp
->ifindex
, addr_str
);
653 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
654 && (ntohl(radvert
->nd_ra_reachable
)
655 != zif
->rtadv
.AdvReachableTime
)) {
657 EC_ZEBRA_RA_PARAM_MISMATCH
,
658 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
659 ifp
->name
, ifp
->ifindex
, addr_str
);
662 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
663 && (ntohl(radvert
->nd_ra_retransmit
)
664 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
666 EC_ZEBRA_RA_PARAM_MISMATCH
,
667 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
668 ifp
->name
, ifp
->ifindex
, addr_str
);
671 /* Create entry for neighbor if not known. */
673 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
674 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
676 if (!nbr_connected_check(ifp
, &p
))
677 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
681 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
682 ifindex_t ifindex
, int hoplimit
,
683 struct sockaddr_in6
*from
,
684 struct zebra_vrf
*zvrf
)
686 struct icmp6_hdr
*icmph
;
687 struct interface
*ifp
;
688 struct zebra_if
*zif
;
689 char addr_str
[INET6_ADDRSTRLEN
];
691 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
693 /* Interface search. */
694 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
696 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
697 "RA/RS received on unknown IF %u from %s", ifindex
,
702 if (IS_ZEBRA_DEBUG_PACKET
)
703 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
704 ifp
->ifindex
, len
, addr_str
);
706 if (if_is_loopback(ifp
)
707 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
710 /* Check interface configuration. */
712 if (!zif
->rtadv
.AdvSendAdvertisements
)
715 /* ICMP message length check. */
716 if (len
< sizeof(struct icmp6_hdr
)) {
717 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
718 ifp
->name
, ifp
->ifindex
, len
);
722 icmph
= (struct icmp6_hdr
*)buf
;
724 /* ICMP message type check. */
725 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
726 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
727 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
728 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
732 /* Hoplimit check. */
733 if (hoplimit
>= 0 && hoplimit
!= 255) {
734 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
735 ifp
->ifindex
, hoplimit
);
739 /* Check ICMP message type. */
740 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
741 rtadv_process_solicit(ifp
);
742 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
743 rtadv_process_advert(buf
, len
, ifp
, from
);
748 static int rtadv_read(struct thread
*thread
)
752 uint8_t buf
[RTADV_MSG_SIZE
];
753 struct sockaddr_in6 from
;
754 ifindex_t ifindex
= 0;
756 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
758 sock
= THREAD_FD(thread
);
759 zvrf
->rtadv
.ra_read
= NULL
;
761 /* Register myself. */
762 rtadv_event(zvrf
, RTADV_READ
, sock
);
764 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
768 flog_err_sys(EC_LIB_SOCKET
,
769 "RA/RS recv failed, socket %u error %s", sock
,
770 safe_strerror(errno
));
774 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
779 static int rtadv_make_socket(ns_id_t ns_id
)
783 struct icmp6_filter filter
;
785 frr_with_privs(&zserv_privs
) {
787 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
795 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
800 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
805 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
810 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
815 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
821 ICMP6_FILTER_SETBLOCKALL(&filter
);
822 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
823 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
825 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
826 sizeof(struct icmp6_filter
));
828 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
836 static struct rtadv_prefix
*rtadv_prefix_new(void)
838 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
841 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
843 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
846 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
847 struct prefix_ipv6
*p
)
849 struct listnode
*node
;
850 struct rtadv_prefix
*rprefix
;
852 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
853 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
859 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
860 struct prefix_ipv6
*p
)
862 struct rtadv_prefix
*rprefix
;
864 rprefix
= rtadv_prefix_lookup(rplist
, p
);
868 rprefix
= rtadv_prefix_new();
869 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
870 listnode_add(rplist
, rprefix
);
875 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
877 struct rtadv_prefix
*rprefix
;
879 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
881 /* Set parameters. */
882 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
883 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
884 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
885 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
886 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
889 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
891 struct rtadv_prefix
*rprefix
;
893 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
894 if (rprefix
!= NULL
) {
895 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
896 rtadv_prefix_free(rprefix
);
902 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
903 ipv6_nd_suppress_ra_status status
)
905 struct zebra_if
*zif
;
906 struct zebra_vrf
*zvrf
;
909 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
911 if (status
== RA_SUPPRESS
) {
912 /* RA is currently enabled */
913 if (zif
->rtadv
.AdvSendAdvertisements
) {
914 zif
->rtadv
.AdvSendAdvertisements
= 0;
915 zif
->rtadv
.AdvIntervalTimer
= 0;
916 zvrf
->rtadv
.adv_if_count
--;
918 if_leave_all_router(rtadv_get_socket(zvrf
), ifp
);
920 if (zvrf
->rtadv
.adv_if_count
== 0)
921 rtadv_event(zvrf
, RTADV_STOP
, 0);
924 if (!zif
->rtadv
.AdvSendAdvertisements
) {
925 zif
->rtadv
.AdvSendAdvertisements
= 1;
926 zif
->rtadv
.AdvIntervalTimer
= 0;
927 zvrf
->rtadv
.adv_if_count
++;
929 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
930 && zif
->rtadv
.UseFastRexmit
) {
932 * Enable Fast RA only when RA interval is in
933 * secs and Fast RA retransmit is enabled
935 zif
->rtadv
.inFastRexmit
= 1;
936 zif
->rtadv
.NumFastReXmitsRemain
=
937 RTADV_NUM_FAST_REXMITS
;
940 if_join_all_router(rtadv_get_socket(zvrf
), ifp
);
942 if (zvrf
->rtadv
.adv_if_count
== 1)
943 rtadv_event(zvrf
, RTADV_START
,
944 rtadv_get_socket(zvrf
));
950 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
951 * Note that while the client could request RA on an interface on which the
952 * operator has not enabled RA, RA won't be disabled upon client request
953 * if the operator has explicitly enabled RA. The enable request can also
954 * specify a RA interval (in seconds).
956 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
960 struct interface
*ifp
;
961 struct zebra_if
*zif
;
966 /* Get interface index and RA interval. */
967 STREAM_GETL(s
, ifindex
);
968 STREAM_GETL(s
, ra_interval
);
970 if (IS_ZEBRA_DEBUG_EVENT
)
971 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
972 zvrf_id(zvrf
), ifindex
,
973 enable
? "enable" : "disable",
974 zebra_route_string(client
->proto
), ra_interval
);
976 /* Locate interface and check VRF match. */
977 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
979 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
980 "%u: IF %u RA %s client %s - interface unknown",
981 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
982 zebra_route_string(client
->proto
));
985 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
987 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
988 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
989 zebra_route_string(client
->proto
), ifp
->vrf_id
);
995 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
996 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
998 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
999 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1000 VTY_RA_INTERVAL_CONFIGURED
))
1001 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1003 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1004 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1005 VTY_RA_INTERVAL_CONFIGURED
))
1006 zif
->rtadv
.MaxRtrAdvInterval
=
1007 RTADV_MAX_RTR_ADV_INTERVAL
;
1008 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1009 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1015 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1017 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1019 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1021 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1024 DEFUN (ipv6_nd_ra_fast_retrans
,
1025 ipv6_nd_ra_fast_retrans_cmd
,
1026 "ipv6 nd ra-fast-retrans",
1027 "Interface IPv6 config commands\n"
1028 "Neighbor discovery\n"
1029 "Fast retransmit of RA packets\n")
1031 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1032 struct zebra_if
*zif
= ifp
->info
;
1034 if (if_is_loopback(ifp
)
1035 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1037 "Cannot configure IPv6 Router Advertisements on this interface\n");
1038 return CMD_WARNING_CONFIG_FAILED
;
1041 zif
->rtadv
.UseFastRexmit
= true;
1046 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1047 no_ipv6_nd_ra_fast_retrans_cmd
,
1048 "no ipv6 nd ra-fast-retrans",
1050 "Interface IPv6 config commands\n"
1051 "Neighbor discovery\n"
1052 "Fast retransmit of RA packets\n")
1054 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1055 struct zebra_if
*zif
= ifp
->info
;
1057 if (if_is_loopback(ifp
)
1058 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1060 "Cannot configure IPv6 Router Advertisements on this interface\n");
1061 return CMD_WARNING_CONFIG_FAILED
;
1064 zif
->rtadv
.UseFastRexmit
= false;
1069 DEFUN (ipv6_nd_suppress_ra
,
1070 ipv6_nd_suppress_ra_cmd
,
1071 "ipv6 nd suppress-ra",
1072 "Interface IPv6 config commands\n"
1073 "Neighbor discovery\n"
1074 "Suppress Router Advertisement\n")
1076 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1077 struct zebra_if
*zif
= ifp
->info
;
1079 if (if_is_loopback(ifp
)
1080 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1082 "Cannot configure IPv6 Router Advertisements on this interface\n");
1083 return CMD_WARNING_CONFIG_FAILED
;
1086 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1087 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1089 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1093 DEFUN (no_ipv6_nd_suppress_ra
,
1094 no_ipv6_nd_suppress_ra_cmd
,
1095 "no ipv6 nd suppress-ra",
1097 "Interface IPv6 config commands\n"
1098 "Neighbor discovery\n"
1099 "Suppress Router Advertisement\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 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1112 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1116 DEFUN (ipv6_nd_ra_interval_msec
,
1117 ipv6_nd_ra_interval_msec_cmd
,
1118 "ipv6 nd ra-interval msec (70-1800000)",
1119 "Interface IPv6 config commands\n"
1120 "Neighbor discovery\n"
1121 "Router Advertisement interval\n"
1122 "Router Advertisement interval in milliseconds\n"
1123 "Router Advertisement interval in milliseconds\n")
1126 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1128 struct zebra_if
*zif
= ifp
->info
;
1129 struct zebra_vrf
*zvrf
;
1131 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1133 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1134 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1135 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1137 "This ra-interval would conflict with configured ra-lifetime!\n");
1138 return CMD_WARNING_CONFIG_FAILED
;
1141 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1142 zvrf
->rtadv
.adv_msec_if_count
--;
1144 if (interval
% 1000)
1145 zvrf
->rtadv
.adv_msec_if_count
++;
1147 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1148 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1149 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1150 zif
->rtadv
.AdvIntervalTimer
= 0;
1155 DEFUN (ipv6_nd_ra_interval
,
1156 ipv6_nd_ra_interval_cmd
,
1157 "ipv6 nd ra-interval (1-1800)",
1158 "Interface IPv6 config commands\n"
1159 "Neighbor discovery\n"
1160 "Router Advertisement interval\n"
1161 "Router Advertisement interval in seconds\n")
1164 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1166 struct zebra_if
*zif
= ifp
->info
;
1167 struct zebra_vrf
*zvrf
;
1169 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1171 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1172 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1173 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1175 "This ra-interval would conflict with configured ra-lifetime!\n");
1176 return CMD_WARNING_CONFIG_FAILED
;
1179 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1180 zvrf
->rtadv
.adv_msec_if_count
--;
1182 /* convert to milliseconds */
1183 interval
= interval
* 1000;
1185 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1186 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1187 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1188 zif
->rtadv
.AdvIntervalTimer
= 0;
1193 DEFUN (no_ipv6_nd_ra_interval
,
1194 no_ipv6_nd_ra_interval_cmd
,
1195 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1197 "Interface IPv6 config commands\n"
1198 "Neighbor discovery\n"
1199 "Router Advertisement interval\n"
1200 "Router Advertisement interval in seconds\n"
1201 "Specify millisecond router advertisement interval\n"
1202 "Router Advertisement interval in milliseconds\n")
1204 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1205 struct zebra_if
*zif
= ifp
->info
;
1206 struct zebra_vrf
*zvrf
= NULL
;
1208 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1210 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1211 zvrf
->rtadv
.adv_msec_if_count
--;
1213 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1215 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1216 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1218 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1220 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1221 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1226 DEFUN (ipv6_nd_ra_lifetime
,
1227 ipv6_nd_ra_lifetime_cmd
,
1228 "ipv6 nd ra-lifetime (0-9000)",
1229 "Interface IPv6 config commands\n"
1230 "Neighbor discovery\n"
1232 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1235 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1236 struct zebra_if
*zif
= ifp
->info
;
1239 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1241 /* The value to be placed in the Router Lifetime field
1242 * of Router Advertisements sent from the interface,
1243 * in seconds. MUST be either zero or between
1244 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1245 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1247 "This ra-lifetime would conflict with configured ra-interval\n");
1248 return CMD_WARNING_CONFIG_FAILED
;
1251 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1256 DEFUN (no_ipv6_nd_ra_lifetime
,
1257 no_ipv6_nd_ra_lifetime_cmd
,
1258 "no ipv6 nd ra-lifetime [(0-9000)]",
1260 "Interface IPv6 config commands\n"
1261 "Neighbor discovery\n"
1263 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1265 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1266 struct zebra_if
*zif
= ifp
->info
;
1268 zif
->rtadv
.AdvDefaultLifetime
= -1;
1273 DEFUN (ipv6_nd_reachable_time
,
1274 ipv6_nd_reachable_time_cmd
,
1275 "ipv6 nd reachable-time (1-3600000)",
1276 "Interface IPv6 config commands\n"
1277 "Neighbor discovery\n"
1279 "Reachable time in milliseconds\n")
1282 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1283 struct zebra_if
*zif
= ifp
->info
;
1284 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1288 DEFUN (no_ipv6_nd_reachable_time
,
1289 no_ipv6_nd_reachable_time_cmd
,
1290 "no ipv6 nd reachable-time [(1-3600000)]",
1292 "Interface IPv6 config commands\n"
1293 "Neighbor discovery\n"
1295 "Reachable time in milliseconds\n")
1297 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1298 struct zebra_if
*zif
= ifp
->info
;
1300 zif
->rtadv
.AdvReachableTime
= 0;
1305 DEFUN (ipv6_nd_homeagent_preference
,
1306 ipv6_nd_homeagent_preference_cmd
,
1307 "ipv6 nd home-agent-preference (0-65535)",
1308 "Interface IPv6 config commands\n"
1309 "Neighbor discovery\n"
1310 "Home Agent preference\n"
1311 "preference value (default is 0, least preferred)\n")
1314 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1315 struct zebra_if
*zif
= ifp
->info
;
1316 zif
->rtadv
.HomeAgentPreference
=
1317 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1321 DEFUN (no_ipv6_nd_homeagent_preference
,
1322 no_ipv6_nd_homeagent_preference_cmd
,
1323 "no ipv6 nd home-agent-preference [(0-65535)]",
1325 "Interface IPv6 config commands\n"
1326 "Neighbor discovery\n"
1327 "Home Agent preference\n"
1328 "preference value (default is 0, least preferred)\n")
1330 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1331 struct zebra_if
*zif
= ifp
->info
;
1333 zif
->rtadv
.HomeAgentPreference
= 0;
1338 DEFUN (ipv6_nd_homeagent_lifetime
,
1339 ipv6_nd_homeagent_lifetime_cmd
,
1340 "ipv6 nd home-agent-lifetime (0-65520)",
1341 "Interface IPv6 config commands\n"
1342 "Neighbor discovery\n"
1343 "Home Agent lifetime\n"
1344 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1347 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1348 struct zebra_if
*zif
= ifp
->info
;
1349 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1353 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1354 no_ipv6_nd_homeagent_lifetime_cmd
,
1355 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1357 "Interface IPv6 config commands\n"
1358 "Neighbor discovery\n"
1359 "Home Agent lifetime\n"
1360 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1362 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1363 struct zebra_if
*zif
= ifp
->info
;
1365 zif
->rtadv
.HomeAgentLifetime
= -1;
1370 DEFUN (ipv6_nd_managed_config_flag
,
1371 ipv6_nd_managed_config_flag_cmd
,
1372 "ipv6 nd managed-config-flag",
1373 "Interface IPv6 config commands\n"
1374 "Neighbor discovery\n"
1375 "Managed address configuration flag\n")
1377 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1378 struct zebra_if
*zif
= ifp
->info
;
1380 zif
->rtadv
.AdvManagedFlag
= 1;
1385 DEFUN (no_ipv6_nd_managed_config_flag
,
1386 no_ipv6_nd_managed_config_flag_cmd
,
1387 "no ipv6 nd managed-config-flag",
1389 "Interface IPv6 config commands\n"
1390 "Neighbor discovery\n"
1391 "Managed address configuration flag\n")
1393 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1394 struct zebra_if
*zif
= ifp
->info
;
1396 zif
->rtadv
.AdvManagedFlag
= 0;
1401 DEFUN (ipv6_nd_homeagent_config_flag
,
1402 ipv6_nd_homeagent_config_flag_cmd
,
1403 "ipv6 nd home-agent-config-flag",
1404 "Interface IPv6 config commands\n"
1405 "Neighbor discovery\n"
1406 "Home Agent configuration flag\n")
1408 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1409 struct zebra_if
*zif
= ifp
->info
;
1411 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1416 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1417 no_ipv6_nd_homeagent_config_flag_cmd
,
1418 "no ipv6 nd home-agent-config-flag",
1420 "Interface IPv6 config commands\n"
1421 "Neighbor discovery\n"
1422 "Home Agent configuration flag\n")
1424 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1425 struct zebra_if
*zif
= ifp
->info
;
1427 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1432 DEFUN (ipv6_nd_adv_interval_config_option
,
1433 ipv6_nd_adv_interval_config_option_cmd
,
1434 "ipv6 nd adv-interval-option",
1435 "Interface IPv6 config commands\n"
1436 "Neighbor discovery\n"
1437 "Advertisement Interval Option\n")
1439 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1440 struct zebra_if
*zif
= ifp
->info
;
1442 zif
->rtadv
.AdvIntervalOption
= 1;
1447 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1448 no_ipv6_nd_adv_interval_config_option_cmd
,
1449 "no ipv6 nd adv-interval-option",
1451 "Interface IPv6 config commands\n"
1452 "Neighbor discovery\n"
1453 "Advertisement Interval Option\n")
1455 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1456 struct zebra_if
*zif
= ifp
->info
;
1458 zif
->rtadv
.AdvIntervalOption
= 0;
1463 DEFUN (ipv6_nd_other_config_flag
,
1464 ipv6_nd_other_config_flag_cmd
,
1465 "ipv6 nd other-config-flag",
1466 "Interface IPv6 config commands\n"
1467 "Neighbor discovery\n"
1468 "Other statefull configuration flag\n")
1470 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1471 struct zebra_if
*zif
= ifp
->info
;
1473 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1478 DEFUN (no_ipv6_nd_other_config_flag
,
1479 no_ipv6_nd_other_config_flag_cmd
,
1480 "no ipv6 nd other-config-flag",
1482 "Interface IPv6 config commands\n"
1483 "Neighbor discovery\n"
1484 "Other statefull configuration flag\n")
1486 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1487 struct zebra_if
*zif
= ifp
->info
;
1489 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1494 DEFUN (ipv6_nd_prefix
,
1496 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1497 "Interface IPv6 config commands\n"
1498 "Neighbor discovery\n"
1499 "Prefix information\n"
1501 "Valid lifetime in seconds\n"
1502 "Infinite valid lifetime\n"
1503 "Preferred lifetime in seconds\n"
1504 "Infinite preferred lifetime\n"
1505 "Set Router Address flag\n"
1506 "Do not use prefix for onlink determination\n"
1507 "Do not use prefix for autoconfiguration\n"
1508 "Do not use prefix for autoconfiguration\n"
1509 "Do not use prefix for onlink determination\n")
1512 char *prefix
= argv
[3]->arg
;
1513 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1514 || strmatch(argv
[4]->text
, "infinite"));
1515 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1517 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1519 char *lifetime
= NULL
, *preflifetime
= NULL
;
1520 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1522 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1524 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1529 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1531 offlink
= (argc
> idx_routeropts
+ 1
1532 || strmatch(argv
[idx_routeropts
]->text
,
1534 noautoconf
= (argc
> idx_routeropts
+ 1
1535 || strmatch(argv
[idx_routeropts
]->text
,
1541 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1542 struct zebra_if
*zebra_if
= ifp
->info
;
1544 struct rtadv_prefix rp
;
1546 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1548 vty_out(vty
, "Malformed IPv6 prefix\n");
1549 return CMD_WARNING_CONFIG_FAILED
;
1551 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1552 rp
.AdvOnLinkFlag
= !offlink
;
1553 rp
.AdvAutonomousFlag
= !noautoconf
;
1554 rp
.AdvRouterAddressFlag
= routeraddr
;
1555 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1556 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1559 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1561 : strtoll(lifetime
, NULL
, 10);
1562 rp
.AdvPreferredLifetime
=
1563 strmatch(preflifetime
, "infinite")
1565 : strtoll(preflifetime
, NULL
, 10);
1566 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1567 vty_out(vty
, "Invalid preferred lifetime\n");
1568 return CMD_WARNING_CONFIG_FAILED
;
1572 rtadv_prefix_set(zebra_if
, &rp
);
1577 DEFUN (no_ipv6_nd_prefix
,
1578 no_ipv6_nd_prefix_cmd
,
1579 "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]>]",
1581 "Interface IPv6 config commands\n"
1582 "Neighbor discovery\n"
1583 "Prefix information\n"
1585 "Valid lifetime in seconds\n"
1586 "Infinite valid lifetime\n"
1587 "Preferred lifetime in seconds\n"
1588 "Infinite preferred lifetime\n"
1589 "Set Router Address flag\n"
1590 "Do not use prefix for onlink determination\n"
1591 "Do not use prefix for autoconfiguration\n"
1592 "Do not use prefix for autoconfiguration\n"
1593 "Do not use prefix for onlink determination\n")
1595 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1596 struct zebra_if
*zebra_if
= ifp
->info
;
1598 struct rtadv_prefix rp
;
1599 char *prefix
= argv
[4]->arg
;
1601 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1603 vty_out(vty
, "Malformed IPv6 prefix\n");
1604 return CMD_WARNING_CONFIG_FAILED
;
1606 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1608 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1610 vty_out(vty
, "Non-existant IPv6 prefix\n");
1611 return CMD_WARNING_CONFIG_FAILED
;
1617 DEFUN (ipv6_nd_router_preference
,
1618 ipv6_nd_router_preference_cmd
,
1619 "ipv6 nd router-preference <high|medium|low>",
1620 "Interface IPv6 config commands\n"
1621 "Neighbor discovery\n"
1622 "Default router preference\n"
1623 "High default router preference\n"
1624 "Medium default router preference (default)\n"
1625 "Low default router preference\n")
1627 int idx_high_medium_low
= 3;
1628 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1629 struct zebra_if
*zif
= ifp
->info
;
1632 while (0 != rtadv_pref_strs
[i
]) {
1633 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1636 zif
->rtadv
.DefaultPreference
= i
;
1642 return CMD_ERR_NO_MATCH
;
1645 DEFUN (no_ipv6_nd_router_preference
,
1646 no_ipv6_nd_router_preference_cmd
,
1647 "no ipv6 nd router-preference [<high|medium|low>]",
1649 "Interface IPv6 config commands\n"
1650 "Neighbor discovery\n"
1651 "Default router preference\n"
1652 "High default router preference\n"
1653 "Medium default router preference (default)\n"
1654 "Low default router preference\n")
1656 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1657 struct zebra_if
*zif
= ifp
->info
;
1659 zif
->rtadv
.DefaultPreference
=
1660 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1667 "ipv6 nd mtu (1-65535)",
1668 "Interface IPv6 config commands\n"
1669 "Neighbor discovery\n"
1674 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1675 struct zebra_if
*zif
= ifp
->info
;
1676 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1680 DEFUN (no_ipv6_nd_mtu
,
1682 "no ipv6 nd mtu [(1-65535)]",
1684 "Interface IPv6 config commands\n"
1685 "Neighbor discovery\n"
1689 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1690 struct zebra_if
*zif
= ifp
->info
;
1691 zif
->rtadv
.AdvLinkMTU
= 0;
1695 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
1697 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
1700 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
1702 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
1705 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
1706 struct rtadv_rdnss
*rdnss
)
1708 struct listnode
*node
;
1709 struct rtadv_rdnss
*p
;
1711 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1712 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
1717 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
1718 struct rtadv_rdnss
*rdnss
)
1720 struct rtadv_rdnss
*p
;
1722 p
= rtadv_rdnss_lookup(list
, rdnss
);
1726 p
= rtadv_rdnss_new();
1727 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
1728 listnode_add(list
, p
);
1733 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1735 struct rtadv_rdnss
*p
;
1737 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1738 p
->lifetime
= rdnss
->lifetime
;
1739 p
->lifetime_set
= rdnss
->lifetime_set
;
1742 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1744 struct rtadv_rdnss
*p
;
1746 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1748 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
1749 rtadv_rdnss_free(p
);
1756 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
1758 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
1761 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
1763 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
1766 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
1767 struct rtadv_dnssl
*dnssl
)
1769 struct listnode
*node
;
1770 struct rtadv_dnssl
*p
;
1772 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1773 if (!strcasecmp(p
->name
, dnssl
->name
))
1778 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
1779 struct rtadv_dnssl
*dnssl
)
1781 struct rtadv_dnssl
*p
;
1783 p
= rtadv_dnssl_lookup(list
, dnssl
);
1787 p
= rtadv_dnssl_new();
1788 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1789 listnode_add(list
, p
);
1794 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1796 struct rtadv_dnssl
*p
;
1798 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1799 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1802 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1804 struct rtadv_dnssl
*p
;
1806 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1808 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
1809 rtadv_dnssl_free(p
);
1817 * Convert dotted domain name (with or without trailing root zone dot) to
1818 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
1819 * to strlen(in) + 2 octets to out.
1821 * Returns the number of octets written to out or -1 if in does not constitute
1822 * a valid domain name.
1824 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
1826 const char *label_start
, *label_end
;
1832 while (*label_start
) {
1835 label_end
= strchr(label_start
, '.');
1836 if (label_end
== NULL
)
1837 label_end
= label_start
+ strlen(label_start
);
1839 label_len
= label_end
- label_start
;
1840 if (label_len
>= 64)
1841 return -1; /* labels must be 63 octets or less */
1843 out
[outp
++] = (uint8_t)label_len
;
1844 memcpy(out
+ outp
, label_start
, label_len
);
1846 label_start
+= label_len
;
1847 if (*label_start
== '.')
1855 DEFUN(ipv6_nd_rdnss
,
1857 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1858 "Interface IPv6 config commands\n"
1859 "Neighbor discovery\n"
1860 "Recursive DNS server information\n"
1862 "Valid lifetime in seconds\n"
1863 "Infinite valid lifetime\n")
1865 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1866 struct zebra_if
*zif
= ifp
->info
;
1867 struct rtadv_rdnss rdnss
= {};
1869 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
1870 vty_out(vty
, "Malformed IPv6 address\n");
1871 return CMD_WARNING_CONFIG_FAILED
;
1874 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1876 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
1878 : strtoll(lifetime
, NULL
, 10);
1879 rdnss
.lifetime_set
= 1;
1882 rtadv_rdnss_set(zif
, &rdnss
);
1887 DEFUN(no_ipv6_nd_rdnss
,
1888 no_ipv6_nd_rdnss_cmd
,
1889 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1891 "Interface IPv6 config commands\n"
1892 "Neighbor discovery\n"
1893 "Recursive DNS server information\n"
1895 "Valid lifetime in seconds\n"
1896 "Infinite valid lifetime\n")
1898 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1899 struct zebra_if
*zif
= ifp
->info
;
1900 struct rtadv_rdnss rdnss
= {};
1902 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
1903 vty_out(vty
, "Malformed IPv6 address\n");
1904 return CMD_WARNING_CONFIG_FAILED
;
1906 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
1907 vty_out(vty
, "Non-existant RDNSS address\n");
1908 return CMD_WARNING_CONFIG_FAILED
;
1914 DEFUN(ipv6_nd_dnssl
,
1916 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1917 "Interface IPv6 config commands\n"
1918 "Neighbor discovery\n"
1919 "DNS search list information\n"
1920 "Domain name suffix\n"
1921 "Valid lifetime in seconds\n"
1922 "Infinite valid lifetime\n")
1924 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1925 struct zebra_if
*zif
= ifp
->info
;
1926 struct rtadv_dnssl dnssl
= {};
1930 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
1931 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1932 vty_out(vty
, "Malformed DNS search domain\n");
1933 return CMD_WARNING_CONFIG_FAILED
;
1935 if (dnssl
.name
[len
- 1] == '.') {
1937 * Allow, but don't require, a trailing dot signifying the root
1938 * zone. Canonicalize by cutting it off if present.
1940 dnssl
.name
[len
- 1] = '\0';
1944 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1946 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
1948 : strtoll(lifetime
, NULL
, 10);
1949 dnssl
.lifetime_set
= 1;
1952 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
1954 vty_out(vty
, "Malformed DNS search domain\n");
1955 return CMD_WARNING_CONFIG_FAILED
;
1957 dnssl
.encoded_len
= ret
;
1958 rtadv_dnssl_set(zif
, &dnssl
);
1963 DEFUN(no_ipv6_nd_dnssl
,
1964 no_ipv6_nd_dnssl_cmd
,
1965 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1967 "Interface IPv6 config commands\n"
1968 "Neighbor discovery\n"
1969 "DNS search list information\n"
1970 "Domain name suffix\n"
1971 "Valid lifetime in seconds\n"
1972 "Infinite valid lifetime\n")
1974 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1975 struct zebra_if
*zif
= ifp
->info
;
1976 struct rtadv_dnssl dnssl
= {};
1979 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
1980 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1981 vty_out(vty
, "Malformed DNS search domain\n");
1982 return CMD_WARNING_CONFIG_FAILED
;
1984 if (dnssl
.name
[len
- 1] == '.') {
1985 dnssl
.name
[len
- 1] = '\0';
1988 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
1989 vty_out(vty
, "Non-existant DNS search domain\n");
1990 return CMD_WARNING_CONFIG_FAILED
;
1997 /* Dump interface ND information to vty. */
1998 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2000 struct zebra_if
*zif
;
2001 struct rtadvconf
*rtadv
;
2004 zif
= (struct zebra_if
*)ifp
->info
;
2005 rtadv
= &zif
->rtadv
;
2007 if (rtadv
->AdvSendAdvertisements
) {
2009 " ND advertised reachable time is %d milliseconds\n",
2010 rtadv
->AdvReachableTime
);
2012 " ND advertised retransmit interval is %d milliseconds\n",
2013 rtadv
->AdvRetransTimer
);
2014 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2015 zif
->ra_sent
, zif
->ra_rcvd
);
2016 interval
= rtadv
->MaxRtrAdvInterval
;
2017 if (interval
% 1000)
2019 " ND router advertisements are sent every "
2020 "%d milliseconds\n",
2024 " ND router advertisements are sent every "
2027 if (!rtadv
->UseFastRexmit
)
2029 " ND router advertisements do not use fast retransmit\n");
2031 if (rtadv
->AdvDefaultLifetime
!= -1)
2033 " ND router advertisements live for %d seconds\n",
2034 rtadv
->AdvDefaultLifetime
);
2037 " ND router advertisements lifetime tracks ra-interval\n");
2039 " ND router advertisement default router preference is "
2041 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2042 if (rtadv
->AdvManagedFlag
)
2044 " Hosts use DHCP to obtain routable addresses.\n");
2047 " Hosts use stateless autoconfig for addresses.\n");
2048 if (rtadv
->AdvHomeAgentFlag
) {
2050 " ND router advertisements with Home Agent flag bit set.\n");
2051 if (rtadv
->HomeAgentLifetime
!= -1)
2053 " Home Agent lifetime is %u seconds\n",
2054 rtadv
->HomeAgentLifetime
);
2057 " Home Agent lifetime tracks ra-lifetime\n");
2058 vty_out(vty
, " Home Agent preference is %u\n",
2059 rtadv
->HomeAgentPreference
);
2061 if (rtadv
->AdvIntervalOption
)
2063 " ND router advertisements with Adv. Interval option.\n");
2069 /* Write configuration about router advertisement. */
2070 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2072 struct zebra_if
*zif
;
2073 struct listnode
*node
;
2074 struct rtadv_prefix
*rprefix
;
2075 struct rtadv_rdnss
*rdnss
;
2076 struct rtadv_dnssl
*dnssl
;
2077 char buf
[PREFIX_STRLEN
];
2082 if (!(if_is_loopback(ifp
)
2083 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
2084 if (zif
->rtadv
.AdvSendAdvertisements
2085 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2086 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2089 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2090 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2091 if (interval
% 1000)
2092 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2094 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2095 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2099 if (zif
->rtadv
.AdvIntervalOption
)
2100 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2102 if (!zif
->rtadv
.UseFastRexmit
)
2103 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2105 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2106 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2107 zif
->rtadv
.AdvDefaultLifetime
);
2109 if (zif
->rtadv
.HomeAgentPreference
)
2110 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2111 zif
->rtadv
.HomeAgentPreference
);
2113 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2114 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2115 zif
->rtadv
.HomeAgentLifetime
);
2117 if (zif
->rtadv
.AdvHomeAgentFlag
)
2118 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2120 if (zif
->rtadv
.AdvReachableTime
)
2121 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2122 zif
->rtadv
.AdvReachableTime
);
2124 if (zif
->rtadv
.AdvManagedFlag
)
2125 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2127 if (zif
->rtadv
.AdvOtherConfigFlag
)
2128 vty_out(vty
, " ipv6 nd other-config-flag\n");
2130 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2131 vty_out(vty
, " ipv6 nd router-preference %s\n",
2132 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2134 if (zif
->rtadv
.AdvLinkMTU
)
2135 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2137 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
2138 vty_out(vty
, " ipv6 nd prefix %s",
2139 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
2140 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2141 || (rprefix
->AdvPreferredLifetime
2142 != RTADV_PREFERRED_LIFETIME
)) {
2143 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2144 vty_out(vty
, " infinite");
2146 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
2147 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2148 vty_out(vty
, " infinite");
2151 rprefix
->AdvPreferredLifetime
);
2153 if (!rprefix
->AdvOnLinkFlag
)
2154 vty_out(vty
, " off-link");
2155 if (!rprefix
->AdvAutonomousFlag
)
2156 vty_out(vty
, " no-autoconfig");
2157 if (rprefix
->AdvRouterAddressFlag
)
2158 vty_out(vty
, " router-address");
2161 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2162 char buf
[INET6_ADDRSTRLEN
];
2164 vty_out(vty
, " ipv6 nd rdnss %s",
2165 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2166 if (rdnss
->lifetime_set
) {
2167 if (rdnss
->lifetime
== UINT32_MAX
)
2168 vty_out(vty
, " infinite");
2170 vty_out(vty
, " %u", rdnss
->lifetime
);
2174 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2175 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2176 if (dnssl
->lifetime_set
) {
2177 if (dnssl
->lifetime
== UINT32_MAX
)
2178 vty_out(vty
, " infinite");
2180 vty_out(vty
, " %u", dnssl
->lifetime
);
2188 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2190 struct rtadv
*rtadv
= &zvrf
->rtadv
;
2194 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2196 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2200 THREAD_OFF(rtadv
->ra_timer
);
2201 THREAD_OFF(rtadv
->ra_read
);
2204 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2207 case RTADV_TIMER_MSEC
:
2208 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2212 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2221 void rtadv_init(struct zebra_vrf
*zvrf
)
2223 if (vrf_is_backend_netns()) {
2224 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2225 zrouter
.rtadv_sock
= -1;
2227 zvrf
->rtadv
.sock
= -1;
2228 if (zrouter
.rtadv_sock
< 0)
2229 zrouter
.rtadv_sock
=
2230 rtadv_make_socket(zvrf
->zns
->ns_id
);
2234 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2236 rtadv_event(zvrf
, RTADV_STOP
, 0);
2237 if (zvrf
->rtadv
.sock
>= 0) {
2238 close(zvrf
->rtadv
.sock
);
2239 zvrf
->rtadv
.sock
= -1;
2240 } else if (zrouter
.rtadv_sock
>= 0) {
2241 close(zrouter
.rtadv_sock
);
2242 zrouter
.rtadv_sock
= -1;
2244 zvrf
->rtadv
.adv_if_count
= 0;
2245 zvrf
->rtadv
.adv_msec_if_count
= 0;
2248 void rtadv_cmd_init(void)
2250 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2251 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2253 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2254 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2255 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2256 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2257 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2258 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2259 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2260 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2261 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2262 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2263 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2264 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2265 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2266 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2267 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2268 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2269 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2270 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2271 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2272 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2273 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2274 install_element(INTERFACE_NODE
,
2275 &ipv6_nd_adv_interval_config_option_cmd
);
2276 install_element(INTERFACE_NODE
,
2277 &no_ipv6_nd_adv_interval_config_option_cmd
);
2278 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2279 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2280 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2281 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2282 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2283 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2284 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2285 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2286 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2287 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2290 static int if_join_all_router(int sock
, struct interface
*ifp
)
2294 struct ipv6_mreq mreq
;
2296 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2297 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2298 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2300 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2303 flog_err_sys(EC_LIB_SOCKET
,
2304 "%s(%u): Failed to join group, socket %u error %s",
2305 ifp
->name
, ifp
->ifindex
, sock
,
2306 safe_strerror(errno
));
2308 if (IS_ZEBRA_DEBUG_EVENT
)
2310 "%s(%u): Join All-Routers multicast group, socket %u",
2311 ifp
->name
, ifp
->ifindex
, sock
);
2316 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2320 struct ipv6_mreq mreq
;
2322 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2323 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2324 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2326 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2331 "%s(%u): Failed to leave group, socket %u error %s",
2332 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
2334 if (IS_ZEBRA_DEBUG_EVENT
)
2336 "%s(%u): Leave All-Routers multicast group, socket %u",
2337 ifp
->name
, ifp
->ifindex
, sock
);
2343 void rtadv_init(struct zebra_vrf
*zvrf
)
2347 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2351 void rtadv_cmd_init(void)
2355 #endif /* HAVE_RTADV */