1 /* Router advertisement
2 * Copyright (C) 2016 Cumulus Networks
3 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
4 * Copyright (C) 1999 Kunihiro Ishiguro
6 * This file is part of GNU Zebra.
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "zebra_memory.h"
38 #include "lib_errors.h"
40 #include "zebra/interface.h"
41 #include "zebra/rtadv.h"
42 #include "zebra/debug.h"
43 #include "zebra/rib.h"
44 #include "zebra/zapi_msg.h"
45 #include "zebra/zebra_vrf.h"
46 #include "zebra/zebra_errors.h"
47 #include "zebra/zebra_router.h"
49 extern struct zebra_privs_t zserv_privs
;
51 #if defined(HAVE_RTADV)
53 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_PREFIX
, "Router Advertisement Prefix")
56 #include <netinet/icmp6.h>
59 /* If RFC2133 definition is used. */
60 #ifndef IPV6_JOIN_GROUP
61 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
63 #ifndef IPV6_LEAVE_GROUP
64 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
67 #define ALLNODE "ff02::1"
68 #define ALLROUTER "ff02::2"
70 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS")
71 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL")
73 /* Order is intentional. Matches RFC4191. This array is also used for
74 command matching, so only modify with care. */
75 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
85 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
87 static int if_join_all_router(int, struct interface
*);
88 static int if_leave_all_router(int, struct interface
*);
90 static int rtadv_get_socket(struct zebra_vrf
*zvrf
)
92 if (zvrf
->rtadv
.sock
> 0)
93 return zvrf
->rtadv
.sock
;
94 return zrouter
.rtadv_sock
;
97 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
100 struct interface
*iface
;
101 struct zebra_if
*zif
;
103 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
104 if (iface
&& iface
->info
) {
112 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
113 int buflen
, struct sockaddr_in6
*from
,
114 ifindex_t
*ifindex
, int *hoplimit
)
119 struct cmsghdr
*cmsgptr
;
124 /* Fill in message and iovec. */
125 memset(&msg
, 0, sizeof(msg
));
126 msg
.msg_name
= (void *)from
;
127 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
130 msg
.msg_control
= (void *)adata
;
131 msg
.msg_controllen
= sizeof adata
;
133 iov
.iov_len
= buflen
;
135 /* If recvmsg fail return minus value. */
136 ret
= recvmsg(sock
, &msg
, 0);
140 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
141 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
142 /* I want interface index which this packet comes from. */
143 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
144 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
145 struct in6_pktinfo
*ptr
;
147 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
148 *ifindex
= ptr
->ipi6_ifindex
;
149 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
152 /* Incoming packet's hop limit. */
153 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
154 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
155 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
160 rtadv_increment_received(zvrf
, ifindex
);
164 #define RTADV_MSG_SIZE 4096
166 /* Send router advertisement packet. */
167 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
171 struct cmsghdr
*cmsgptr
;
172 struct in6_pktinfo
*pkt
;
173 struct sockaddr_in6 addr
;
174 static void *adata
= NULL
;
175 unsigned char buf
[RTADV_MSG_SIZE
];
176 struct nd_router_advert
*rtadv
;
179 struct zebra_if
*zif
;
180 struct rtadv_prefix
*rprefix
;
181 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
182 0, 0, 0, 0, 0, 0, 0, 1};
183 struct listnode
*node
;
184 uint16_t pkt_RouterLifetime
;
187 * Allocate control message bufffer. This is dynamic because
188 * CMSG_SPACE is not guaranteed not to call a function. Note that
189 * the size will be different on different architectures due to
190 * differing alignment rules.
193 /* XXX Free on shutdown. */
194 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
198 "rtadv_send_packet: can't malloc control data");
203 /* Logging of packet. */
204 if (IS_ZEBRA_DEBUG_PACKET
)
205 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
208 /* Fill in sockaddr_in6. */
209 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
210 addr
.sin6_family
= AF_INET6
;
212 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
213 #endif /* SIN6_LEN */
214 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
215 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
217 /* Fetch interface information. */
220 /* Make router advertisement message. */
221 rtadv
= (struct nd_router_advert
*)buf
;
223 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
224 rtadv
->nd_ra_code
= 0;
225 rtadv
->nd_ra_cksum
= 0;
227 rtadv
->nd_ra_curhoplimit
= 64;
229 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
230 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
232 : zif
->rtadv
.DefaultPreference
;
233 rtadv
->nd_ra_flags_reserved
<<= 3;
235 if (zif
->rtadv
.AdvManagedFlag
)
236 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
237 if (zif
->rtadv
.AdvOtherConfigFlag
)
238 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
239 if (zif
->rtadv
.AdvHomeAgentFlag
)
240 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
241 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
242 * AdvDefaultLifetime is by default based on the value of
243 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
244 * field of Router Advertisements. Given that this field is expressed
245 * in seconds, a small MaxRtrAdvInterval value can result in a zero
246 * value for this field. To prevent this, routers SHOULD keep
247 * AdvDefaultLifetime in at least one second, even if the use of
248 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
250 zif
->rtadv
.AdvDefaultLifetime
!= -1
251 ? zif
->rtadv
.AdvDefaultLifetime
252 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
253 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
254 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
255 rtadv
->nd_ra_retransmit
= htonl(0);
257 len
= sizeof(struct nd_router_advert
);
259 /* If both the Home Agent Preference and Home Agent Lifetime are set to
260 * their default values specified above, this option SHOULD NOT be
261 * included in the Router Advertisement messages sent by this home
262 * agent. -- RFC6275, 7.4 */
263 if (zif
->rtadv
.AdvHomeAgentFlag
264 && (zif
->rtadv
.HomeAgentPreference
265 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
266 struct nd_opt_homeagent_info
*ndopt_hai
=
267 (struct nd_opt_homeagent_info
*)(buf
+ len
);
268 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
269 ndopt_hai
->nd_opt_hai_len
= 1;
270 ndopt_hai
->nd_opt_hai_reserved
= 0;
271 ndopt_hai
->nd_opt_hai_preference
=
272 htons(zif
->rtadv
.HomeAgentPreference
);
273 /* 16-bit unsigned integer. The lifetime associated with the
275 * agent in units of seconds. The default value is the same as
277 * Router Lifetime, as specified in the main body of the Router
278 * Advertisement. The maximum value corresponds to 18.2 hours.
280 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
281 ndopt_hai
->nd_opt_hai_lifetime
=
282 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
283 ? zif
->rtadv
.HomeAgentLifetime
284 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
289 len
+= sizeof(struct nd_opt_homeagent_info
);
292 if (zif
->rtadv
.AdvIntervalOption
) {
293 struct nd_opt_adv_interval
*ndopt_adv
=
294 (struct nd_opt_adv_interval
*)(buf
+ len
);
295 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
296 ndopt_adv
->nd_opt_ai_len
= 1;
297 ndopt_adv
->nd_opt_ai_reserved
= 0;
298 ndopt_adv
->nd_opt_ai_interval
=
299 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
300 len
+= sizeof(struct nd_opt_adv_interval
);
303 /* Fill in prefix. */
304 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
305 struct nd_opt_prefix_info
*pinfo
;
307 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
309 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
310 pinfo
->nd_opt_pi_len
= 4;
311 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
313 pinfo
->nd_opt_pi_flags_reserved
= 0;
314 if (rprefix
->AdvOnLinkFlag
)
315 pinfo
->nd_opt_pi_flags_reserved
|=
316 ND_OPT_PI_FLAG_ONLINK
;
317 if (rprefix
->AdvAutonomousFlag
)
318 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
319 if (rprefix
->AdvRouterAddressFlag
)
320 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
322 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
323 pinfo
->nd_opt_pi_preferred_time
=
324 htonl(rprefix
->AdvPreferredLifetime
);
325 pinfo
->nd_opt_pi_reserved2
= 0;
327 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
328 &rprefix
->prefix
.prefix
);
332 uint8_t buf
[INET6_ADDRSTRLEN
];
334 zlog_debug("DEBUG %s",
335 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
336 buf
, INET6_ADDRSTRLEN
));
340 len
+= sizeof(struct nd_opt_prefix_info
);
343 /* Hardware address. */
344 if (ifp
->hw_addr_len
!= 0) {
345 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
347 /* Option length should be rounded up to next octet if
348 the link address does not end on an octet boundary. */
349 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
351 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
352 len
+= ifp
->hw_addr_len
;
354 /* Pad option to end on an octet boundary. */
355 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
356 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
360 if (zif
->rtadv
.AdvLinkMTU
) {
361 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
362 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
363 opt
->nd_opt_mtu_len
= 1;
364 opt
->nd_opt_mtu_reserved
= 0;
365 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
366 len
+= sizeof(struct nd_opt_mtu
);
370 * There is no limit on the number of configurable recursive DNS
371 * servers or search list entries. We don't want the RA message
372 * to exceed the link's MTU (risking fragmentation) or even
373 * blow the stack buffer allocated for it.
375 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
377 /* Recursive DNS servers */
378 struct rtadv_rdnss
*rdnss
;
380 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
382 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
384 if (len
+ opt_len
> max_len
) {
386 "%s(%u): Tx RA: RDNSS option would exceed MTU, omitting it",
387 ifp
->name
, ifp
->ifindex
);
390 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
392 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
393 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
394 opt
->nd_opt_rdnss_reserved
= 0;
395 opt
->nd_opt_rdnss_lifetime
= htonl(
398 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
400 len
+= sizeof(struct nd_opt_rdnss
);
402 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
403 len
+= sizeof(struct in6_addr
);
406 /* DNS search list */
407 struct rtadv_dnssl
*dnssl
;
409 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
410 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
411 + ((dnssl
->encoded_len
+ 7) & ~7);
413 if (len
+ opt_len
> max_len
) {
415 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
416 ifp
->name
, ifp
->ifindex
);
419 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
421 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
422 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
423 opt
->nd_opt_dnssl_reserved
= 0;
424 opt
->nd_opt_dnssl_lifetime
= htonl(
427 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
429 len
+= sizeof(struct nd_opt_dnssl
);
431 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
432 len
+= dnssl
->encoded_len
;
434 /* Zero-pad to 8-octet boundary */
441 msg
.msg_name
= (void *)&addr
;
442 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
445 msg
.msg_control
= (void *)adata
;
446 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
451 cmsgptr
= CMSG_FIRSTHDR(&msg
);
452 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
453 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
454 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
456 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
457 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
458 pkt
->ipi6_ifindex
= ifp
->ifindex
;
460 ret
= sendmsg(sock
, &msg
, 0);
462 flog_err_sys(EC_LIB_SOCKET
,
463 "%s(%u): Tx RA failed, socket %u error %d (%s)",
464 ifp
->name
, ifp
->ifindex
, sock
, errno
,
465 safe_strerror(errno
));
470 static int rtadv_timer(struct thread
*thread
)
472 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
474 struct interface
*ifp
;
475 struct zebra_if
*zif
;
478 zvrf
->rtadv
.ra_timer
= NULL
;
479 if (zvrf
->rtadv
.adv_msec_if_count
== 0) {
480 period
= 1000; /* 1 s */
481 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
483 period
= 10; /* 10 ms */
484 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
487 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
488 FOR_ALL_INTERFACES (vrf
, ifp
) {
489 if (if_is_loopback(ifp
)
490 || CHECK_FLAG(ifp
->status
,
491 ZEBRA_INTERFACE_VRF_LOOPBACK
)
492 || !if_is_operative(ifp
))
497 if (zif
->rtadv
.AdvSendAdvertisements
) {
498 if (zif
->rtadv
.inFastRexmit
) {
499 /* We assume we fast rexmit every sec so
502 if (--zif
->rtadv
.NumFastReXmitsRemain
504 zif
->rtadv
.inFastRexmit
= 0;
506 if (IS_ZEBRA_DEBUG_SEND
)
508 "Fast RA Rexmit on interface %s",
511 rtadv_send_packet(rtadv_get_socket(zvrf
),
514 zif
->rtadv
.AdvIntervalTimer
-= period
;
515 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
517 MaxRtrAdvInterval each
518 time isn't what section
519 6.2.4 of RFC4861 tells to do.
521 zif
->rtadv
.AdvIntervalTimer
=
525 rtadv_get_socket(zvrf
),
535 static void rtadv_process_solicit(struct interface
*ifp
)
537 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
540 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
);
544 * This function processes optional attributes off of
545 * end of a RA packet received. At this point in
546 * time we only care about this in one situation
547 * which is when a interface does not have a LL
548 * v6 address. We still need to be able to install
549 * the mac address for v4 to v6 resolution
551 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
552 struct interface
*ifp
,
553 struct sockaddr_in6
*addr
)
558 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
560 switch(opt_hdr
->nd_opt_type
) {
561 case ND_OPT_SOURCE_LINKADDR
:
562 mac
= (char *)(optional
+2);
563 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
564 &addr
->sin6_addr
, 1);
570 len
-= 8 * opt_hdr
->nd_opt_len
;
571 optional
+= 8 * opt_hdr
->nd_opt_len
;
575 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
576 struct interface
*ifp
,
577 struct sockaddr_in6
*addr
)
579 struct nd_router_advert
*radvert
;
580 char addr_str
[INET6_ADDRSTRLEN
];
581 struct zebra_if
*zif
;
586 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
588 if (len
< sizeof(struct nd_router_advert
)) {
589 if (IS_ZEBRA_DEBUG_PACKET
)
590 zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
591 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
595 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
596 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
597 len
- sizeof(struct nd_router_advert
),
599 if (IS_ZEBRA_DEBUG_PACKET
)
600 zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s",
601 ifp
->name
, ifp
->ifindex
, addr_str
);
605 radvert
= (struct nd_router_advert
*)msg
;
607 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
608 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
610 EC_ZEBRA_RA_PARAM_MISMATCH
,
611 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
612 ifp
->name
, ifp
->ifindex
, addr_str
);
615 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
616 && !zif
->rtadv
.AdvManagedFlag
) {
618 EC_ZEBRA_RA_PARAM_MISMATCH
,
619 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
620 ifp
->name
, ifp
->ifindex
, addr_str
);
623 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
624 && !zif
->rtadv
.AdvOtherConfigFlag
) {
626 EC_ZEBRA_RA_PARAM_MISMATCH
,
627 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
628 ifp
->name
, ifp
->ifindex
, addr_str
);
631 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
632 && (ntohl(radvert
->nd_ra_reachable
)
633 != zif
->rtadv
.AdvReachableTime
)) {
635 EC_ZEBRA_RA_PARAM_MISMATCH
,
636 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
637 ifp
->name
, ifp
->ifindex
, addr_str
);
640 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
641 && (ntohl(radvert
->nd_ra_retransmit
)
642 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
644 EC_ZEBRA_RA_PARAM_MISMATCH
,
645 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
646 ifp
->name
, ifp
->ifindex
, addr_str
);
649 /* Create entry for neighbor if not known. */
651 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
652 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
654 if (!nbr_connected_check(ifp
, &p
))
655 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
659 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
660 ifindex_t ifindex
, int hoplimit
,
661 struct sockaddr_in6
*from
,
662 struct zebra_vrf
*zvrf
)
664 struct icmp6_hdr
*icmph
;
665 struct interface
*ifp
;
666 struct zebra_if
*zif
;
667 char addr_str
[INET6_ADDRSTRLEN
];
669 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
671 /* Interface search. */
672 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
674 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
675 "RA/RS received on unknown IF %u from %s", ifindex
,
680 if (IS_ZEBRA_DEBUG_PACKET
)
681 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
682 ifp
->ifindex
, len
, addr_str
);
684 if (if_is_loopback(ifp
)
685 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
688 /* Check interface configuration. */
690 if (!zif
->rtadv
.AdvSendAdvertisements
)
693 /* ICMP message length check. */
694 if (len
< sizeof(struct icmp6_hdr
)) {
695 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
696 ifp
->name
, ifp
->ifindex
, len
);
700 icmph
= (struct icmp6_hdr
*)buf
;
702 /* ICMP message type check. */
703 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
704 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
705 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
706 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
710 /* Hoplimit check. */
711 if (hoplimit
>= 0 && hoplimit
!= 255) {
712 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
713 ifp
->ifindex
, hoplimit
);
717 /* Check ICMP message type. */
718 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
719 rtadv_process_solicit(ifp
);
720 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
721 rtadv_process_advert(buf
, len
, ifp
, from
);
726 static int rtadv_read(struct thread
*thread
)
730 uint8_t buf
[RTADV_MSG_SIZE
];
731 struct sockaddr_in6 from
;
732 ifindex_t ifindex
= 0;
734 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
736 sock
= THREAD_FD(thread
);
737 zvrf
->rtadv
.ra_read
= NULL
;
739 /* Register myself. */
740 rtadv_event(zvrf
, RTADV_READ
, sock
);
742 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
746 flog_err_sys(EC_LIB_SOCKET
,
747 "RA/RS recv failed, socket %u error %s", sock
,
748 safe_strerror(errno
));
752 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
757 static int rtadv_make_socket(ns_id_t ns_id
)
761 struct icmp6_filter filter
;
763 frr_elevate_privs(&zserv_privs
) {
765 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
773 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
778 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
783 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
788 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
793 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
799 ICMP6_FILTER_SETBLOCKALL(&filter
);
800 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
801 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
803 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
804 sizeof(struct icmp6_filter
));
806 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
814 static struct rtadv_prefix
*rtadv_prefix_new(void)
816 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
819 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
821 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
824 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
825 struct prefix_ipv6
*p
)
827 struct listnode
*node
;
828 struct rtadv_prefix
*rprefix
;
830 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
831 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
837 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
838 struct prefix_ipv6
*p
)
840 struct rtadv_prefix
*rprefix
;
842 rprefix
= rtadv_prefix_lookup(rplist
, p
);
846 rprefix
= rtadv_prefix_new();
847 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
848 listnode_add(rplist
, rprefix
);
853 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
855 struct rtadv_prefix
*rprefix
;
857 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
859 /* Set parameters. */
860 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
861 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
862 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
863 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
864 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
867 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
869 struct rtadv_prefix
*rprefix
;
871 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
872 if (rprefix
!= NULL
) {
873 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
874 rtadv_prefix_free(rprefix
);
880 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
881 ipv6_nd_suppress_ra_status status
)
883 struct zebra_if
*zif
;
884 struct zebra_vrf
*zvrf
;
887 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
889 if (status
== RA_SUPPRESS
) {
890 /* RA is currently enabled */
891 if (zif
->rtadv
.AdvSendAdvertisements
) {
892 zif
->rtadv
.AdvSendAdvertisements
= 0;
893 zif
->rtadv
.AdvIntervalTimer
= 0;
894 zvrf
->rtadv
.adv_if_count
--;
896 if_leave_all_router(rtadv_get_socket(zvrf
), ifp
);
898 if (zvrf
->rtadv
.adv_if_count
== 0)
899 rtadv_event(zvrf
, RTADV_STOP
, 0);
902 if (!zif
->rtadv
.AdvSendAdvertisements
) {
903 zif
->rtadv
.AdvSendAdvertisements
= 1;
904 zif
->rtadv
.AdvIntervalTimer
= 0;
905 zvrf
->rtadv
.adv_if_count
++;
907 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
908 /* Enable Fast RA only when RA interval is in
910 zif
->rtadv
.inFastRexmit
= 1;
911 zif
->rtadv
.NumFastReXmitsRemain
=
912 RTADV_NUM_FAST_REXMITS
;
915 if_join_all_router(rtadv_get_socket(zvrf
), ifp
);
917 if (zvrf
->rtadv
.adv_if_count
== 1)
918 rtadv_event(zvrf
, RTADV_START
,
919 rtadv_get_socket(zvrf
));
925 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
926 * Note that while the client could request RA on an interface on which the
927 * operator has not enabled RA, RA won't be disabled upon client request
928 * if the operator has explicitly enabled RA. The enable request can also
929 * specify a RA interval (in seconds).
931 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
935 struct interface
*ifp
;
936 struct zebra_if
*zif
;
941 /* Get interface index and RA interval. */
942 STREAM_GETL(s
, ifindex
);
943 STREAM_GETL(s
, ra_interval
);
945 if (IS_ZEBRA_DEBUG_EVENT
)
946 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
947 zvrf_id(zvrf
), ifindex
,
948 enable
? "enable" : "disable",
949 zebra_route_string(client
->proto
), ra_interval
);
951 /* Locate interface and check VRF match. */
952 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
954 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
955 "%u: IF %u RA %s client %s - interface unknown",
956 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
957 zebra_route_string(client
->proto
));
960 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
962 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
963 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
964 zebra_route_string(client
->proto
), ifp
->vrf_id
);
970 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
971 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
973 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
974 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
975 VTY_RA_INTERVAL_CONFIGURED
))
976 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
978 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
979 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
980 VTY_RA_INTERVAL_CONFIGURED
))
981 zif
->rtadv
.MaxRtrAdvInterval
=
982 RTADV_MAX_RTR_ADV_INTERVAL
;
983 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
984 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
990 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
992 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
994 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
996 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
999 DEFUN (ipv6_nd_suppress_ra
,
1000 ipv6_nd_suppress_ra_cmd
,
1001 "ipv6 nd suppress-ra",
1002 "Interface IPv6 config commands\n"
1003 "Neighbor discovery\n"
1004 "Suppress Router Advertisement\n")
1006 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1007 struct zebra_if
*zif
= ifp
->info
;
1009 if (if_is_loopback(ifp
)
1010 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1012 "Cannot configure IPv6 Router Advertisements on this interface\n");
1013 return CMD_WARNING_CONFIG_FAILED
;
1016 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1017 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1019 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1023 DEFUN (no_ipv6_nd_suppress_ra
,
1024 no_ipv6_nd_suppress_ra_cmd
,
1025 "no ipv6 nd suppress-ra",
1027 "Interface IPv6 config commands\n"
1028 "Neighbor discovery\n"
1029 "Suppress Router Advertisement\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 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1042 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1046 DEFUN (ipv6_nd_ra_interval_msec
,
1047 ipv6_nd_ra_interval_msec_cmd
,
1048 "ipv6 nd ra-interval msec (70-1800000)",
1049 "Interface IPv6 config commands\n"
1050 "Neighbor discovery\n"
1051 "Router Advertisement interval\n"
1052 "Router Advertisement interval in milliseconds\n"
1053 "Router Advertisement interval in milliseconds\n")
1056 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1058 struct zebra_if
*zif
= ifp
->info
;
1059 struct zebra_vrf
*zvrf
;
1061 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1063 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1064 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1065 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1067 "This ra-interval would conflict with configured ra-lifetime!\n");
1068 return CMD_WARNING_CONFIG_FAILED
;
1071 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1072 zvrf
->rtadv
.adv_msec_if_count
--;
1074 if (interval
% 1000)
1075 zvrf
->rtadv
.adv_msec_if_count
++;
1077 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1078 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1079 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1080 zif
->rtadv
.AdvIntervalTimer
= 0;
1085 DEFUN (ipv6_nd_ra_interval
,
1086 ipv6_nd_ra_interval_cmd
,
1087 "ipv6 nd ra-interval (1-1800)",
1088 "Interface IPv6 config commands\n"
1089 "Neighbor discovery\n"
1090 "Router Advertisement interval\n"
1091 "Router Advertisement interval in seconds\n")
1094 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1096 struct zebra_if
*zif
= ifp
->info
;
1097 struct zebra_vrf
*zvrf
;
1099 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1101 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1102 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1103 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1105 "This ra-interval would conflict with configured ra-lifetime!\n");
1106 return CMD_WARNING_CONFIG_FAILED
;
1109 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1110 zvrf
->rtadv
.adv_msec_if_count
--;
1112 /* convert to milliseconds */
1113 interval
= interval
* 1000;
1115 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1116 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1117 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1118 zif
->rtadv
.AdvIntervalTimer
= 0;
1123 DEFUN (no_ipv6_nd_ra_interval
,
1124 no_ipv6_nd_ra_interval_cmd
,
1125 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1127 "Interface IPv6 config commands\n"
1128 "Neighbor discovery\n"
1129 "Router Advertisement interval\n"
1130 "Router Advertisement interval in seconds\n"
1131 "Specify millisecond router advertisement interval\n"
1132 "Router Advertisement interval in milliseconds\n")
1134 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1135 struct zebra_if
*zif
= ifp
->info
;
1136 struct zebra_vrf
*zvrf
= NULL
;
1138 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1140 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1141 zvrf
->rtadv
.adv_msec_if_count
--;
1143 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1145 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1146 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1148 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1150 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1151 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1156 DEFUN (ipv6_nd_ra_lifetime
,
1157 ipv6_nd_ra_lifetime_cmd
,
1158 "ipv6 nd ra-lifetime (0-9000)",
1159 "Interface IPv6 config commands\n"
1160 "Neighbor discovery\n"
1162 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1165 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1166 struct zebra_if
*zif
= ifp
->info
;
1169 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1171 /* The value to be placed in the Router Lifetime field
1172 * of Router Advertisements sent from the interface,
1173 * in seconds. MUST be either zero or between
1174 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1175 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1177 "This ra-lifetime would conflict with configured ra-interval\n");
1178 return CMD_WARNING_CONFIG_FAILED
;
1181 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1186 DEFUN (no_ipv6_nd_ra_lifetime
,
1187 no_ipv6_nd_ra_lifetime_cmd
,
1188 "no ipv6 nd ra-lifetime [(0-9000)]",
1190 "Interface IPv6 config commands\n"
1191 "Neighbor discovery\n"
1193 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1195 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1196 struct zebra_if
*zif
= ifp
->info
;
1198 zif
->rtadv
.AdvDefaultLifetime
= -1;
1203 DEFUN (ipv6_nd_reachable_time
,
1204 ipv6_nd_reachable_time_cmd
,
1205 "ipv6 nd reachable-time (1-3600000)",
1206 "Interface IPv6 config commands\n"
1207 "Neighbor discovery\n"
1209 "Reachable time in milliseconds\n")
1212 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1213 struct zebra_if
*zif
= ifp
->info
;
1214 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1218 DEFUN (no_ipv6_nd_reachable_time
,
1219 no_ipv6_nd_reachable_time_cmd
,
1220 "no ipv6 nd reachable-time [(1-3600000)]",
1222 "Interface IPv6 config commands\n"
1223 "Neighbor discovery\n"
1225 "Reachable time in milliseconds\n")
1227 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1228 struct zebra_if
*zif
= ifp
->info
;
1230 zif
->rtadv
.AdvReachableTime
= 0;
1235 DEFUN (ipv6_nd_homeagent_preference
,
1236 ipv6_nd_homeagent_preference_cmd
,
1237 "ipv6 nd home-agent-preference (0-65535)",
1238 "Interface IPv6 config commands\n"
1239 "Neighbor discovery\n"
1240 "Home Agent preference\n"
1241 "preference value (default is 0, least preferred)\n")
1244 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1245 struct zebra_if
*zif
= ifp
->info
;
1246 zif
->rtadv
.HomeAgentPreference
=
1247 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1251 DEFUN (no_ipv6_nd_homeagent_preference
,
1252 no_ipv6_nd_homeagent_preference_cmd
,
1253 "no ipv6 nd home-agent-preference [(0-65535)]",
1255 "Interface IPv6 config commands\n"
1256 "Neighbor discovery\n"
1257 "Home Agent preference\n"
1258 "preference value (default is 0, least preferred)\n")
1260 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1261 struct zebra_if
*zif
= ifp
->info
;
1263 zif
->rtadv
.HomeAgentPreference
= 0;
1268 DEFUN (ipv6_nd_homeagent_lifetime
,
1269 ipv6_nd_homeagent_lifetime_cmd
,
1270 "ipv6 nd home-agent-lifetime (0-65520)",
1271 "Interface IPv6 config commands\n"
1272 "Neighbor discovery\n"
1273 "Home Agent lifetime\n"
1274 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1277 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1278 struct zebra_if
*zif
= ifp
->info
;
1279 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1283 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1284 no_ipv6_nd_homeagent_lifetime_cmd
,
1285 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1287 "Interface IPv6 config commands\n"
1288 "Neighbor discovery\n"
1289 "Home Agent lifetime\n"
1290 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1292 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1293 struct zebra_if
*zif
= ifp
->info
;
1295 zif
->rtadv
.HomeAgentLifetime
= -1;
1300 DEFUN (ipv6_nd_managed_config_flag
,
1301 ipv6_nd_managed_config_flag_cmd
,
1302 "ipv6 nd managed-config-flag",
1303 "Interface IPv6 config commands\n"
1304 "Neighbor discovery\n"
1305 "Managed address configuration flag\n")
1307 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1308 struct zebra_if
*zif
= ifp
->info
;
1310 zif
->rtadv
.AdvManagedFlag
= 1;
1315 DEFUN (no_ipv6_nd_managed_config_flag
,
1316 no_ipv6_nd_managed_config_flag_cmd
,
1317 "no ipv6 nd managed-config-flag",
1319 "Interface IPv6 config commands\n"
1320 "Neighbor discovery\n"
1321 "Managed address configuration flag\n")
1323 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1324 struct zebra_if
*zif
= ifp
->info
;
1326 zif
->rtadv
.AdvManagedFlag
= 0;
1331 DEFUN (ipv6_nd_homeagent_config_flag
,
1332 ipv6_nd_homeagent_config_flag_cmd
,
1333 "ipv6 nd home-agent-config-flag",
1334 "Interface IPv6 config commands\n"
1335 "Neighbor discovery\n"
1336 "Home Agent configuration flag\n")
1338 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1339 struct zebra_if
*zif
= ifp
->info
;
1341 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1346 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1347 no_ipv6_nd_homeagent_config_flag_cmd
,
1348 "no ipv6 nd home-agent-config-flag",
1350 "Interface IPv6 config commands\n"
1351 "Neighbor discovery\n"
1352 "Home Agent configuration flag\n")
1354 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1355 struct zebra_if
*zif
= ifp
->info
;
1357 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1362 DEFUN (ipv6_nd_adv_interval_config_option
,
1363 ipv6_nd_adv_interval_config_option_cmd
,
1364 "ipv6 nd adv-interval-option",
1365 "Interface IPv6 config commands\n"
1366 "Neighbor discovery\n"
1367 "Advertisement Interval Option\n")
1369 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1370 struct zebra_if
*zif
= ifp
->info
;
1372 zif
->rtadv
.AdvIntervalOption
= 1;
1377 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1378 no_ipv6_nd_adv_interval_config_option_cmd
,
1379 "no ipv6 nd adv-interval-option",
1381 "Interface IPv6 config commands\n"
1382 "Neighbor discovery\n"
1383 "Advertisement Interval Option\n")
1385 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1386 struct zebra_if
*zif
= ifp
->info
;
1388 zif
->rtadv
.AdvIntervalOption
= 0;
1393 DEFUN (ipv6_nd_other_config_flag
,
1394 ipv6_nd_other_config_flag_cmd
,
1395 "ipv6 nd other-config-flag",
1396 "Interface IPv6 config commands\n"
1397 "Neighbor discovery\n"
1398 "Other statefull configuration flag\n")
1400 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1401 struct zebra_if
*zif
= ifp
->info
;
1403 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1408 DEFUN (no_ipv6_nd_other_config_flag
,
1409 no_ipv6_nd_other_config_flag_cmd
,
1410 "no ipv6 nd other-config-flag",
1412 "Interface IPv6 config commands\n"
1413 "Neighbor discovery\n"
1414 "Other statefull configuration flag\n")
1416 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1417 struct zebra_if
*zif
= ifp
->info
;
1419 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1424 DEFUN (ipv6_nd_prefix
,
1426 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1427 "Interface IPv6 config commands\n"
1428 "Neighbor discovery\n"
1429 "Prefix information\n"
1431 "Valid lifetime in seconds\n"
1432 "Infinite valid lifetime\n"
1433 "Preferred lifetime in seconds\n"
1434 "Infinite preferred lifetime\n"
1435 "Set Router Address flag\n"
1436 "Do not use prefix for onlink determination\n"
1437 "Do not use prefix for autoconfiguration\n"
1438 "Do not use prefix for autoconfiguration\n"
1439 "Do not use prefix for onlink determination\n")
1442 char *prefix
= argv
[3]->arg
;
1443 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1444 || strmatch(argv
[4]->text
, "infinite"));
1445 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1447 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1449 char *lifetime
= NULL
, *preflifetime
= NULL
;
1450 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1452 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1454 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1459 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1461 offlink
= (argc
> idx_routeropts
+ 1
1462 || strmatch(argv
[idx_routeropts
]->text
,
1464 noautoconf
= (argc
> idx_routeropts
+ 1
1465 || strmatch(argv
[idx_routeropts
]->text
,
1471 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1472 struct zebra_if
*zebra_if
= ifp
->info
;
1474 struct rtadv_prefix rp
;
1476 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1478 vty_out(vty
, "Malformed IPv6 prefix\n");
1479 return CMD_WARNING_CONFIG_FAILED
;
1481 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1482 rp
.AdvOnLinkFlag
= !offlink
;
1483 rp
.AdvAutonomousFlag
= !noautoconf
;
1484 rp
.AdvRouterAddressFlag
= routeraddr
;
1485 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1486 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1489 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1491 : strtoll(lifetime
, NULL
, 10);
1492 rp
.AdvPreferredLifetime
=
1493 strmatch(preflifetime
, "infinite")
1495 : strtoll(preflifetime
, NULL
, 10);
1496 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1497 vty_out(vty
, "Invalid preferred lifetime\n");
1498 return CMD_WARNING_CONFIG_FAILED
;
1502 rtadv_prefix_set(zebra_if
, &rp
);
1507 DEFUN (no_ipv6_nd_prefix
,
1508 no_ipv6_nd_prefix_cmd
,
1509 "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]>]",
1511 "Interface IPv6 config commands\n"
1512 "Neighbor discovery\n"
1513 "Prefix information\n"
1515 "Valid lifetime in seconds\n"
1516 "Infinite valid lifetime\n"
1517 "Preferred lifetime in seconds\n"
1518 "Infinite preferred lifetime\n"
1519 "Set Router Address flag\n"
1520 "Do not use prefix for onlink determination\n"
1521 "Do not use prefix for autoconfiguration\n"
1522 "Do not use prefix for autoconfiguration\n"
1523 "Do not use prefix for onlink determination\n")
1525 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1526 struct zebra_if
*zebra_if
= ifp
->info
;
1528 struct rtadv_prefix rp
;
1529 char *prefix
= argv
[4]->arg
;
1531 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1533 vty_out(vty
, "Malformed IPv6 prefix\n");
1534 return CMD_WARNING_CONFIG_FAILED
;
1536 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1538 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1540 vty_out(vty
, "Non-existant IPv6 prefix\n");
1541 return CMD_WARNING_CONFIG_FAILED
;
1547 DEFUN (ipv6_nd_router_preference
,
1548 ipv6_nd_router_preference_cmd
,
1549 "ipv6 nd router-preference <high|medium|low>",
1550 "Interface IPv6 config commands\n"
1551 "Neighbor discovery\n"
1552 "Default router preference\n"
1553 "High default router preference\n"
1554 "Medium default router preference (default)\n"
1555 "Low default router preference\n")
1557 int idx_high_medium_low
= 3;
1558 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1559 struct zebra_if
*zif
= ifp
->info
;
1562 while (0 != rtadv_pref_strs
[i
]) {
1563 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1566 zif
->rtadv
.DefaultPreference
= i
;
1572 return CMD_ERR_NO_MATCH
;
1575 DEFUN (no_ipv6_nd_router_preference
,
1576 no_ipv6_nd_router_preference_cmd
,
1577 "no ipv6 nd router-preference [<high|medium|low>]",
1579 "Interface IPv6 config commands\n"
1580 "Neighbor discovery\n"
1581 "Default router preference\n"
1582 "High default router preference\n"
1583 "Medium default router preference (default)\n"
1584 "Low default router preference\n")
1586 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1587 struct zebra_if
*zif
= ifp
->info
;
1589 zif
->rtadv
.DefaultPreference
=
1590 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1597 "ipv6 nd mtu (1-65535)",
1598 "Interface IPv6 config commands\n"
1599 "Neighbor discovery\n"
1604 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1605 struct zebra_if
*zif
= ifp
->info
;
1606 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1610 DEFUN (no_ipv6_nd_mtu
,
1612 "no ipv6 nd mtu [(1-65535)]",
1614 "Interface IPv6 config commands\n"
1615 "Neighbor discovery\n"
1619 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1620 struct zebra_if
*zif
= ifp
->info
;
1621 zif
->rtadv
.AdvLinkMTU
= 0;
1625 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
1627 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
1630 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
1632 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
1635 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
1636 struct rtadv_rdnss
*rdnss
)
1638 struct listnode
*node
;
1639 struct rtadv_rdnss
*p
;
1641 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1642 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
1647 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
1648 struct rtadv_rdnss
*rdnss
)
1650 struct rtadv_rdnss
*p
;
1652 p
= rtadv_rdnss_lookup(list
, rdnss
);
1656 p
= rtadv_rdnss_new();
1657 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
1658 listnode_add(list
, p
);
1663 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1665 struct rtadv_rdnss
*p
;
1667 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1668 p
->lifetime
= rdnss
->lifetime
;
1669 p
->lifetime_set
= rdnss
->lifetime_set
;
1672 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1674 struct rtadv_rdnss
*p
;
1676 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1678 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
1679 rtadv_rdnss_free(p
);
1686 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
1688 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
1691 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
1693 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
1696 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
1697 struct rtadv_dnssl
*dnssl
)
1699 struct listnode
*node
;
1700 struct rtadv_dnssl
*p
;
1702 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1703 if (!strcasecmp(p
->name
, dnssl
->name
))
1708 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
1709 struct rtadv_dnssl
*dnssl
)
1711 struct rtadv_dnssl
*p
;
1713 p
= rtadv_dnssl_lookup(list
, dnssl
);
1717 p
= rtadv_dnssl_new();
1718 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1719 listnode_add(list
, p
);
1724 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1726 struct rtadv_dnssl
*p
;
1728 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1729 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1732 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1734 struct rtadv_dnssl
*p
;
1736 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1738 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
1739 rtadv_dnssl_free(p
);
1747 * Convert dotted domain name (with or without trailing root zone dot) to
1748 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
1749 * to strlen(in) + 2 octets to out.
1751 * Returns the number of octets written to out or -1 if in does not constitute
1752 * a valid domain name.
1754 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
1756 const char *label_start
, *label_end
;
1762 while (*label_start
) {
1765 label_end
= strchr(label_start
, '.');
1766 if (label_end
== NULL
)
1767 label_end
= label_start
+ strlen(label_start
);
1769 label_len
= label_end
- label_start
;
1770 if (label_len
>= 64)
1771 return -1; /* labels must be 63 octets or less */
1773 out
[outp
++] = (uint8_t)label_len
;
1774 memcpy(out
+ outp
, label_start
, label_len
);
1776 label_start
+= label_len
;
1777 if (*label_start
== '.')
1785 DEFUN(ipv6_nd_rdnss
,
1787 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1788 "Interface IPv6 config commands\n"
1789 "Neighbor discovery\n"
1790 "Recursive DNS server information\n"
1792 "Valid lifetime in seconds\n"
1793 "Infinite valid lifetime\n")
1795 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1796 struct zebra_if
*zif
= ifp
->info
;
1797 struct rtadv_rdnss rdnss
= {};
1799 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
1800 vty_out(vty
, "Malformed IPv6 address\n");
1801 return CMD_WARNING_CONFIG_FAILED
;
1804 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1806 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
1808 : strtoll(lifetime
, NULL
, 10);
1809 rdnss
.lifetime_set
= 1;
1812 rtadv_rdnss_set(zif
, &rdnss
);
1817 DEFUN(no_ipv6_nd_rdnss
,
1818 no_ipv6_nd_rdnss_cmd
,
1819 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1821 "Interface IPv6 config commands\n"
1822 "Neighbor discovery\n"
1823 "Recursive DNS server information\n"
1825 "Valid lifetime in seconds\n"
1826 "Infinite valid lifetime\n")
1828 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1829 struct zebra_if
*zif
= ifp
->info
;
1830 struct rtadv_rdnss rdnss
= {};
1832 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
1833 vty_out(vty
, "Malformed IPv6 address\n");
1834 return CMD_WARNING_CONFIG_FAILED
;
1836 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
1837 vty_out(vty
, "Non-existant RDNSS address\n");
1838 return CMD_WARNING_CONFIG_FAILED
;
1844 DEFUN(ipv6_nd_dnssl
,
1846 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1847 "Interface IPv6 config commands\n"
1848 "Neighbor discovery\n"
1849 "DNS search list information\n"
1850 "Domain name suffix\n"
1851 "Valid lifetime in seconds\n"
1852 "Infinite valid lifetime\n")
1854 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1855 struct zebra_if
*zif
= ifp
->info
;
1856 struct rtadv_dnssl dnssl
= {};
1860 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
1861 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1862 vty_out(vty
, "Malformed DNS search domain\n");
1863 return CMD_WARNING_CONFIG_FAILED
;
1865 if (dnssl
.name
[len
- 1] == '.') {
1867 * Allow, but don't require, a trailing dot signifying the root
1868 * zone. Canonicalize by cutting it off if present.
1870 dnssl
.name
[len
- 1] = '\0';
1874 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1876 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
1878 : strtoll(lifetime
, NULL
, 10);
1879 dnssl
.lifetime_set
= 1;
1882 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
1884 vty_out(vty
, "Malformed DNS search domain\n");
1885 return CMD_WARNING_CONFIG_FAILED
;
1887 dnssl
.encoded_len
= ret
;
1888 rtadv_dnssl_set(zif
, &dnssl
);
1893 DEFUN(no_ipv6_nd_dnssl
,
1894 no_ipv6_nd_dnssl_cmd
,
1895 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1897 "Interface IPv6 config commands\n"
1898 "Neighbor discovery\n"
1899 "DNS search list information\n"
1900 "Domain name suffix\n"
1901 "Valid lifetime in seconds\n"
1902 "Infinite valid lifetime\n")
1904 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1905 struct zebra_if
*zif
= ifp
->info
;
1906 struct rtadv_dnssl dnssl
= {};
1909 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
1910 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1911 vty_out(vty
, "Malformed DNS search domain\n");
1912 return CMD_WARNING_CONFIG_FAILED
;
1914 if (dnssl
.name
[len
- 1] == '.') {
1915 dnssl
.name
[len
- 1] = '\0';
1918 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
1919 vty_out(vty
, "Non-existant DNS search domain\n");
1920 return CMD_WARNING_CONFIG_FAILED
;
1927 /* Dump interface ND information to vty. */
1928 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1930 struct zebra_if
*zif
;
1931 struct rtadvconf
*rtadv
;
1934 zif
= (struct zebra_if
*)ifp
->info
;
1935 rtadv
= &zif
->rtadv
;
1937 if (rtadv
->AdvSendAdvertisements
) {
1939 " ND advertised reachable time is %d milliseconds\n",
1940 rtadv
->AdvReachableTime
);
1942 " ND advertised retransmit interval is %d milliseconds\n",
1943 rtadv
->AdvRetransTimer
);
1944 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1945 zif
->ra_sent
, zif
->ra_rcvd
);
1946 interval
= rtadv
->MaxRtrAdvInterval
;
1947 if (interval
% 1000)
1949 " ND router advertisements are sent every "
1950 "%d milliseconds\n",
1954 " ND router advertisements are sent every "
1957 if (rtadv
->AdvDefaultLifetime
!= -1)
1959 " ND router advertisements live for %d seconds\n",
1960 rtadv
->AdvDefaultLifetime
);
1963 " ND router advertisements lifetime tracks ra-interval\n");
1965 " ND router advertisement default router preference is "
1967 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1968 if (rtadv
->AdvManagedFlag
)
1970 " Hosts use DHCP to obtain routable addresses.\n");
1973 " Hosts use stateless autoconfig for addresses.\n");
1974 if (rtadv
->AdvHomeAgentFlag
) {
1976 " ND router advertisements with Home Agent flag bit set.\n");
1977 if (rtadv
->HomeAgentLifetime
!= -1)
1979 " Home Agent lifetime is %u seconds\n",
1980 rtadv
->HomeAgentLifetime
);
1983 " Home Agent lifetime tracks ra-lifetime\n");
1984 vty_out(vty
, " Home Agent preference is %u\n",
1985 rtadv
->HomeAgentPreference
);
1987 if (rtadv
->AdvIntervalOption
)
1989 " ND router advertisements with Adv. Interval option.\n");
1995 /* Write configuration about router advertisement. */
1996 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1998 struct zebra_if
*zif
;
1999 struct listnode
*node
;
2000 struct rtadv_prefix
*rprefix
;
2001 struct rtadv_rdnss
*rdnss
;
2002 struct rtadv_dnssl
*dnssl
;
2003 char buf
[PREFIX_STRLEN
];
2008 if (!(if_is_loopback(ifp
)
2009 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
2010 if (zif
->rtadv
.AdvSendAdvertisements
2011 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2012 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2015 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2016 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2017 if (interval
% 1000)
2018 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2020 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2021 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2025 if (zif
->rtadv
.AdvIntervalOption
)
2026 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2028 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2029 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2030 zif
->rtadv
.AdvDefaultLifetime
);
2032 if (zif
->rtadv
.HomeAgentPreference
)
2033 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2034 zif
->rtadv
.HomeAgentPreference
);
2036 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2037 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2038 zif
->rtadv
.HomeAgentLifetime
);
2040 if (zif
->rtadv
.AdvHomeAgentFlag
)
2041 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2043 if (zif
->rtadv
.AdvReachableTime
)
2044 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2045 zif
->rtadv
.AdvReachableTime
);
2047 if (zif
->rtadv
.AdvManagedFlag
)
2048 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2050 if (zif
->rtadv
.AdvOtherConfigFlag
)
2051 vty_out(vty
, " ipv6 nd other-config-flag\n");
2053 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2054 vty_out(vty
, " ipv6 nd router-preference %s\n",
2055 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2057 if (zif
->rtadv
.AdvLinkMTU
)
2058 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2060 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
2061 vty_out(vty
, " ipv6 nd prefix %s",
2062 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
2063 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2064 || (rprefix
->AdvPreferredLifetime
2065 != RTADV_PREFERRED_LIFETIME
)) {
2066 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2067 vty_out(vty
, " infinite");
2069 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
2070 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2071 vty_out(vty
, " infinite");
2074 rprefix
->AdvPreferredLifetime
);
2076 if (!rprefix
->AdvOnLinkFlag
)
2077 vty_out(vty
, " off-link");
2078 if (!rprefix
->AdvAutonomousFlag
)
2079 vty_out(vty
, " no-autoconfig");
2080 if (rprefix
->AdvRouterAddressFlag
)
2081 vty_out(vty
, " router-address");
2084 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2085 char buf
[INET6_ADDRSTRLEN
];
2087 vty_out(vty
, " ipv6 nd rdnss %s",
2088 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2089 if (rdnss
->lifetime_set
) {
2090 if (rdnss
->lifetime
== UINT32_MAX
)
2091 vty_out(vty
, " infinite");
2093 vty_out(vty
, " %u", rdnss
->lifetime
);
2097 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2098 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2099 if (dnssl
->lifetime_set
) {
2100 if (dnssl
->lifetime
== UINT32_MAX
)
2101 vty_out(vty
, " infinite");
2103 vty_out(vty
, " %u", dnssl
->lifetime
);
2111 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2113 struct rtadv
*rtadv
= &zvrf
->rtadv
;
2117 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2119 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2123 if (rtadv
->ra_timer
) {
2124 thread_cancel(rtadv
->ra_timer
);
2125 rtadv
->ra_timer
= NULL
;
2127 if (rtadv
->ra_read
) {
2128 thread_cancel(rtadv
->ra_read
);
2129 rtadv
->ra_read
= NULL
;
2133 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2136 case RTADV_TIMER_MSEC
:
2137 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2141 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2150 void rtadv_init(struct zebra_vrf
*zvrf
)
2152 if (vrf_is_backend_netns()) {
2153 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2154 zrouter
.rtadv_sock
= -1;
2155 } else if (!zrouter
.rtadv_sock
) {
2156 zvrf
->rtadv
.sock
= -1;
2157 if (!zrouter
.rtadv_sock
)
2158 zrouter
.rtadv_sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2162 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2164 rtadv_event(zvrf
, RTADV_STOP
, 0);
2165 if (zvrf
->rtadv
.sock
>= 0) {
2166 close(zvrf
->rtadv
.sock
);
2167 zvrf
->rtadv
.sock
= -1;
2168 } else if (zrouter
.rtadv_sock
>= 0) {
2169 close(zrouter
.rtadv_sock
);
2170 zrouter
.rtadv_sock
= -1;
2172 zvrf
->rtadv
.adv_if_count
= 0;
2173 zvrf
->rtadv
.adv_msec_if_count
= 0;
2176 void rtadv_cmd_init(void)
2178 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2179 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2181 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2182 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2183 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2184 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2185 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2186 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2187 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2188 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2189 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2190 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2191 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2192 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2193 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2194 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2195 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2196 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2197 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2198 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2199 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2200 install_element(INTERFACE_NODE
,
2201 &ipv6_nd_adv_interval_config_option_cmd
);
2202 install_element(INTERFACE_NODE
,
2203 &no_ipv6_nd_adv_interval_config_option_cmd
);
2204 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2205 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2206 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2207 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2208 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2209 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2210 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2211 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2212 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2213 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2216 static int if_join_all_router(int sock
, struct interface
*ifp
)
2220 struct ipv6_mreq mreq
;
2222 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2223 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2224 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2226 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2229 flog_err_sys(EC_LIB_SOCKET
,
2230 "%s(%u): Failed to join group, socket %u error %s",
2231 ifp
->name
, ifp
->ifindex
, sock
,
2232 safe_strerror(errno
));
2234 if (IS_ZEBRA_DEBUG_EVENT
)
2236 "%s(%u): Join All-Routers multicast group, socket %u",
2237 ifp
->name
, ifp
->ifindex
, sock
);
2242 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2246 struct ipv6_mreq mreq
;
2248 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2249 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2250 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2252 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2257 "%s(%u): Failed to leave group, socket %u error %s",
2258 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
2260 if (IS_ZEBRA_DEBUG_EVENT
)
2262 "%s(%u): Leave All-Routers multicast group, socket %u",
2263 ifp
->name
, ifp
->ifindex
, sock
);
2269 void rtadv_init(struct zebra_vrf
*zvrf
)
2273 void rtadv_terminate(struct zebra_vrf
*zvrf
)
2277 void rtadv_cmd_init(void)
2281 #endif /* HAVE_RTADV */