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)
54 #include <netinet/icmp6.h>
57 /* If RFC2133 definition is used. */
58 #ifndef IPV6_JOIN_GROUP
59 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
61 #ifndef IPV6_LEAVE_GROUP
62 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
65 #define ALLNODE "ff02::1"
66 #define ALLROUTER "ff02::2"
68 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS")
69 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL")
71 /* Order is intentional. Matches RFC4191. This array is also used for
72 command matching, so only modify with care. */
73 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
83 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
85 static int if_join_all_router(int, struct interface
*);
86 static int if_leave_all_router(int, struct interface
*);
88 static int rtadv_get_socket(struct zebra_vrf
*zvrf
)
90 if (zvrf
->rtadv
.sock
> 0)
91 return zvrf
->rtadv
.sock
;
92 return zrouter
.rtadv_sock
;
95 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
98 struct interface
*iface
;
101 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
102 if (iface
&& iface
->info
) {
110 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
111 int buflen
, struct sockaddr_in6
*from
,
112 ifindex_t
*ifindex
, int *hoplimit
)
117 struct cmsghdr
*cmsgptr
;
122 /* Fill in message and iovec. */
123 memset(&msg
, 0, sizeof(msg
));
124 msg
.msg_name
= (void *)from
;
125 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
128 msg
.msg_control
= (void *)adata
;
129 msg
.msg_controllen
= sizeof adata
;
131 iov
.iov_len
= buflen
;
133 /* If recvmsg fail return minus value. */
134 ret
= recvmsg(sock
, &msg
, 0);
138 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
139 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
140 /* I want interface index which this packet comes from. */
141 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
142 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
143 struct in6_pktinfo
*ptr
;
145 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
146 *ifindex
= ptr
->ipi6_ifindex
;
147 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
150 /* Incoming packet's hop limit. */
151 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
152 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
153 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
158 rtadv_increment_received(zvrf
, ifindex
);
162 #define RTADV_MSG_SIZE 4096
164 /* Send router advertisement packet. */
165 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
169 struct cmsghdr
*cmsgptr
;
170 struct in6_pktinfo
*pkt
;
171 struct sockaddr_in6 addr
;
172 static void *adata
= NULL
;
173 unsigned char buf
[RTADV_MSG_SIZE
];
174 struct nd_router_advert
*rtadv
;
177 struct zebra_if
*zif
;
178 struct rtadv_prefix
*rprefix
;
179 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
180 0, 0, 0, 0, 0, 0, 0, 1};
181 struct listnode
*node
;
182 uint16_t pkt_RouterLifetime
;
185 * Allocate control message bufffer. This is dynamic because
186 * CMSG_SPACE is not guaranteed not to call a function. Note that
187 * the size will be different on different architectures due to
188 * differing alignment rules.
191 /* XXX Free on shutdown. */
192 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
196 "rtadv_send_packet: can't malloc control data");
201 /* Logging of packet. */
202 if (IS_ZEBRA_DEBUG_PACKET
)
203 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
206 /* Fill in sockaddr_in6. */
207 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
208 addr
.sin6_family
= AF_INET6
;
210 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
211 #endif /* SIN6_LEN */
212 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
213 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
215 /* Fetch interface information. */
218 /* Make router advertisement message. */
219 rtadv
= (struct nd_router_advert
*)buf
;
221 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
222 rtadv
->nd_ra_code
= 0;
223 rtadv
->nd_ra_cksum
= 0;
225 rtadv
->nd_ra_curhoplimit
= 64;
227 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
228 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
230 : zif
->rtadv
.DefaultPreference
;
231 rtadv
->nd_ra_flags_reserved
<<= 3;
233 if (zif
->rtadv
.AdvManagedFlag
)
234 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
235 if (zif
->rtadv
.AdvOtherConfigFlag
)
236 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
237 if (zif
->rtadv
.AdvHomeAgentFlag
)
238 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
239 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
240 * AdvDefaultLifetime is by default based on the value of
241 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
242 * field of Router Advertisements. Given that this field is expressed
243 * in seconds, a small MaxRtrAdvInterval value can result in a zero
244 * value for this field. To prevent this, routers SHOULD keep
245 * AdvDefaultLifetime in at least one second, even if the use of
246 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
248 zif
->rtadv
.AdvDefaultLifetime
!= -1
249 ? zif
->rtadv
.AdvDefaultLifetime
250 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
251 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
252 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
253 rtadv
->nd_ra_retransmit
= htonl(0);
255 len
= sizeof(struct nd_router_advert
);
257 /* If both the Home Agent Preference and Home Agent Lifetime are set to
258 * their default values specified above, this option SHOULD NOT be
259 * included in the Router Advertisement messages sent by this home
260 * agent. -- RFC6275, 7.4 */
261 if (zif
->rtadv
.AdvHomeAgentFlag
262 && (zif
->rtadv
.HomeAgentPreference
263 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
264 struct nd_opt_homeagent_info
*ndopt_hai
=
265 (struct nd_opt_homeagent_info
*)(buf
+ len
);
266 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
267 ndopt_hai
->nd_opt_hai_len
= 1;
268 ndopt_hai
->nd_opt_hai_reserved
= 0;
269 ndopt_hai
->nd_opt_hai_preference
=
270 htons(zif
->rtadv
.HomeAgentPreference
);
271 /* 16-bit unsigned integer. The lifetime associated with the
273 * agent in units of seconds. The default value is the same as
275 * Router Lifetime, as specified in the main body of the Router
276 * Advertisement. The maximum value corresponds to 18.2 hours.
278 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
279 ndopt_hai
->nd_opt_hai_lifetime
=
280 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
281 ? zif
->rtadv
.HomeAgentLifetime
282 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
287 len
+= sizeof(struct nd_opt_homeagent_info
);
290 if (zif
->rtadv
.AdvIntervalOption
) {
291 struct nd_opt_adv_interval
*ndopt_adv
=
292 (struct nd_opt_adv_interval
*)(buf
+ len
);
293 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
294 ndopt_adv
->nd_opt_ai_len
= 1;
295 ndopt_adv
->nd_opt_ai_reserved
= 0;
296 ndopt_adv
->nd_opt_ai_interval
=
297 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
298 len
+= sizeof(struct nd_opt_adv_interval
);
301 /* Fill in prefix. */
302 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
303 struct nd_opt_prefix_info
*pinfo
;
305 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
307 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
308 pinfo
->nd_opt_pi_len
= 4;
309 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
311 pinfo
->nd_opt_pi_flags_reserved
= 0;
312 if (rprefix
->AdvOnLinkFlag
)
313 pinfo
->nd_opt_pi_flags_reserved
|=
314 ND_OPT_PI_FLAG_ONLINK
;
315 if (rprefix
->AdvAutonomousFlag
)
316 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
317 if (rprefix
->AdvRouterAddressFlag
)
318 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
320 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
321 pinfo
->nd_opt_pi_preferred_time
=
322 htonl(rprefix
->AdvPreferredLifetime
);
323 pinfo
->nd_opt_pi_reserved2
= 0;
325 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
326 &rprefix
->prefix
.prefix
);
330 uint8_t buf
[INET6_ADDRSTRLEN
];
332 zlog_debug("DEBUG %s",
333 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
334 buf
, INET6_ADDRSTRLEN
));
338 len
+= sizeof(struct nd_opt_prefix_info
);
341 /* Hardware address. */
342 if (ifp
->hw_addr_len
!= 0) {
343 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
345 /* Option length should be rounded up to next octet if
346 the link address does not end on an octet boundary. */
347 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
349 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
350 len
+= ifp
->hw_addr_len
;
352 /* Pad option to end on an octet boundary. */
353 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
354 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
358 if (zif
->rtadv
.AdvLinkMTU
) {
359 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
360 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
361 opt
->nd_opt_mtu_len
= 1;
362 opt
->nd_opt_mtu_reserved
= 0;
363 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
364 len
+= sizeof(struct nd_opt_mtu
);
368 * There is no limit on the number of configurable recursive DNS
369 * servers or search list entries. We don't want the RA message
370 * to exceed the link's MTU (risking fragmentation) or even
371 * blow the stack buffer allocated for it.
373 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
375 /* Recursive DNS servers */
376 struct rtadv_rdnss
*rdnss
;
378 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
380 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
382 if (len
+ opt_len
> max_len
) {
384 "%s(%u): Tx RA: RDNSS option would exceed MTU, omitting it",
385 ifp
->name
, ifp
->ifindex
);
388 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
390 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
391 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
392 opt
->nd_opt_rdnss_reserved
= 0;
393 opt
->nd_opt_rdnss_lifetime
= htonl(
396 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
398 len
+= sizeof(struct nd_opt_rdnss
);
400 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
401 len
+= sizeof(struct in6_addr
);
404 /* DNS search list */
405 struct rtadv_dnssl
*dnssl
;
407 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
408 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
409 + ((dnssl
->encoded_len
+ 7) & ~7);
411 if (len
+ opt_len
> max_len
) {
413 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
414 ifp
->name
, ifp
->ifindex
);
417 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
419 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
420 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
421 opt
->nd_opt_dnssl_reserved
= 0;
422 opt
->nd_opt_dnssl_lifetime
= htonl(
425 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
427 len
+= sizeof(struct nd_opt_dnssl
);
429 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
430 len
+= dnssl
->encoded_len
;
432 /* Zero-pad to 8-octet boundary */
439 msg
.msg_name
= (void *)&addr
;
440 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
443 msg
.msg_control
= (void *)adata
;
444 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
449 cmsgptr
= CMSG_FIRSTHDR(&msg
);
450 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
451 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
452 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
454 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
455 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
456 pkt
->ipi6_ifindex
= ifp
->ifindex
;
458 ret
= sendmsg(sock
, &msg
, 0);
460 flog_err_sys(EC_LIB_SOCKET
,
461 "%s(%u): Tx RA failed, socket %u error %d (%s)",
462 ifp
->name
, ifp
->ifindex
, sock
, errno
,
463 safe_strerror(errno
));
468 static int rtadv_timer(struct thread
*thread
)
470 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
472 struct interface
*ifp
;
473 struct zebra_if
*zif
;
476 zvrf
->rtadv
.ra_timer
= NULL
;
477 if (zvrf
->rtadv
.adv_msec_if_count
== 0) {
478 period
= 1000; /* 1 s */
479 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
481 period
= 10; /* 10 ms */
482 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
485 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
486 FOR_ALL_INTERFACES (vrf
, ifp
) {
487 if (if_is_loopback(ifp
)
488 || CHECK_FLAG(ifp
->status
,
489 ZEBRA_INTERFACE_VRF_LOOPBACK
)
490 || !if_is_operative(ifp
))
495 if (zif
->rtadv
.AdvSendAdvertisements
) {
496 if (zif
->rtadv
.inFastRexmit
) {
497 /* We assume we fast rexmit every sec so
500 if (--zif
->rtadv
.NumFastReXmitsRemain
502 zif
->rtadv
.inFastRexmit
= 0;
504 if (IS_ZEBRA_DEBUG_SEND
)
506 "Fast RA Rexmit on interface %s",
509 rtadv_send_packet(rtadv_get_socket(zvrf
),
512 zif
->rtadv
.AdvIntervalTimer
-= period
;
513 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
515 MaxRtrAdvInterval each
516 time isn't what section
517 6.2.4 of RFC4861 tells to do.
519 zif
->rtadv
.AdvIntervalTimer
=
523 rtadv_get_socket(zvrf
),
533 static void rtadv_process_solicit(struct interface
*ifp
)
535 struct zebra_vrf
*zvrf
= zvrf_info_lookup(ifp
->vrf
);
538 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
);
542 * This function processes optional attributes off of
543 * end of a RA packet received. At this point in
544 * time we only care about this in one situation
545 * which is when a interface does not have a LL
546 * v6 address. We still need to be able to install
547 * the mac address for v4 to v6 resolution
549 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
550 struct interface
*ifp
,
551 struct sockaddr_in6
*addr
)
556 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
558 switch(opt_hdr
->nd_opt_type
) {
559 case ND_OPT_SOURCE_LINKADDR
:
560 mac
= (char *)(optional
+2);
561 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
562 &addr
->sin6_addr
, 1);
568 len
-= 8 * opt_hdr
->nd_opt_len
;
569 optional
+= 8 * opt_hdr
->nd_opt_len
;
573 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
574 struct interface
*ifp
,
575 struct sockaddr_in6
*addr
)
577 struct nd_router_advert
*radvert
;
578 char addr_str
[INET6_ADDRSTRLEN
];
579 struct zebra_if
*zif
;
584 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
586 if (len
< sizeof(struct nd_router_advert
)) {
587 if (IS_ZEBRA_DEBUG_PACKET
)
588 zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
589 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
593 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
594 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
595 len
- sizeof(struct nd_router_advert
),
597 if (IS_ZEBRA_DEBUG_PACKET
)
598 zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s",
599 ifp
->name
, ifp
->ifindex
, addr_str
);
603 radvert
= (struct nd_router_advert
*)msg
;
605 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
606 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
608 EC_ZEBRA_RA_PARAM_MISMATCH
,
609 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
610 ifp
->name
, ifp
->ifindex
, addr_str
);
613 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
614 && !zif
->rtadv
.AdvManagedFlag
) {
616 EC_ZEBRA_RA_PARAM_MISMATCH
,
617 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
618 ifp
->name
, ifp
->ifindex
, addr_str
);
621 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
622 && !zif
->rtadv
.AdvOtherConfigFlag
) {
624 EC_ZEBRA_RA_PARAM_MISMATCH
,
625 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
626 ifp
->name
, ifp
->ifindex
, addr_str
);
629 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
630 && (ntohl(radvert
->nd_ra_reachable
)
631 != zif
->rtadv
.AdvReachableTime
)) {
633 EC_ZEBRA_RA_PARAM_MISMATCH
,
634 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
635 ifp
->name
, ifp
->ifindex
, addr_str
);
638 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
639 && (ntohl(radvert
->nd_ra_retransmit
)
640 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
642 EC_ZEBRA_RA_PARAM_MISMATCH
,
643 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
644 ifp
->name
, ifp
->ifindex
, addr_str
);
647 /* Create entry for neighbor if not known. */
649 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
650 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
652 if (!nbr_connected_check(ifp
, &p
))
653 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
657 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
658 ifindex_t ifindex
, int hoplimit
,
659 struct sockaddr_in6
*from
,
660 struct zebra_vrf
*zvrf
)
662 struct icmp6_hdr
*icmph
;
663 struct interface
*ifp
;
664 struct zebra_if
*zif
;
665 char addr_str
[INET6_ADDRSTRLEN
];
667 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
669 /* Interface search. */
670 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
672 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
673 "RA/RS received on unknown IF %u from %s", ifindex
,
678 if (IS_ZEBRA_DEBUG_PACKET
)
679 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
680 ifp
->ifindex
, len
, addr_str
);
682 if (if_is_loopback(ifp
)
683 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
686 /* Check interface configuration. */
688 if (!zif
->rtadv
.AdvSendAdvertisements
)
691 /* ICMP message length check. */
692 if (len
< sizeof(struct icmp6_hdr
)) {
693 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
694 ifp
->name
, ifp
->ifindex
, len
);
698 icmph
= (struct icmp6_hdr
*)buf
;
700 /* ICMP message type check. */
701 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
702 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
703 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
704 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
708 /* Hoplimit check. */
709 if (hoplimit
>= 0 && hoplimit
!= 255) {
710 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
711 ifp
->ifindex
, hoplimit
);
715 /* Check ICMP message type. */
716 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
717 rtadv_process_solicit(ifp
);
718 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
719 rtadv_process_advert(buf
, len
, ifp
, from
);
724 static int rtadv_read(struct thread
*thread
)
728 uint8_t buf
[RTADV_MSG_SIZE
];
729 struct sockaddr_in6 from
;
730 ifindex_t ifindex
= 0;
732 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
734 sock
= THREAD_FD(thread
);
735 zvrf
->rtadv
.ra_read
= NULL
;
737 /* Register myself. */
738 rtadv_event(zvrf
, RTADV_READ
, sock
);
740 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
744 flog_err_sys(EC_LIB_SOCKET
,
745 "RA/RS recv failed, socket %u error %s", sock
,
746 safe_strerror(errno
));
750 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
755 static int rtadv_make_socket(ns_id_t ns_id
)
759 struct icmp6_filter filter
;
761 frr_elevate_privs(&zserv_privs
) {
763 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
771 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
776 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
781 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
786 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
791 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
797 ICMP6_FILTER_SETBLOCKALL(&filter
);
798 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
799 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
801 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
802 sizeof(struct icmp6_filter
));
804 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
812 static struct rtadv_prefix
*rtadv_prefix_new(void)
814 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
817 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
819 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
822 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
823 struct prefix_ipv6
*p
)
825 struct listnode
*node
;
826 struct rtadv_prefix
*rprefix
;
828 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
829 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
835 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
836 struct prefix_ipv6
*p
)
838 struct rtadv_prefix
*rprefix
;
840 rprefix
= rtadv_prefix_lookup(rplist
, p
);
844 rprefix
= rtadv_prefix_new();
845 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
846 listnode_add(rplist
, rprefix
);
851 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
853 struct rtadv_prefix
*rprefix
;
855 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
857 /* Set parameters. */
858 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
859 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
860 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
861 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
862 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
865 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
867 struct rtadv_prefix
*rprefix
;
869 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
870 if (rprefix
!= NULL
) {
871 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
872 rtadv_prefix_free(rprefix
);
878 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
879 ipv6_nd_suppress_ra_status status
)
881 struct zebra_if
*zif
;
882 struct zebra_vrf
*zvrf
;
885 zvrf
= zvrf_info_lookup(ifp
->vrf
);
887 if (status
== RA_SUPPRESS
) {
888 /* RA is currently enabled */
889 if (zif
->rtadv
.AdvSendAdvertisements
) {
890 zif
->rtadv
.AdvSendAdvertisements
= 0;
891 zif
->rtadv
.AdvIntervalTimer
= 0;
892 zvrf
->rtadv
.adv_if_count
--;
894 if_leave_all_router(rtadv_get_socket(zvrf
), ifp
);
896 if (zvrf
->rtadv
.adv_if_count
== 0)
897 rtadv_event(zvrf
, RTADV_STOP
, 0);
900 if (!zif
->rtadv
.AdvSendAdvertisements
) {
901 zif
->rtadv
.AdvSendAdvertisements
= 1;
902 zif
->rtadv
.AdvIntervalTimer
= 0;
903 zvrf
->rtadv
.adv_if_count
++;
905 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
906 /* Enable Fast RA only when RA interval is in
908 zif
->rtadv
.inFastRexmit
= 1;
909 zif
->rtadv
.NumFastReXmitsRemain
=
910 RTADV_NUM_FAST_REXMITS
;
913 if_join_all_router(rtadv_get_socket(zvrf
), ifp
);
915 if (zvrf
->rtadv
.adv_if_count
== 1)
916 rtadv_event(zvrf
, RTADV_START
,
917 rtadv_get_socket(zvrf
));
923 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
924 * Note that while the client could request RA on an interface on which the
925 * operator has not enabled RA, RA won't be disabled upon client request
926 * if the operator has explicitly enabled RA. The enable request can also
927 * specify a RA interval (in seconds).
929 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
933 struct interface
*ifp
;
934 struct zebra_if
*zif
;
939 /* Get interface index and RA interval. */
940 STREAM_GETL(s
, ifindex
);
941 STREAM_GETL(s
, ra_interval
);
943 if (IS_ZEBRA_DEBUG_EVENT
)
944 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
945 zvrf_id(zvrf
), ifindex
,
946 enable
? "enable" : "disable",
947 zebra_route_string(client
->proto
), ra_interval
);
949 /* Locate interface and check VRF match. */
950 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
952 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
953 "%u: IF %u RA %s client %s - interface unknown",
954 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
955 zebra_route_string(client
->proto
));
958 if (ifp
->vrf
!= zvrf
->vrf
) {
960 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
961 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
962 zebra_route_string(client
->proto
), vrf_to_id(ifp
->vrf
));
968 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
969 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
971 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
972 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
973 VTY_RA_INTERVAL_CONFIGURED
))
974 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
976 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
977 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
978 VTY_RA_INTERVAL_CONFIGURED
))
979 zif
->rtadv
.MaxRtrAdvInterval
=
980 RTADV_MAX_RTR_ADV_INTERVAL
;
981 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
982 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
988 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
990 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
992 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
994 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
997 DEFUN (ipv6_nd_suppress_ra
,
998 ipv6_nd_suppress_ra_cmd
,
999 "ipv6 nd suppress-ra",
1000 "Interface IPv6 config commands\n"
1001 "Neighbor discovery\n"
1002 "Suppress Router Advertisement\n")
1004 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1005 struct zebra_if
*zif
= ifp
->info
;
1007 if (if_is_loopback(ifp
)
1008 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1010 "Cannot configure IPv6 Router Advertisements on this interface\n");
1011 return CMD_WARNING_CONFIG_FAILED
;
1014 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1015 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1017 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1021 DEFUN (no_ipv6_nd_suppress_ra
,
1022 no_ipv6_nd_suppress_ra_cmd
,
1023 "no ipv6 nd suppress-ra",
1025 "Interface IPv6 config commands\n"
1026 "Neighbor discovery\n"
1027 "Suppress Router Advertisement\n")
1029 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1030 struct zebra_if
*zif
= ifp
->info
;
1032 if (if_is_loopback(ifp
)
1033 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1035 "Cannot configure IPv6 Router Advertisements on this interface\n");
1036 return CMD_WARNING_CONFIG_FAILED
;
1039 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1040 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1044 DEFUN (ipv6_nd_ra_interval_msec
,
1045 ipv6_nd_ra_interval_msec_cmd
,
1046 "ipv6 nd ra-interval msec (70-1800000)",
1047 "Interface IPv6 config commands\n"
1048 "Neighbor discovery\n"
1049 "Router Advertisement interval\n"
1050 "Router Advertisement interval in milliseconds\n"
1051 "Router Advertisement interval in milliseconds\n")
1054 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1056 struct zebra_if
*zif
= ifp
->info
;
1057 struct zebra_vrf
*zvrf
;
1059 zvrf
= zvrf_info_lookup(ifp
->vrf
);
1061 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1062 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1063 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1065 "This ra-interval would conflict with configured ra-lifetime!\n");
1066 return CMD_WARNING_CONFIG_FAILED
;
1069 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1070 zvrf
->rtadv
.adv_msec_if_count
--;
1072 if (interval
% 1000)
1073 zvrf
->rtadv
.adv_msec_if_count
++;
1075 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1076 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1077 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1078 zif
->rtadv
.AdvIntervalTimer
= 0;
1083 DEFUN (ipv6_nd_ra_interval
,
1084 ipv6_nd_ra_interval_cmd
,
1085 "ipv6 nd ra-interval (1-1800)",
1086 "Interface IPv6 config commands\n"
1087 "Neighbor discovery\n"
1088 "Router Advertisement interval\n"
1089 "Router Advertisement interval in seconds\n")
1092 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1094 struct zebra_if
*zif
= ifp
->info
;
1095 struct zebra_vrf
*zvrf
;
1097 zvrf
= zvrf_info_lookup(ifp
->vrf
);
1099 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1100 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1101 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1103 "This ra-interval would conflict with configured ra-lifetime!\n");
1104 return CMD_WARNING_CONFIG_FAILED
;
1107 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1108 zvrf
->rtadv
.adv_msec_if_count
--;
1110 /* convert to milliseconds */
1111 interval
= interval
* 1000;
1113 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1114 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1115 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1116 zif
->rtadv
.AdvIntervalTimer
= 0;
1121 DEFUN (no_ipv6_nd_ra_interval
,
1122 no_ipv6_nd_ra_interval_cmd
,
1123 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1125 "Interface IPv6 config commands\n"
1126 "Neighbor discovery\n"
1127 "Router Advertisement interval\n"
1128 "Router Advertisement interval in seconds\n"
1129 "Specify millisecond router advertisement interval\n"
1130 "Router Advertisement interval in milliseconds\n")
1132 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1133 struct zebra_if
*zif
= ifp
->info
;
1134 struct zebra_vrf
*zvrf
= NULL
;
1136 zvrf
= zvrf_info_lookup(ifp
->vrf
);
1138 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1139 zvrf
->rtadv
.adv_msec_if_count
--;
1141 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1143 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1144 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1146 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1148 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1149 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1154 DEFUN (ipv6_nd_ra_lifetime
,
1155 ipv6_nd_ra_lifetime_cmd
,
1156 "ipv6 nd ra-lifetime (0-9000)",
1157 "Interface IPv6 config commands\n"
1158 "Neighbor discovery\n"
1160 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1163 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1164 struct zebra_if
*zif
= ifp
->info
;
1167 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1169 /* The value to be placed in the Router Lifetime field
1170 * of Router Advertisements sent from the interface,
1171 * in seconds. MUST be either zero or between
1172 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1173 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1175 "This ra-lifetime would conflict with configured ra-interval\n");
1176 return CMD_WARNING_CONFIG_FAILED
;
1179 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1184 DEFUN (no_ipv6_nd_ra_lifetime
,
1185 no_ipv6_nd_ra_lifetime_cmd
,
1186 "no ipv6 nd ra-lifetime [(0-9000)]",
1188 "Interface IPv6 config commands\n"
1189 "Neighbor discovery\n"
1191 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1193 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1194 struct zebra_if
*zif
= ifp
->info
;
1196 zif
->rtadv
.AdvDefaultLifetime
= -1;
1201 DEFUN (ipv6_nd_reachable_time
,
1202 ipv6_nd_reachable_time_cmd
,
1203 "ipv6 nd reachable-time (1-3600000)",
1204 "Interface IPv6 config commands\n"
1205 "Neighbor discovery\n"
1207 "Reachable time in milliseconds\n")
1210 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1211 struct zebra_if
*zif
= ifp
->info
;
1212 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1216 DEFUN (no_ipv6_nd_reachable_time
,
1217 no_ipv6_nd_reachable_time_cmd
,
1218 "no ipv6 nd reachable-time [(1-3600000)]",
1220 "Interface IPv6 config commands\n"
1221 "Neighbor discovery\n"
1223 "Reachable time in milliseconds\n")
1225 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1226 struct zebra_if
*zif
= ifp
->info
;
1228 zif
->rtadv
.AdvReachableTime
= 0;
1233 DEFUN (ipv6_nd_homeagent_preference
,
1234 ipv6_nd_homeagent_preference_cmd
,
1235 "ipv6 nd home-agent-preference (0-65535)",
1236 "Interface IPv6 config commands\n"
1237 "Neighbor discovery\n"
1238 "Home Agent preference\n"
1239 "preference value (default is 0, least preferred)\n")
1242 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1243 struct zebra_if
*zif
= ifp
->info
;
1244 zif
->rtadv
.HomeAgentPreference
=
1245 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1249 DEFUN (no_ipv6_nd_homeagent_preference
,
1250 no_ipv6_nd_homeagent_preference_cmd
,
1251 "no ipv6 nd home-agent-preference [(0-65535)]",
1253 "Interface IPv6 config commands\n"
1254 "Neighbor discovery\n"
1255 "Home Agent preference\n"
1256 "preference value (default is 0, least preferred)\n")
1258 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1259 struct zebra_if
*zif
= ifp
->info
;
1261 zif
->rtadv
.HomeAgentPreference
= 0;
1266 DEFUN (ipv6_nd_homeagent_lifetime
,
1267 ipv6_nd_homeagent_lifetime_cmd
,
1268 "ipv6 nd home-agent-lifetime (0-65520)",
1269 "Interface IPv6 config commands\n"
1270 "Neighbor discovery\n"
1271 "Home Agent lifetime\n"
1272 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1275 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1276 struct zebra_if
*zif
= ifp
->info
;
1277 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1281 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1282 no_ipv6_nd_homeagent_lifetime_cmd
,
1283 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1285 "Interface IPv6 config commands\n"
1286 "Neighbor discovery\n"
1287 "Home Agent lifetime\n"
1288 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1290 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1291 struct zebra_if
*zif
= ifp
->info
;
1293 zif
->rtadv
.HomeAgentLifetime
= -1;
1298 DEFUN (ipv6_nd_managed_config_flag
,
1299 ipv6_nd_managed_config_flag_cmd
,
1300 "ipv6 nd managed-config-flag",
1301 "Interface IPv6 config commands\n"
1302 "Neighbor discovery\n"
1303 "Managed address configuration flag\n")
1305 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1306 struct zebra_if
*zif
= ifp
->info
;
1308 zif
->rtadv
.AdvManagedFlag
= 1;
1313 DEFUN (no_ipv6_nd_managed_config_flag
,
1314 no_ipv6_nd_managed_config_flag_cmd
,
1315 "no ipv6 nd managed-config-flag",
1317 "Interface IPv6 config commands\n"
1318 "Neighbor discovery\n"
1319 "Managed address configuration flag\n")
1321 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1322 struct zebra_if
*zif
= ifp
->info
;
1324 zif
->rtadv
.AdvManagedFlag
= 0;
1329 DEFUN (ipv6_nd_homeagent_config_flag
,
1330 ipv6_nd_homeagent_config_flag_cmd
,
1331 "ipv6 nd home-agent-config-flag",
1332 "Interface IPv6 config commands\n"
1333 "Neighbor discovery\n"
1334 "Home Agent configuration flag\n")
1336 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1337 struct zebra_if
*zif
= ifp
->info
;
1339 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1344 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1345 no_ipv6_nd_homeagent_config_flag_cmd
,
1346 "no ipv6 nd home-agent-config-flag",
1348 "Interface IPv6 config commands\n"
1349 "Neighbor discovery\n"
1350 "Home Agent configuration flag\n")
1352 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1353 struct zebra_if
*zif
= ifp
->info
;
1355 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1360 DEFUN (ipv6_nd_adv_interval_config_option
,
1361 ipv6_nd_adv_interval_config_option_cmd
,
1362 "ipv6 nd adv-interval-option",
1363 "Interface IPv6 config commands\n"
1364 "Neighbor discovery\n"
1365 "Advertisement Interval Option\n")
1367 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1368 struct zebra_if
*zif
= ifp
->info
;
1370 zif
->rtadv
.AdvIntervalOption
= 1;
1375 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1376 no_ipv6_nd_adv_interval_config_option_cmd
,
1377 "no ipv6 nd adv-interval-option",
1379 "Interface IPv6 config commands\n"
1380 "Neighbor discovery\n"
1381 "Advertisement Interval Option\n")
1383 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1384 struct zebra_if
*zif
= ifp
->info
;
1386 zif
->rtadv
.AdvIntervalOption
= 0;
1391 DEFUN (ipv6_nd_other_config_flag
,
1392 ipv6_nd_other_config_flag_cmd
,
1393 "ipv6 nd other-config-flag",
1394 "Interface IPv6 config commands\n"
1395 "Neighbor discovery\n"
1396 "Other statefull configuration flag\n")
1398 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1399 struct zebra_if
*zif
= ifp
->info
;
1401 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1406 DEFUN (no_ipv6_nd_other_config_flag
,
1407 no_ipv6_nd_other_config_flag_cmd
,
1408 "no ipv6 nd other-config-flag",
1410 "Interface IPv6 config commands\n"
1411 "Neighbor discovery\n"
1412 "Other statefull configuration flag\n")
1414 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1415 struct zebra_if
*zif
= ifp
->info
;
1417 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1422 DEFUN (ipv6_nd_prefix
,
1424 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1425 "Interface IPv6 config commands\n"
1426 "Neighbor discovery\n"
1427 "Prefix information\n"
1429 "Valid lifetime in seconds\n"
1430 "Infinite valid lifetime\n"
1431 "Preferred lifetime in seconds\n"
1432 "Infinite preferred lifetime\n"
1433 "Set Router Address flag\n"
1434 "Do not use prefix for onlink determination\n"
1435 "Do not use prefix for autoconfiguration\n"
1436 "Do not use prefix for autoconfiguration\n"
1437 "Do not use prefix for onlink determination\n")
1440 char *prefix
= argv
[3]->arg
;
1441 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1442 || strmatch(argv
[4]->text
, "infinite"));
1443 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1445 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1447 char *lifetime
= NULL
, *preflifetime
= NULL
;
1448 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1450 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1452 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1457 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1459 offlink
= (argc
> idx_routeropts
+ 1
1460 || strmatch(argv
[idx_routeropts
]->text
,
1462 noautoconf
= (argc
> idx_routeropts
+ 1
1463 || strmatch(argv
[idx_routeropts
]->text
,
1469 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1470 struct zebra_if
*zebra_if
= ifp
->info
;
1472 struct rtadv_prefix rp
;
1474 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1476 vty_out(vty
, "Malformed IPv6 prefix\n");
1477 return CMD_WARNING_CONFIG_FAILED
;
1479 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1480 rp
.AdvOnLinkFlag
= !offlink
;
1481 rp
.AdvAutonomousFlag
= !noautoconf
;
1482 rp
.AdvRouterAddressFlag
= routeraddr
;
1483 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1484 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1487 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1489 : strtoll(lifetime
, NULL
, 10);
1490 rp
.AdvPreferredLifetime
=
1491 strmatch(preflifetime
, "infinite")
1493 : strtoll(preflifetime
, NULL
, 10);
1494 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1495 vty_out(vty
, "Invalid preferred lifetime\n");
1496 return CMD_WARNING_CONFIG_FAILED
;
1500 rtadv_prefix_set(zebra_if
, &rp
);
1505 DEFUN (no_ipv6_nd_prefix
,
1506 no_ipv6_nd_prefix_cmd
,
1507 "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]>]",
1509 "Interface IPv6 config commands\n"
1510 "Neighbor discovery\n"
1511 "Prefix information\n"
1513 "Valid lifetime in seconds\n"
1514 "Infinite valid lifetime\n"
1515 "Preferred lifetime in seconds\n"
1516 "Infinite preferred lifetime\n"
1517 "Set Router Address flag\n"
1518 "Do not use prefix for onlink determination\n"
1519 "Do not use prefix for autoconfiguration\n"
1520 "Do not use prefix for autoconfiguration\n"
1521 "Do not use prefix for onlink determination\n")
1523 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1524 struct zebra_if
*zebra_if
= ifp
->info
;
1526 struct rtadv_prefix rp
;
1527 char *prefix
= argv
[4]->arg
;
1529 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1531 vty_out(vty
, "Malformed IPv6 prefix\n");
1532 return CMD_WARNING_CONFIG_FAILED
;
1534 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1536 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1538 vty_out(vty
, "Non-existant IPv6 prefix\n");
1539 return CMD_WARNING_CONFIG_FAILED
;
1545 DEFUN (ipv6_nd_router_preference
,
1546 ipv6_nd_router_preference_cmd
,
1547 "ipv6 nd router-preference <high|medium|low>",
1548 "Interface IPv6 config commands\n"
1549 "Neighbor discovery\n"
1550 "Default router preference\n"
1551 "High default router preference\n"
1552 "Medium default router preference (default)\n"
1553 "Low default router preference\n")
1555 int idx_high_medium_low
= 3;
1556 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1557 struct zebra_if
*zif
= ifp
->info
;
1560 while (0 != rtadv_pref_strs
[i
]) {
1561 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1564 zif
->rtadv
.DefaultPreference
= i
;
1570 return CMD_ERR_NO_MATCH
;
1573 DEFUN (no_ipv6_nd_router_preference
,
1574 no_ipv6_nd_router_preference_cmd
,
1575 "no ipv6 nd router-preference [<high|medium|low>]",
1577 "Interface IPv6 config commands\n"
1578 "Neighbor discovery\n"
1579 "Default router preference\n"
1580 "High default router preference\n"
1581 "Medium default router preference (default)\n"
1582 "Low default router preference\n")
1584 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1585 struct zebra_if
*zif
= ifp
->info
;
1587 zif
->rtadv
.DefaultPreference
=
1588 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1595 "ipv6 nd mtu (1-65535)",
1596 "Interface IPv6 config commands\n"
1597 "Neighbor discovery\n"
1602 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1603 struct zebra_if
*zif
= ifp
->info
;
1604 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1608 DEFUN (no_ipv6_nd_mtu
,
1610 "no ipv6 nd mtu [(1-65535)]",
1612 "Interface IPv6 config commands\n"
1613 "Neighbor discovery\n"
1617 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1618 struct zebra_if
*zif
= ifp
->info
;
1619 zif
->rtadv
.AdvLinkMTU
= 0;
1623 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
1625 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
1628 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
1630 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
1633 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
1634 struct rtadv_rdnss
*rdnss
)
1636 struct listnode
*node
;
1637 struct rtadv_rdnss
*p
;
1639 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1640 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
1645 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
1646 struct rtadv_rdnss
*rdnss
)
1648 struct rtadv_rdnss
*p
;
1650 p
= rtadv_rdnss_lookup(list
, rdnss
);
1654 p
= rtadv_rdnss_new();
1655 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
1656 listnode_add(list
, p
);
1661 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1663 struct rtadv_rdnss
*p
;
1665 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1666 p
->lifetime
= rdnss
->lifetime
;
1667 p
->lifetime_set
= rdnss
->lifetime_set
;
1670 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1672 struct rtadv_rdnss
*p
;
1674 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1676 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
1677 rtadv_rdnss_free(p
);
1684 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
1686 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
1689 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
1691 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
1694 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
1695 struct rtadv_dnssl
*dnssl
)
1697 struct listnode
*node
;
1698 struct rtadv_dnssl
*p
;
1700 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1701 if (!strcasecmp(p
->name
, dnssl
->name
))
1706 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
1707 struct rtadv_dnssl
*dnssl
)
1709 struct rtadv_dnssl
*p
;
1711 p
= rtadv_dnssl_lookup(list
, dnssl
);
1715 p
= rtadv_dnssl_new();
1716 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1717 listnode_add(list
, p
);
1722 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1724 struct rtadv_dnssl
*p
;
1726 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1727 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1730 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1732 struct rtadv_dnssl
*p
;
1734 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1736 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
1737 rtadv_dnssl_free(p
);
1745 * Convert dotted domain name (with or without trailing root zone dot) to
1746 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
1747 * to strlen(in) + 2 octets to out.
1749 * Returns the number of octets written to out or -1 if in does not constitute
1750 * a valid domain name.
1752 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
1754 const char *label_start
, *label_end
;
1760 while (*label_start
) {
1763 label_end
= strchr(label_start
, '.');
1764 if (label_end
== NULL
)
1765 label_end
= label_start
+ strlen(label_start
);
1767 label_len
= label_end
- label_start
;
1768 if (label_len
>= 64)
1769 return -1; /* labels must be 63 octets or less */
1771 out
[outp
++] = (uint8_t)label_len
;
1772 memcpy(out
+ outp
, label_start
, label_len
);
1774 label_start
+= label_len
;
1775 if (*label_start
== '.')
1783 DEFUN(ipv6_nd_rdnss
,
1785 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1786 "Interface IPv6 config commands\n"
1787 "Neighbor discovery\n"
1788 "Recursive DNS server information\n"
1790 "Valid lifetime in seconds\n"
1791 "Infinite valid lifetime\n")
1793 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1794 struct zebra_if
*zif
= ifp
->info
;
1795 struct rtadv_rdnss rdnss
= {};
1797 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
1798 vty_out(vty
, "Malformed IPv6 address\n");
1799 return CMD_WARNING_CONFIG_FAILED
;
1802 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1804 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
1806 : strtoll(lifetime
, NULL
, 10);
1807 rdnss
.lifetime_set
= 1;
1810 rtadv_rdnss_set(zif
, &rdnss
);
1815 DEFUN(no_ipv6_nd_rdnss
,
1816 no_ipv6_nd_rdnss_cmd
,
1817 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1819 "Interface IPv6 config commands\n"
1820 "Neighbor discovery\n"
1821 "Recursive DNS server information\n"
1823 "Valid lifetime in seconds\n"
1824 "Infinite valid lifetime\n")
1826 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1827 struct zebra_if
*zif
= ifp
->info
;
1828 struct rtadv_rdnss rdnss
= {};
1830 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
1831 vty_out(vty
, "Malformed IPv6 address\n");
1832 return CMD_WARNING_CONFIG_FAILED
;
1834 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
1835 vty_out(vty
, "Non-existant RDNSS address\n");
1836 return CMD_WARNING_CONFIG_FAILED
;
1842 DEFUN(ipv6_nd_dnssl
,
1844 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1845 "Interface IPv6 config commands\n"
1846 "Neighbor discovery\n"
1847 "DNS search list information\n"
1848 "Domain name suffix\n"
1849 "Valid lifetime in seconds\n"
1850 "Infinite valid lifetime\n")
1852 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1853 struct zebra_if
*zif
= ifp
->info
;
1854 struct rtadv_dnssl dnssl
= {};
1858 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
1859 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1860 vty_out(vty
, "Malformed DNS search domain\n");
1861 return CMD_WARNING_CONFIG_FAILED
;
1863 if (dnssl
.name
[len
- 1] == '.') {
1865 * Allow, but don't require, a trailing dot signifying the root
1866 * zone. Canonicalize by cutting it off if present.
1868 dnssl
.name
[len
- 1] = '\0';
1872 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1874 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
1876 : strtoll(lifetime
, NULL
, 10);
1877 dnssl
.lifetime_set
= 1;
1880 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
1882 vty_out(vty
, "Malformed DNS search domain\n");
1883 return CMD_WARNING_CONFIG_FAILED
;
1885 dnssl
.encoded_len
= ret
;
1886 rtadv_dnssl_set(zif
, &dnssl
);
1891 DEFUN(no_ipv6_nd_dnssl
,
1892 no_ipv6_nd_dnssl_cmd
,
1893 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1895 "Interface IPv6 config commands\n"
1896 "Neighbor discovery\n"
1897 "DNS search list information\n"
1898 "Domain name suffix\n"
1899 "Valid lifetime in seconds\n"
1900 "Infinite valid lifetime\n")
1902 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1903 struct zebra_if
*zif
= ifp
->info
;
1904 struct rtadv_dnssl dnssl
= {};
1907 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
1908 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1909 vty_out(vty
, "Malformed DNS search domain\n");
1910 return CMD_WARNING_CONFIG_FAILED
;
1912 if (dnssl
.name
[len
- 1] == '.') {
1913 dnssl
.name
[len
- 1] = '\0';
1916 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
1917 vty_out(vty
, "Non-existant DNS search domain\n");
1918 return CMD_WARNING_CONFIG_FAILED
;
1925 /* Dump interface ND information to vty. */
1926 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1928 struct zebra_if
*zif
;
1929 struct rtadvconf
*rtadv
;
1932 zif
= (struct zebra_if
*)ifp
->info
;
1933 rtadv
= &zif
->rtadv
;
1935 if (rtadv
->AdvSendAdvertisements
) {
1937 " ND advertised reachable time is %d milliseconds\n",
1938 rtadv
->AdvReachableTime
);
1940 " ND advertised retransmit interval is %d milliseconds\n",
1941 rtadv
->AdvRetransTimer
);
1942 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1943 zif
->ra_sent
, zif
->ra_rcvd
);
1944 interval
= rtadv
->MaxRtrAdvInterval
;
1945 if (interval
% 1000)
1947 " ND router advertisements are sent every "
1948 "%d milliseconds\n",
1952 " ND router advertisements are sent every "
1955 if (rtadv
->AdvDefaultLifetime
!= -1)
1957 " ND router advertisements live for %d seconds\n",
1958 rtadv
->AdvDefaultLifetime
);
1961 " ND router advertisements lifetime tracks ra-interval\n");
1963 " ND router advertisement default router preference is "
1965 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1966 if (rtadv
->AdvManagedFlag
)
1968 " Hosts use DHCP to obtain routable addresses.\n");
1971 " Hosts use stateless autoconfig for addresses.\n");
1972 if (rtadv
->AdvHomeAgentFlag
) {
1974 " ND router advertisements with Home Agent flag bit set.\n");
1975 if (rtadv
->HomeAgentLifetime
!= -1)
1977 " Home Agent lifetime is %u seconds\n",
1978 rtadv
->HomeAgentLifetime
);
1981 " Home Agent lifetime tracks ra-lifetime\n");
1982 vty_out(vty
, " Home Agent preference is %u\n",
1983 rtadv
->HomeAgentPreference
);
1985 if (rtadv
->AdvIntervalOption
)
1987 " ND router advertisements with Adv. Interval option.\n");
1993 /* Write configuration about router advertisement. */
1994 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1996 struct zebra_if
*zif
;
1997 struct listnode
*node
;
1998 struct rtadv_prefix
*rprefix
;
1999 struct rtadv_rdnss
*rdnss
;
2000 struct rtadv_dnssl
*dnssl
;
2001 char buf
[PREFIX_STRLEN
];
2006 if (!(if_is_loopback(ifp
)
2007 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
2008 if (zif
->rtadv
.AdvSendAdvertisements
2009 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2010 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2013 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2014 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2015 if (interval
% 1000)
2016 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2018 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2019 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2023 if (zif
->rtadv
.AdvIntervalOption
)
2024 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2026 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2027 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2028 zif
->rtadv
.AdvDefaultLifetime
);
2030 if (zif
->rtadv
.HomeAgentPreference
)
2031 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2032 zif
->rtadv
.HomeAgentPreference
);
2034 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2035 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2036 zif
->rtadv
.HomeAgentLifetime
);
2038 if (zif
->rtadv
.AdvHomeAgentFlag
)
2039 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2041 if (zif
->rtadv
.AdvReachableTime
)
2042 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2043 zif
->rtadv
.AdvReachableTime
);
2045 if (zif
->rtadv
.AdvManagedFlag
)
2046 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2048 if (zif
->rtadv
.AdvOtherConfigFlag
)
2049 vty_out(vty
, " ipv6 nd other-config-flag\n");
2051 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2052 vty_out(vty
, " ipv6 nd router-preference %s\n",
2053 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2055 if (zif
->rtadv
.AdvLinkMTU
)
2056 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2058 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
2059 vty_out(vty
, " ipv6 nd prefix %s",
2060 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
2061 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2062 || (rprefix
->AdvPreferredLifetime
2063 != RTADV_PREFERRED_LIFETIME
)) {
2064 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2065 vty_out(vty
, " infinite");
2067 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
2068 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2069 vty_out(vty
, " infinite");
2072 rprefix
->AdvPreferredLifetime
);
2074 if (!rprefix
->AdvOnLinkFlag
)
2075 vty_out(vty
, " off-link");
2076 if (!rprefix
->AdvAutonomousFlag
)
2077 vty_out(vty
, " no-autoconfig");
2078 if (rprefix
->AdvRouterAddressFlag
)
2079 vty_out(vty
, " router-address");
2082 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2083 char buf
[INET6_ADDRSTRLEN
];
2085 vty_out(vty
, " ipv6 nd rdnss %s",
2086 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2087 if (rdnss
->lifetime_set
) {
2088 if (rdnss
->lifetime
== UINT32_MAX
)
2089 vty_out(vty
, " infinite");
2091 vty_out(vty
, " %u", rdnss
->lifetime
);
2095 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2096 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2097 if (dnssl
->lifetime_set
) {
2098 if (dnssl
->lifetime
== UINT32_MAX
)
2099 vty_out(vty
, " infinite");
2101 vty_out(vty
, " %u", dnssl
->lifetime
);
2109 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2111 struct rtadv
*rtadv
= &zvrf
->rtadv
;
2115 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2117 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2121 if (rtadv
->ra_timer
) {
2122 thread_cancel(rtadv
->ra_timer
);
2123 rtadv
->ra_timer
= NULL
;
2125 if (rtadv
->ra_read
) {
2126 thread_cancel(rtadv
->ra_read
);
2127 rtadv
->ra_read
= NULL
;
2131 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2134 case RTADV_TIMER_MSEC
:
2135 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2139 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2148 void rtadv_init(struct zebra_vrf
*zvrf
)
2150 if (vrf_is_backend_netns()) {
2151 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2152 zrouter
.rtadv_sock
= -1;
2153 } else if (!zrouter
.rtadv_sock
) {
2154 zvrf
->rtadv
.sock
= -1;
2155 if (!zrouter
.rtadv_sock
)
2156 zrouter
.rtadv_sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2160 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2162 rtadv_event(zvrf
, RTADV_STOP
, 0);
2163 if (zvrf
->rtadv
.sock
>= 0) {
2164 close(zvrf
->rtadv
.sock
);
2165 zvrf
->rtadv
.sock
= -1;
2166 } else if (zrouter
.rtadv_sock
>= 0) {
2167 close(zrouter
.rtadv_sock
);
2168 zrouter
.rtadv_sock
= -1;
2170 zvrf
->rtadv
.adv_if_count
= 0;
2171 zvrf
->rtadv
.adv_msec_if_count
= 0;
2174 void rtadv_cmd_init(void)
2176 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2177 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2179 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2180 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2181 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2182 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2183 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2184 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2185 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2186 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2187 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2188 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2189 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2190 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2191 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2192 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2193 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2194 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2195 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2196 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2197 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2198 install_element(INTERFACE_NODE
,
2199 &ipv6_nd_adv_interval_config_option_cmd
);
2200 install_element(INTERFACE_NODE
,
2201 &no_ipv6_nd_adv_interval_config_option_cmd
);
2202 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2203 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2204 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2205 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2206 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2207 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2208 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2209 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2210 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2211 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2214 static int if_join_all_router(int sock
, struct interface
*ifp
)
2218 struct ipv6_mreq mreq
;
2220 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2221 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2222 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2224 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2227 flog_err_sys(EC_LIB_SOCKET
,
2228 "%s(%u): Failed to join group, socket %u error %s",
2229 ifp
->name
, ifp
->ifindex
, sock
,
2230 safe_strerror(errno
));
2232 if (IS_ZEBRA_DEBUG_EVENT
)
2234 "%s(%u): Join All-Routers multicast group, socket %u",
2235 ifp
->name
, ifp
->ifindex
, sock
);
2240 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2244 struct ipv6_mreq mreq
;
2246 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2247 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2248 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2250 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2255 "%s(%u): Failed to leave group, socket %u error %s",
2256 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
2258 if (IS_ZEBRA_DEBUG_EVENT
)
2260 "%s(%u): Leave All-Routers multicast group, socket %u",
2261 ifp
->name
, ifp
->ifindex
, sock
);
2267 void rtadv_init(struct zebra_vrf
*zvrf
)
2271 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2275 void rtadv_cmd_init(void)
2279 #endif /* HAVE_RTADV */