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_ns.h"
46 #include "zebra/zebra_vrf.h"
47 #include "zebra/zebra_errors.h"
48 #include "zebra/zebra_router.h"
50 extern struct zebra_privs_t zserv_privs
;
52 #if defined(HAVE_RTADV)
55 #include <netinet/icmp6.h>
58 /* If RFC2133 definition is used. */
59 #ifndef IPV6_JOIN_GROUP
60 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
62 #ifndef IPV6_LEAVE_GROUP
63 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
66 #define ALLNODE "ff02::1"
67 #define ALLROUTER "ff02::2"
69 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS")
70 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL")
72 /* Order is intentional. Matches RFC4191. This array is also used for
73 command matching, so only modify with care. */
74 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
84 static void rtadv_event(struct zebra_ns
*, enum rtadv_event
, int);
86 static int if_join_all_router(int, struct interface
*);
87 static int if_leave_all_router(int, struct interface
*);
89 static int rtadv_increment_received(struct zebra_ns
*zns
, ifindex_t
*ifindex
)
92 struct interface
*iface
;
95 iface
= if_lookup_by_index_per_ns(zns
, *ifindex
);
96 if (iface
&& iface
->info
) {
104 static int rtadv_recv_packet(struct zebra_ns
*zns
, int sock
, uint8_t *buf
,
105 int buflen
, struct sockaddr_in6
*from
,
106 ifindex_t
*ifindex
, int *hoplimit
)
111 struct cmsghdr
*cmsgptr
;
116 /* Fill in message and iovec. */
117 memset(&msg
, 0, sizeof(msg
));
118 msg
.msg_name
= (void *)from
;
119 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
122 msg
.msg_control
= (void *)adata
;
123 msg
.msg_controllen
= sizeof adata
;
125 iov
.iov_len
= buflen
;
127 /* If recvmsg fail return minus value. */
128 ret
= recvmsg(sock
, &msg
, 0);
132 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
133 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
134 /* I want interface index which this packet comes from. */
135 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
136 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
137 struct in6_pktinfo
*ptr
;
139 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
140 *ifindex
= ptr
->ipi6_ifindex
;
141 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
144 /* Incoming packet's hop limit. */
145 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
146 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
147 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
152 rtadv_increment_received(zns
, ifindex
);
156 #define RTADV_MSG_SIZE 4096
158 /* Send router advertisement packet. */
159 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
163 struct cmsghdr
*cmsgptr
;
164 struct in6_pktinfo
*pkt
;
165 struct sockaddr_in6 addr
;
166 static void *adata
= NULL
;
167 unsigned char buf
[RTADV_MSG_SIZE
];
168 struct nd_router_advert
*rtadv
;
171 struct zebra_if
*zif
;
172 struct rtadv_prefix
*rprefix
;
173 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
174 0, 0, 0, 0, 0, 0, 0, 1};
175 struct listnode
*node
;
176 uint16_t pkt_RouterLifetime
;
179 * Allocate control message bufffer. This is dynamic because
180 * CMSG_SPACE is not guaranteed not to call a function. Note that
181 * the size will be different on different architectures due to
182 * differing alignment rules.
185 /* XXX Free on shutdown. */
186 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
190 "rtadv_send_packet: can't malloc control data");
195 /* Logging of packet. */
196 if (IS_ZEBRA_DEBUG_PACKET
)
197 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
200 /* Fill in sockaddr_in6. */
201 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
202 addr
.sin6_family
= AF_INET6
;
204 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
205 #endif /* SIN6_LEN */
206 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
207 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
209 /* Fetch interface information. */
212 /* Make router advertisement message. */
213 rtadv
= (struct nd_router_advert
*)buf
;
215 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
216 rtadv
->nd_ra_code
= 0;
217 rtadv
->nd_ra_cksum
= 0;
219 rtadv
->nd_ra_curhoplimit
= 64;
221 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
222 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
224 : zif
->rtadv
.DefaultPreference
;
225 rtadv
->nd_ra_flags_reserved
<<= 3;
227 if (zif
->rtadv
.AdvManagedFlag
)
228 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
229 if (zif
->rtadv
.AdvOtherConfigFlag
)
230 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
231 if (zif
->rtadv
.AdvHomeAgentFlag
)
232 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
233 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
234 * AdvDefaultLifetime is by default based on the value of
235 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
236 * field of Router Advertisements. Given that this field is expressed
237 * in seconds, a small MaxRtrAdvInterval value can result in a zero
238 * value for this field. To prevent this, routers SHOULD keep
239 * AdvDefaultLifetime in at least one second, even if the use of
240 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
242 zif
->rtadv
.AdvDefaultLifetime
!= -1
243 ? zif
->rtadv
.AdvDefaultLifetime
244 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
245 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
246 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
247 rtadv
->nd_ra_retransmit
= htonl(0);
249 len
= sizeof(struct nd_router_advert
);
251 /* If both the Home Agent Preference and Home Agent Lifetime are set to
252 * their default values specified above, this option SHOULD NOT be
253 * included in the Router Advertisement messages sent by this home
254 * agent. -- RFC6275, 7.4 */
255 if (zif
->rtadv
.AdvHomeAgentFlag
256 && (zif
->rtadv
.HomeAgentPreference
257 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
258 struct nd_opt_homeagent_info
*ndopt_hai
=
259 (struct nd_opt_homeagent_info
*)(buf
+ len
);
260 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
261 ndopt_hai
->nd_opt_hai_len
= 1;
262 ndopt_hai
->nd_opt_hai_reserved
= 0;
263 ndopt_hai
->nd_opt_hai_preference
=
264 htons(zif
->rtadv
.HomeAgentPreference
);
265 /* 16-bit unsigned integer. The lifetime associated with the
267 * agent in units of seconds. The default value is the same as
269 * Router Lifetime, as specified in the main body of the Router
270 * Advertisement. The maximum value corresponds to 18.2 hours.
272 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
273 ndopt_hai
->nd_opt_hai_lifetime
=
274 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
275 ? zif
->rtadv
.HomeAgentLifetime
276 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
281 len
+= sizeof(struct nd_opt_homeagent_info
);
284 if (zif
->rtadv
.AdvIntervalOption
) {
285 struct nd_opt_adv_interval
*ndopt_adv
=
286 (struct nd_opt_adv_interval
*)(buf
+ len
);
287 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
288 ndopt_adv
->nd_opt_ai_len
= 1;
289 ndopt_adv
->nd_opt_ai_reserved
= 0;
290 ndopt_adv
->nd_opt_ai_interval
=
291 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
292 len
+= sizeof(struct nd_opt_adv_interval
);
295 /* Fill in prefix. */
296 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
297 struct nd_opt_prefix_info
*pinfo
;
299 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
301 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
302 pinfo
->nd_opt_pi_len
= 4;
303 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
305 pinfo
->nd_opt_pi_flags_reserved
= 0;
306 if (rprefix
->AdvOnLinkFlag
)
307 pinfo
->nd_opt_pi_flags_reserved
|=
308 ND_OPT_PI_FLAG_ONLINK
;
309 if (rprefix
->AdvAutonomousFlag
)
310 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
311 if (rprefix
->AdvRouterAddressFlag
)
312 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
314 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
315 pinfo
->nd_opt_pi_preferred_time
=
316 htonl(rprefix
->AdvPreferredLifetime
);
317 pinfo
->nd_opt_pi_reserved2
= 0;
319 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
320 &rprefix
->prefix
.prefix
);
324 uint8_t buf
[INET6_ADDRSTRLEN
];
326 zlog_debug("DEBUG %s",
327 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
328 buf
, INET6_ADDRSTRLEN
));
332 len
+= sizeof(struct nd_opt_prefix_info
);
335 /* Hardware address. */
336 if (ifp
->hw_addr_len
!= 0) {
337 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
339 /* Option length should be rounded up to next octet if
340 the link address does not end on an octet boundary. */
341 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
343 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
344 len
+= ifp
->hw_addr_len
;
346 /* Pad option to end on an octet boundary. */
347 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
348 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
352 if (zif
->rtadv
.AdvLinkMTU
) {
353 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
354 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
355 opt
->nd_opt_mtu_len
= 1;
356 opt
->nd_opt_mtu_reserved
= 0;
357 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
358 len
+= sizeof(struct nd_opt_mtu
);
362 * There is no limit on the number of configurable recursive DNS
363 * servers or search list entries. We don't want the RA message
364 * to exceed the link's MTU (risking fragmentation) or even
365 * blow the stack buffer allocated for it.
367 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
369 /* Recursive DNS servers */
370 struct rtadv_rdnss
*rdnss
;
372 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
374 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
376 if (len
+ opt_len
> max_len
) {
378 "%s(%u): Tx RA: RDNSS option would exceed MTU, omitting it",
379 ifp
->name
, ifp
->ifindex
);
382 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
384 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
385 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
386 opt
->nd_opt_rdnss_reserved
= 0;
387 opt
->nd_opt_rdnss_lifetime
= htonl(
390 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
392 len
+= sizeof(struct nd_opt_rdnss
);
394 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
395 len
+= sizeof(struct in6_addr
);
398 /* DNS search list */
399 struct rtadv_dnssl
*dnssl
;
401 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
402 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
403 + ((dnssl
->encoded_len
+ 7) & ~7);
405 if (len
+ opt_len
> max_len
) {
407 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
408 ifp
->name
, ifp
->ifindex
);
411 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
413 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
414 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
415 opt
->nd_opt_dnssl_reserved
= 0;
416 opt
->nd_opt_dnssl_lifetime
= htonl(
419 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
421 len
+= sizeof(struct nd_opt_dnssl
);
423 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
424 len
+= dnssl
->encoded_len
;
426 /* Zero-pad to 8-octet boundary */
433 msg
.msg_name
= (void *)&addr
;
434 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
437 msg
.msg_control
= (void *)adata
;
438 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
443 cmsgptr
= CMSG_FIRSTHDR(&msg
);
444 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
445 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
446 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
448 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
449 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
450 pkt
->ipi6_ifindex
= ifp
->ifindex
;
452 ret
= sendmsg(sock
, &msg
, 0);
454 flog_err_sys(EC_LIB_SOCKET
,
455 "%s(%u): Tx RA failed, socket %u error %d (%s)",
456 ifp
->name
, ifp
->ifindex
, sock
, errno
,
457 safe_strerror(errno
));
462 static int rtadv_timer(struct thread
*thread
)
464 struct zebra_ns
*zns
= THREAD_ARG(thread
);
466 struct interface
*ifp
;
467 struct zebra_if
*zif
;
470 zrouter
.rtadv
.ra_timer
= NULL
;
471 if (zrouter
.rtadv
.adv_msec_if_count
== 0) {
472 period
= 1000; /* 1 s */
473 rtadv_event(zns
, RTADV_TIMER
, 1 /* 1 s */);
475 period
= 10; /* 10 ms */
476 rtadv_event(zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
479 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
480 FOR_ALL_INTERFACES (vrf
, ifp
) {
481 if (if_is_loopback(ifp
)
482 || CHECK_FLAG(ifp
->status
,
483 ZEBRA_INTERFACE_VRF_LOOPBACK
)
484 || !if_is_operative(ifp
))
489 if (zif
->rtadv
.AdvSendAdvertisements
) {
490 if (zif
->rtadv
.inFastRexmit
) {
491 /* We assume we fast rexmit every sec so
494 if (--zif
->rtadv
.NumFastReXmitsRemain
496 zif
->rtadv
.inFastRexmit
= 0;
498 if (IS_ZEBRA_DEBUG_SEND
)
500 "Fast RA Rexmit on interface %s",
503 rtadv_send_packet(zrouter
.rtadv
.sock
,
506 zif
->rtadv
.AdvIntervalTimer
-= period
;
507 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
509 MaxRtrAdvInterval each
510 time isn't what section
511 6.2.4 of RFC4861 tells to do.
513 zif
->rtadv
.AdvIntervalTimer
=
527 static void rtadv_process_solicit(struct interface
*ifp
)
529 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
530 struct zebra_ns
*zns
= zvrf
->zns
;
533 rtadv_send_packet(zrouter
.rtadv
.sock
, ifp
);
537 * This function processes optional attributes off of
538 * end of a RA packet received. At this point in
539 * time we only care about this in one situation
540 * which is when a interface does not have a LL
541 * v6 address. We still need to be able to install
542 * the mac address for v4 to v6 resolution
544 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
545 struct interface
*ifp
,
546 struct sockaddr_in6
*addr
)
551 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
553 switch(opt_hdr
->nd_opt_type
) {
554 case ND_OPT_SOURCE_LINKADDR
:
555 mac
= (char *)(optional
+2);
556 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
557 &addr
->sin6_addr
, 1);
563 len
-= 8 * opt_hdr
->nd_opt_len
;
564 optional
+= 8 * opt_hdr
->nd_opt_len
;
568 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
569 struct interface
*ifp
,
570 struct sockaddr_in6
*addr
)
572 struct nd_router_advert
*radvert
;
573 char addr_str
[INET6_ADDRSTRLEN
];
574 struct zebra_if
*zif
;
579 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
581 if (len
< sizeof(struct nd_router_advert
)) {
582 if (IS_ZEBRA_DEBUG_PACKET
)
583 zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
584 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
588 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
589 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
590 len
- sizeof(struct nd_router_advert
),
592 if (IS_ZEBRA_DEBUG_PACKET
)
593 zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s",
594 ifp
->name
, ifp
->ifindex
, addr_str
);
598 radvert
= (struct nd_router_advert
*)msg
;
600 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
601 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
603 EC_ZEBRA_RA_PARAM_MISMATCH
,
604 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
605 ifp
->name
, ifp
->ifindex
, addr_str
);
608 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
609 && !zif
->rtadv
.AdvManagedFlag
) {
611 EC_ZEBRA_RA_PARAM_MISMATCH
,
612 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
613 ifp
->name
, ifp
->ifindex
, addr_str
);
616 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
617 && !zif
->rtadv
.AdvOtherConfigFlag
) {
619 EC_ZEBRA_RA_PARAM_MISMATCH
,
620 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
621 ifp
->name
, ifp
->ifindex
, addr_str
);
624 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
625 && (ntohl(radvert
->nd_ra_reachable
)
626 != zif
->rtadv
.AdvReachableTime
)) {
628 EC_ZEBRA_RA_PARAM_MISMATCH
,
629 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
630 ifp
->name
, ifp
->ifindex
, addr_str
);
633 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
634 && (ntohl(radvert
->nd_ra_retransmit
)
635 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
637 EC_ZEBRA_RA_PARAM_MISMATCH
,
638 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
639 ifp
->name
, ifp
->ifindex
, addr_str
);
642 /* Create entry for neighbor if not known. */
644 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
645 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
647 if (!nbr_connected_check(ifp
, &p
))
648 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
652 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
653 ifindex_t ifindex
, int hoplimit
,
654 struct sockaddr_in6
*from
,
655 struct zebra_ns
*zns
)
657 struct icmp6_hdr
*icmph
;
658 struct interface
*ifp
;
659 struct zebra_if
*zif
;
660 char addr_str
[INET6_ADDRSTRLEN
];
662 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
664 /* Interface search. */
665 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
667 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
668 "RA/RS received on unknown IF %u from %s", ifindex
,
673 if (IS_ZEBRA_DEBUG_PACKET
)
674 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
675 ifp
->ifindex
, len
, addr_str
);
677 if (if_is_loopback(ifp
)
678 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
681 /* Check interface configuration. */
683 if (!zif
->rtadv
.AdvSendAdvertisements
)
686 /* ICMP message length check. */
687 if (len
< sizeof(struct icmp6_hdr
)) {
688 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
689 ifp
->name
, ifp
->ifindex
, len
);
693 icmph
= (struct icmp6_hdr
*)buf
;
695 /* ICMP message type check. */
696 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
697 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
698 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
699 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
703 /* Hoplimit check. */
704 if (hoplimit
>= 0 && hoplimit
!= 255) {
705 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
706 ifp
->ifindex
, hoplimit
);
710 /* Check ICMP message type. */
711 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
712 rtadv_process_solicit(ifp
);
713 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
714 rtadv_process_advert(buf
, len
, ifp
, from
);
719 static int rtadv_read(struct thread
*thread
)
723 uint8_t buf
[RTADV_MSG_SIZE
];
724 struct sockaddr_in6 from
;
725 ifindex_t ifindex
= 0;
727 struct zebra_ns
*zns
= THREAD_ARG(thread
);
729 sock
= THREAD_FD(thread
);
730 zrouter
.rtadv
.ra_read
= NULL
;
732 /* Register myself. */
733 rtadv_event(zns
, RTADV_READ
, sock
);
735 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
739 flog_err_sys(EC_LIB_SOCKET
,
740 "RA/RS recv failed, socket %u error %s", sock
,
741 safe_strerror(errno
));
745 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
750 static int rtadv_make_socket(ns_id_t ns_id
)
754 struct icmp6_filter filter
;
756 frr_elevate_privs(&zserv_privs
) {
758 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
766 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
771 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
776 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
781 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
786 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
792 ICMP6_FILTER_SETBLOCKALL(&filter
);
793 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
794 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
796 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
797 sizeof(struct icmp6_filter
));
799 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
807 static struct rtadv_prefix
*rtadv_prefix_new(void)
809 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
812 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
814 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
817 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
818 struct prefix_ipv6
*p
)
820 struct listnode
*node
;
821 struct rtadv_prefix
*rprefix
;
823 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
824 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
830 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
831 struct prefix_ipv6
*p
)
833 struct rtadv_prefix
*rprefix
;
835 rprefix
= rtadv_prefix_lookup(rplist
, p
);
839 rprefix
= rtadv_prefix_new();
840 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
841 listnode_add(rplist
, rprefix
);
846 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
848 struct rtadv_prefix
*rprefix
;
850 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
852 /* Set parameters. */
853 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
854 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
855 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
856 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
857 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
860 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
862 struct rtadv_prefix
*rprefix
;
864 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
865 if (rprefix
!= NULL
) {
866 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
867 rtadv_prefix_free(rprefix
);
873 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
874 ipv6_nd_suppress_ra_status status
)
876 struct zebra_if
*zif
;
877 struct zebra_vrf
*zvrf
;
878 struct zebra_ns
*zns
;
881 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
884 if (status
== RA_SUPPRESS
) {
885 /* RA is currently enabled */
886 if (zif
->rtadv
.AdvSendAdvertisements
) {
887 zif
->rtadv
.AdvSendAdvertisements
= 0;
888 zif
->rtadv
.AdvIntervalTimer
= 0;
889 zrouter
.rtadv
.adv_if_count
--;
891 if_leave_all_router(zrouter
.rtadv
.sock
, ifp
);
893 if (zrouter
.rtadv
.adv_if_count
== 0)
894 rtadv_event(zns
, RTADV_STOP
, 0);
897 if (!zif
->rtadv
.AdvSendAdvertisements
) {
898 zif
->rtadv
.AdvSendAdvertisements
= 1;
899 zif
->rtadv
.AdvIntervalTimer
= 0;
900 zrouter
.rtadv
.adv_if_count
++;
902 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
903 /* Enable Fast RA only when RA interval is in
905 zif
->rtadv
.inFastRexmit
= 1;
906 zif
->rtadv
.NumFastReXmitsRemain
=
907 RTADV_NUM_FAST_REXMITS
;
910 if_join_all_router(zrouter
.rtadv
.sock
, ifp
);
912 if (zrouter
.rtadv
.adv_if_count
== 1)
913 rtadv_event(zns
, RTADV_START
,
920 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
921 * Note that while the client could request RA on an interface on which the
922 * operator has not enabled RA, RA won't be disabled upon client request
923 * if the operator has explicitly enabled RA. The enable request can also
924 * specify a RA interval (in seconds).
926 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
930 struct interface
*ifp
;
931 struct zebra_if
*zif
;
936 /* Get interface index and RA interval. */
937 STREAM_GETL(s
, ifindex
);
938 STREAM_GETL(s
, ra_interval
);
940 if (IS_ZEBRA_DEBUG_EVENT
)
941 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
942 zvrf_id(zvrf
), ifindex
,
943 enable
? "enable" : "disable",
944 zebra_route_string(client
->proto
), ra_interval
);
946 /* Locate interface and check VRF match. */
947 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
949 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
950 "%u: IF %u RA %s client %s - interface unknown",
951 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
952 zebra_route_string(client
->proto
));
955 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
957 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
958 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
959 zebra_route_string(client
->proto
), ifp
->vrf_id
);
965 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
966 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
968 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
969 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
970 VTY_RA_INTERVAL_CONFIGURED
))
971 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
973 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
974 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
975 VTY_RA_INTERVAL_CONFIGURED
))
976 zif
->rtadv
.MaxRtrAdvInterval
=
977 RTADV_MAX_RTR_ADV_INTERVAL
;
978 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
979 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
985 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
987 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
989 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
991 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
994 DEFUN (ipv6_nd_suppress_ra
,
995 ipv6_nd_suppress_ra_cmd
,
996 "ipv6 nd suppress-ra",
997 "Interface IPv6 config commands\n"
998 "Neighbor discovery\n"
999 "Suppress Router Advertisement\n")
1001 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1002 struct zebra_if
*zif
= ifp
->info
;
1004 if (if_is_loopback(ifp
)
1005 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1007 "Cannot configure IPv6 Router Advertisements on this interface\n");
1008 return CMD_WARNING_CONFIG_FAILED
;
1011 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1012 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1014 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1018 DEFUN (no_ipv6_nd_suppress_ra
,
1019 no_ipv6_nd_suppress_ra_cmd
,
1020 "no ipv6 nd suppress-ra",
1022 "Interface IPv6 config commands\n"
1023 "Neighbor discovery\n"
1024 "Suppress Router Advertisement\n")
1026 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1027 struct zebra_if
*zif
= ifp
->info
;
1029 if (if_is_loopback(ifp
)
1030 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1032 "Cannot configure IPv6 Router Advertisements on this interface\n");
1033 return CMD_WARNING_CONFIG_FAILED
;
1036 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1037 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1041 DEFUN (ipv6_nd_ra_interval_msec
,
1042 ipv6_nd_ra_interval_msec_cmd
,
1043 "ipv6 nd ra-interval msec (70-1800000)",
1044 "Interface IPv6 config commands\n"
1045 "Neighbor discovery\n"
1046 "Router Advertisement interval\n"
1047 "Router Advertisement interval in milliseconds\n"
1048 "Router Advertisement interval in milliseconds\n")
1051 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1053 struct zebra_if
*zif
= ifp
->info
;
1055 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1056 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1057 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1059 "This ra-interval would conflict with configured ra-lifetime!\n");
1060 return CMD_WARNING_CONFIG_FAILED
;
1063 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1064 zrouter
.rtadv
.adv_msec_if_count
--;
1066 if (interval
% 1000)
1067 zrouter
.rtadv
.adv_msec_if_count
++;
1069 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1070 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1071 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1072 zif
->rtadv
.AdvIntervalTimer
= 0;
1077 DEFUN (ipv6_nd_ra_interval
,
1078 ipv6_nd_ra_interval_cmd
,
1079 "ipv6 nd ra-interval (1-1800)",
1080 "Interface IPv6 config commands\n"
1081 "Neighbor discovery\n"
1082 "Router Advertisement interval\n"
1083 "Router Advertisement interval in seconds\n")
1086 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1088 struct zebra_if
*zif
= ifp
->info
;
1090 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1091 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1092 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1094 "This ra-interval would conflict with configured ra-lifetime!\n");
1095 return CMD_WARNING_CONFIG_FAILED
;
1098 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1099 zrouter
.rtadv
.adv_msec_if_count
--;
1101 /* convert to milliseconds */
1102 interval
= interval
* 1000;
1104 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1105 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1106 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1107 zif
->rtadv
.AdvIntervalTimer
= 0;
1112 DEFUN (no_ipv6_nd_ra_interval
,
1113 no_ipv6_nd_ra_interval_cmd
,
1114 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1116 "Interface IPv6 config commands\n"
1117 "Neighbor discovery\n"
1118 "Router Advertisement interval\n"
1119 "Router Advertisement interval in seconds\n"
1120 "Specify millisecond router advertisement interval\n"
1121 "Router Advertisement interval in milliseconds\n")
1123 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1124 struct zebra_if
*zif
= ifp
->info
;
1126 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1127 zrouter
.rtadv
.adv_msec_if_count
--;
1129 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1131 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1132 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1134 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1136 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1137 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1142 DEFUN (ipv6_nd_ra_lifetime
,
1143 ipv6_nd_ra_lifetime_cmd
,
1144 "ipv6 nd ra-lifetime (0-9000)",
1145 "Interface IPv6 config commands\n"
1146 "Neighbor discovery\n"
1148 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1151 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1152 struct zebra_if
*zif
= ifp
->info
;
1155 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1157 /* The value to be placed in the Router Lifetime field
1158 * of Router Advertisements sent from the interface,
1159 * in seconds. MUST be either zero or between
1160 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1161 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1163 "This ra-lifetime would conflict with configured ra-interval\n");
1164 return CMD_WARNING_CONFIG_FAILED
;
1167 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1172 DEFUN (no_ipv6_nd_ra_lifetime
,
1173 no_ipv6_nd_ra_lifetime_cmd
,
1174 "no ipv6 nd ra-lifetime [(0-9000)]",
1176 "Interface IPv6 config commands\n"
1177 "Neighbor discovery\n"
1179 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1181 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1182 struct zebra_if
*zif
= ifp
->info
;
1184 zif
->rtadv
.AdvDefaultLifetime
= -1;
1189 DEFUN (ipv6_nd_reachable_time
,
1190 ipv6_nd_reachable_time_cmd
,
1191 "ipv6 nd reachable-time (1-3600000)",
1192 "Interface IPv6 config commands\n"
1193 "Neighbor discovery\n"
1195 "Reachable time in milliseconds\n")
1198 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1199 struct zebra_if
*zif
= ifp
->info
;
1200 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1204 DEFUN (no_ipv6_nd_reachable_time
,
1205 no_ipv6_nd_reachable_time_cmd
,
1206 "no ipv6 nd reachable-time [(1-3600000)]",
1208 "Interface IPv6 config commands\n"
1209 "Neighbor discovery\n"
1211 "Reachable time in milliseconds\n")
1213 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1214 struct zebra_if
*zif
= ifp
->info
;
1216 zif
->rtadv
.AdvReachableTime
= 0;
1221 DEFUN (ipv6_nd_homeagent_preference
,
1222 ipv6_nd_homeagent_preference_cmd
,
1223 "ipv6 nd home-agent-preference (0-65535)",
1224 "Interface IPv6 config commands\n"
1225 "Neighbor discovery\n"
1226 "Home Agent preference\n"
1227 "preference value (default is 0, least preferred)\n")
1230 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1231 struct zebra_if
*zif
= ifp
->info
;
1232 zif
->rtadv
.HomeAgentPreference
=
1233 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1237 DEFUN (no_ipv6_nd_homeagent_preference
,
1238 no_ipv6_nd_homeagent_preference_cmd
,
1239 "no ipv6 nd home-agent-preference [(0-65535)]",
1241 "Interface IPv6 config commands\n"
1242 "Neighbor discovery\n"
1243 "Home Agent preference\n"
1244 "preference value (default is 0, least preferred)\n")
1246 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1247 struct zebra_if
*zif
= ifp
->info
;
1249 zif
->rtadv
.HomeAgentPreference
= 0;
1254 DEFUN (ipv6_nd_homeagent_lifetime
,
1255 ipv6_nd_homeagent_lifetime_cmd
,
1256 "ipv6 nd home-agent-lifetime (0-65520)",
1257 "Interface IPv6 config commands\n"
1258 "Neighbor discovery\n"
1259 "Home Agent lifetime\n"
1260 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1263 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1264 struct zebra_if
*zif
= ifp
->info
;
1265 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1269 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1270 no_ipv6_nd_homeagent_lifetime_cmd
,
1271 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1273 "Interface IPv6 config commands\n"
1274 "Neighbor discovery\n"
1275 "Home Agent lifetime\n"
1276 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1278 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1279 struct zebra_if
*zif
= ifp
->info
;
1281 zif
->rtadv
.HomeAgentLifetime
= -1;
1286 DEFUN (ipv6_nd_managed_config_flag
,
1287 ipv6_nd_managed_config_flag_cmd
,
1288 "ipv6 nd managed-config-flag",
1289 "Interface IPv6 config commands\n"
1290 "Neighbor discovery\n"
1291 "Managed address configuration flag\n")
1293 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1294 struct zebra_if
*zif
= ifp
->info
;
1296 zif
->rtadv
.AdvManagedFlag
= 1;
1301 DEFUN (no_ipv6_nd_managed_config_flag
,
1302 no_ipv6_nd_managed_config_flag_cmd
,
1303 "no ipv6 nd managed-config-flag",
1305 "Interface IPv6 config commands\n"
1306 "Neighbor discovery\n"
1307 "Managed address configuration flag\n")
1309 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1310 struct zebra_if
*zif
= ifp
->info
;
1312 zif
->rtadv
.AdvManagedFlag
= 0;
1317 DEFUN (ipv6_nd_homeagent_config_flag
,
1318 ipv6_nd_homeagent_config_flag_cmd
,
1319 "ipv6 nd home-agent-config-flag",
1320 "Interface IPv6 config commands\n"
1321 "Neighbor discovery\n"
1322 "Home Agent configuration flag\n")
1324 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1325 struct zebra_if
*zif
= ifp
->info
;
1327 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1332 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1333 no_ipv6_nd_homeagent_config_flag_cmd
,
1334 "no ipv6 nd home-agent-config-flag",
1336 "Interface IPv6 config commands\n"
1337 "Neighbor discovery\n"
1338 "Home Agent configuration flag\n")
1340 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1341 struct zebra_if
*zif
= ifp
->info
;
1343 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1348 DEFUN (ipv6_nd_adv_interval_config_option
,
1349 ipv6_nd_adv_interval_config_option_cmd
,
1350 "ipv6 nd adv-interval-option",
1351 "Interface IPv6 config commands\n"
1352 "Neighbor discovery\n"
1353 "Advertisement Interval Option\n")
1355 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1356 struct zebra_if
*zif
= ifp
->info
;
1358 zif
->rtadv
.AdvIntervalOption
= 1;
1363 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1364 no_ipv6_nd_adv_interval_config_option_cmd
,
1365 "no ipv6 nd adv-interval-option",
1367 "Interface IPv6 config commands\n"
1368 "Neighbor discovery\n"
1369 "Advertisement Interval Option\n")
1371 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1372 struct zebra_if
*zif
= ifp
->info
;
1374 zif
->rtadv
.AdvIntervalOption
= 0;
1379 DEFUN (ipv6_nd_other_config_flag
,
1380 ipv6_nd_other_config_flag_cmd
,
1381 "ipv6 nd other-config-flag",
1382 "Interface IPv6 config commands\n"
1383 "Neighbor discovery\n"
1384 "Other statefull configuration flag\n")
1386 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1387 struct zebra_if
*zif
= ifp
->info
;
1389 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1394 DEFUN (no_ipv6_nd_other_config_flag
,
1395 no_ipv6_nd_other_config_flag_cmd
,
1396 "no ipv6 nd other-config-flag",
1398 "Interface IPv6 config commands\n"
1399 "Neighbor discovery\n"
1400 "Other statefull configuration flag\n")
1402 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1403 struct zebra_if
*zif
= ifp
->info
;
1405 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1410 DEFUN (ipv6_nd_prefix
,
1412 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1413 "Interface IPv6 config commands\n"
1414 "Neighbor discovery\n"
1415 "Prefix information\n"
1417 "Valid lifetime in seconds\n"
1418 "Infinite valid lifetime\n"
1419 "Preferred lifetime in seconds\n"
1420 "Infinite preferred lifetime\n"
1421 "Set Router Address flag\n"
1422 "Do not use prefix for onlink determination\n"
1423 "Do not use prefix for autoconfiguration\n"
1424 "Do not use prefix for autoconfiguration\n"
1425 "Do not use prefix for onlink determination\n")
1428 char *prefix
= argv
[3]->arg
;
1429 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1430 || strmatch(argv
[4]->text
, "infinite"));
1431 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1433 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1435 char *lifetime
= NULL
, *preflifetime
= NULL
;
1436 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1438 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1440 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1445 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1447 offlink
= (argc
> idx_routeropts
+ 1
1448 || strmatch(argv
[idx_routeropts
]->text
,
1450 noautoconf
= (argc
> idx_routeropts
+ 1
1451 || strmatch(argv
[idx_routeropts
]->text
,
1457 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1458 struct zebra_if
*zebra_if
= ifp
->info
;
1460 struct rtadv_prefix rp
;
1462 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1464 vty_out(vty
, "Malformed IPv6 prefix\n");
1465 return CMD_WARNING_CONFIG_FAILED
;
1467 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1468 rp
.AdvOnLinkFlag
= !offlink
;
1469 rp
.AdvAutonomousFlag
= !noautoconf
;
1470 rp
.AdvRouterAddressFlag
= routeraddr
;
1471 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1472 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1475 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1477 : strtoll(lifetime
, NULL
, 10);
1478 rp
.AdvPreferredLifetime
=
1479 strmatch(preflifetime
, "infinite")
1481 : strtoll(preflifetime
, NULL
, 10);
1482 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1483 vty_out(vty
, "Invalid preferred lifetime\n");
1484 return CMD_WARNING_CONFIG_FAILED
;
1488 rtadv_prefix_set(zebra_if
, &rp
);
1493 DEFUN (no_ipv6_nd_prefix
,
1494 no_ipv6_nd_prefix_cmd
,
1495 "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]>]",
1497 "Interface IPv6 config commands\n"
1498 "Neighbor discovery\n"
1499 "Prefix information\n"
1501 "Valid lifetime in seconds\n"
1502 "Infinite valid lifetime\n"
1503 "Preferred lifetime in seconds\n"
1504 "Infinite preferred lifetime\n"
1505 "Set Router Address flag\n"
1506 "Do not use prefix for onlink determination\n"
1507 "Do not use prefix for autoconfiguration\n"
1508 "Do not use prefix for autoconfiguration\n"
1509 "Do not use prefix for onlink determination\n")
1511 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1512 struct zebra_if
*zebra_if
= ifp
->info
;
1514 struct rtadv_prefix rp
;
1515 char *prefix
= argv
[4]->arg
;
1517 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1519 vty_out(vty
, "Malformed IPv6 prefix\n");
1520 return CMD_WARNING_CONFIG_FAILED
;
1522 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1524 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1526 vty_out(vty
, "Non-existant IPv6 prefix\n");
1527 return CMD_WARNING_CONFIG_FAILED
;
1533 DEFUN (ipv6_nd_router_preference
,
1534 ipv6_nd_router_preference_cmd
,
1535 "ipv6 nd router-preference <high|medium|low>",
1536 "Interface IPv6 config commands\n"
1537 "Neighbor discovery\n"
1538 "Default router preference\n"
1539 "High default router preference\n"
1540 "Medium default router preference (default)\n"
1541 "Low default router preference\n")
1543 int idx_high_medium_low
= 3;
1544 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1545 struct zebra_if
*zif
= ifp
->info
;
1548 while (0 != rtadv_pref_strs
[i
]) {
1549 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1552 zif
->rtadv
.DefaultPreference
= i
;
1558 return CMD_ERR_NO_MATCH
;
1561 DEFUN (no_ipv6_nd_router_preference
,
1562 no_ipv6_nd_router_preference_cmd
,
1563 "no ipv6 nd router-preference [<high|medium|low>]",
1565 "Interface IPv6 config commands\n"
1566 "Neighbor discovery\n"
1567 "Default router preference\n"
1568 "High default router preference\n"
1569 "Medium default router preference (default)\n"
1570 "Low default router preference\n")
1572 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1573 struct zebra_if
*zif
= ifp
->info
;
1575 zif
->rtadv
.DefaultPreference
=
1576 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1583 "ipv6 nd mtu (1-65535)",
1584 "Interface IPv6 config commands\n"
1585 "Neighbor discovery\n"
1590 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1591 struct zebra_if
*zif
= ifp
->info
;
1592 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1596 DEFUN (no_ipv6_nd_mtu
,
1598 "no ipv6 nd mtu [(1-65535)]",
1600 "Interface IPv6 config commands\n"
1601 "Neighbor discovery\n"
1605 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1606 struct zebra_if
*zif
= ifp
->info
;
1607 zif
->rtadv
.AdvLinkMTU
= 0;
1611 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
1613 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
1616 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
1618 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
1621 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
1622 struct rtadv_rdnss
*rdnss
)
1624 struct listnode
*node
;
1625 struct rtadv_rdnss
*p
;
1627 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1628 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
1633 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
1634 struct rtadv_rdnss
*rdnss
)
1636 struct rtadv_rdnss
*p
;
1638 p
= rtadv_rdnss_lookup(list
, rdnss
);
1642 p
= rtadv_rdnss_new();
1643 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
1644 listnode_add(list
, p
);
1649 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1651 struct rtadv_rdnss
*p
;
1653 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1654 p
->lifetime
= rdnss
->lifetime
;
1655 p
->lifetime_set
= rdnss
->lifetime_set
;
1658 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1660 struct rtadv_rdnss
*p
;
1662 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
1664 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
1665 rtadv_rdnss_free(p
);
1672 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
1674 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
1677 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
1679 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
1682 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
1683 struct rtadv_dnssl
*dnssl
)
1685 struct listnode
*node
;
1686 struct rtadv_dnssl
*p
;
1688 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1689 if (!strcasecmp(p
->name
, dnssl
->name
))
1694 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
1695 struct rtadv_dnssl
*dnssl
)
1697 struct rtadv_dnssl
*p
;
1699 p
= rtadv_dnssl_lookup(list
, dnssl
);
1703 p
= rtadv_dnssl_new();
1704 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1705 listnode_add(list
, p
);
1710 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1712 struct rtadv_dnssl
*p
;
1714 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1715 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
1718 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
1720 struct rtadv_dnssl
*p
;
1722 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
1724 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
1725 rtadv_dnssl_free(p
);
1733 * Convert dotted domain name (with or without trailing root zone dot) to
1734 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
1735 * to strlen(in) + 2 octets to out.
1737 * Returns the number of octets written to out or -1 if in does not constitute
1738 * a valid domain name.
1740 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
1742 const char *label_start
, *label_end
;
1748 while (*label_start
) {
1751 label_end
= strchr(label_start
, '.');
1752 if (label_end
== NULL
)
1753 label_end
= label_start
+ strlen(label_start
);
1755 label_len
= label_end
- label_start
;
1756 if (label_len
>= 64)
1757 return -1; /* labels must be 63 octets or less */
1759 out
[outp
++] = (uint8_t)label_len
;
1760 memcpy(out
+ outp
, label_start
, label_len
);
1762 label_start
+= label_len
;
1763 if (*label_start
== '.')
1771 DEFUN(ipv6_nd_rdnss
,
1773 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1774 "Interface IPv6 config commands\n"
1775 "Neighbor discovery\n"
1776 "Recursive DNS server information\n"
1778 "Valid lifetime in seconds\n"
1779 "Infinite valid lifetime\n")
1781 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1782 struct zebra_if
*zif
= ifp
->info
;
1783 struct rtadv_rdnss rdnss
= {};
1785 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
1786 vty_out(vty
, "Malformed IPv6 address\n");
1787 return CMD_WARNING_CONFIG_FAILED
;
1790 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1792 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
1794 : strtoll(lifetime
, NULL
, 10);
1795 rdnss
.lifetime_set
= 1;
1798 rtadv_rdnss_set(zif
, &rdnss
);
1803 DEFUN(no_ipv6_nd_rdnss
,
1804 no_ipv6_nd_rdnss_cmd
,
1805 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1807 "Interface IPv6 config commands\n"
1808 "Neighbor discovery\n"
1809 "Recursive DNS server information\n"
1811 "Valid lifetime in seconds\n"
1812 "Infinite valid lifetime\n")
1814 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1815 struct zebra_if
*zif
= ifp
->info
;
1816 struct rtadv_rdnss rdnss
= {};
1818 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
1819 vty_out(vty
, "Malformed IPv6 address\n");
1820 return CMD_WARNING_CONFIG_FAILED
;
1822 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
1823 vty_out(vty
, "Non-existant RDNSS address\n");
1824 return CMD_WARNING_CONFIG_FAILED
;
1830 DEFUN(ipv6_nd_dnssl
,
1832 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1833 "Interface IPv6 config commands\n"
1834 "Neighbor discovery\n"
1835 "DNS search list information\n"
1836 "Domain name suffix\n"
1837 "Valid lifetime in seconds\n"
1838 "Infinite valid lifetime\n")
1840 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1841 struct zebra_if
*zif
= ifp
->info
;
1842 struct rtadv_dnssl dnssl
= {};
1846 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
1847 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1848 vty_out(vty
, "Malformed DNS search domain\n");
1849 return CMD_WARNING_CONFIG_FAILED
;
1851 if (dnssl
.name
[len
- 1] == '.') {
1853 * Allow, but don't require, a trailing dot signifying the root
1854 * zone. Canonicalize by cutting it off if present.
1856 dnssl
.name
[len
- 1] = '\0';
1860 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1862 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
1864 : strtoll(lifetime
, NULL
, 10);
1865 dnssl
.lifetime_set
= 1;
1868 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
1870 vty_out(vty
, "Malformed DNS search domain\n");
1871 return CMD_WARNING_CONFIG_FAILED
;
1873 dnssl
.encoded_len
= ret
;
1874 rtadv_dnssl_set(zif
, &dnssl
);
1879 DEFUN(no_ipv6_nd_dnssl
,
1880 no_ipv6_nd_dnssl_cmd
,
1881 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1883 "Interface IPv6 config commands\n"
1884 "Neighbor discovery\n"
1885 "DNS search list information\n"
1886 "Domain name suffix\n"
1887 "Valid lifetime in seconds\n"
1888 "Infinite valid lifetime\n")
1890 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1891 struct zebra_if
*zif
= ifp
->info
;
1892 struct rtadv_dnssl dnssl
= {};
1895 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
1896 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
1897 vty_out(vty
, "Malformed DNS search domain\n");
1898 return CMD_WARNING_CONFIG_FAILED
;
1900 if (dnssl
.name
[len
- 1] == '.') {
1901 dnssl
.name
[len
- 1] = '\0';
1904 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
1905 vty_out(vty
, "Non-existant DNS search domain\n");
1906 return CMD_WARNING_CONFIG_FAILED
;
1913 /* Dump interface ND information to vty. */
1914 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1916 struct zebra_if
*zif
;
1917 struct rtadvconf
*rtadv
;
1920 zif
= (struct zebra_if
*)ifp
->info
;
1921 rtadv
= &zif
->rtadv
;
1923 if (rtadv
->AdvSendAdvertisements
) {
1925 " ND advertised reachable time is %d milliseconds\n",
1926 rtadv
->AdvReachableTime
);
1928 " ND advertised retransmit interval is %d milliseconds\n",
1929 rtadv
->AdvRetransTimer
);
1930 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1931 zif
->ra_sent
, zif
->ra_rcvd
);
1932 interval
= rtadv
->MaxRtrAdvInterval
;
1933 if (interval
% 1000)
1935 " ND router advertisements are sent every "
1936 "%d milliseconds\n",
1940 " ND router advertisements are sent every "
1943 if (rtadv
->AdvDefaultLifetime
!= -1)
1945 " ND router advertisements live for %d seconds\n",
1946 rtadv
->AdvDefaultLifetime
);
1949 " ND router advertisements lifetime tracks ra-interval\n");
1951 " ND router advertisement default router preference is "
1953 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1954 if (rtadv
->AdvManagedFlag
)
1956 " Hosts use DHCP to obtain routable addresses.\n");
1959 " Hosts use stateless autoconfig for addresses.\n");
1960 if (rtadv
->AdvHomeAgentFlag
) {
1962 " ND router advertisements with Home Agent flag bit set.\n");
1963 if (rtadv
->HomeAgentLifetime
!= -1)
1965 " Home Agent lifetime is %u seconds\n",
1966 rtadv
->HomeAgentLifetime
);
1969 " Home Agent lifetime tracks ra-lifetime\n");
1970 vty_out(vty
, " Home Agent preference is %u\n",
1971 rtadv
->HomeAgentPreference
);
1973 if (rtadv
->AdvIntervalOption
)
1975 " ND router advertisements with Adv. Interval option.\n");
1981 /* Write configuration about router advertisement. */
1982 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1984 struct zebra_if
*zif
;
1985 struct listnode
*node
;
1986 struct rtadv_prefix
*rprefix
;
1987 struct rtadv_rdnss
*rdnss
;
1988 struct rtadv_dnssl
*dnssl
;
1989 char buf
[PREFIX_STRLEN
];
1994 if (!(if_is_loopback(ifp
)
1995 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1996 if (zif
->rtadv
.AdvSendAdvertisements
1997 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1998 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2001 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2002 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2003 if (interval
% 1000)
2004 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2006 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2007 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2011 if (zif
->rtadv
.AdvIntervalOption
)
2012 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2014 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2015 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2016 zif
->rtadv
.AdvDefaultLifetime
);
2018 if (zif
->rtadv
.HomeAgentPreference
)
2019 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2020 zif
->rtadv
.HomeAgentPreference
);
2022 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2023 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2024 zif
->rtadv
.HomeAgentLifetime
);
2026 if (zif
->rtadv
.AdvHomeAgentFlag
)
2027 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2029 if (zif
->rtadv
.AdvReachableTime
)
2030 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2031 zif
->rtadv
.AdvReachableTime
);
2033 if (zif
->rtadv
.AdvManagedFlag
)
2034 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2036 if (zif
->rtadv
.AdvOtherConfigFlag
)
2037 vty_out(vty
, " ipv6 nd other-config-flag\n");
2039 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2040 vty_out(vty
, " ipv6 nd router-preference %s\n",
2041 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2043 if (zif
->rtadv
.AdvLinkMTU
)
2044 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2046 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
2047 vty_out(vty
, " ipv6 nd prefix %s",
2048 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
2049 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2050 || (rprefix
->AdvPreferredLifetime
2051 != RTADV_PREFERRED_LIFETIME
)) {
2052 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2053 vty_out(vty
, " infinite");
2055 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
2056 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2057 vty_out(vty
, " infinite");
2060 rprefix
->AdvPreferredLifetime
);
2062 if (!rprefix
->AdvOnLinkFlag
)
2063 vty_out(vty
, " off-link");
2064 if (!rprefix
->AdvAutonomousFlag
)
2065 vty_out(vty
, " no-autoconfig");
2066 if (rprefix
->AdvRouterAddressFlag
)
2067 vty_out(vty
, " router-address");
2070 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2071 char buf
[INET6_ADDRSTRLEN
];
2073 vty_out(vty
, " ipv6 nd rdnss %s",
2074 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2075 if (rdnss
->lifetime_set
) {
2076 if (rdnss
->lifetime
== UINT32_MAX
)
2077 vty_out(vty
, " infinite");
2079 vty_out(vty
, " %u", rdnss
->lifetime
);
2083 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2084 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2085 if (dnssl
->lifetime_set
) {
2086 if (dnssl
->lifetime
== UINT32_MAX
)
2087 vty_out(vty
, " infinite");
2089 vty_out(vty
, " %u", dnssl
->lifetime
);
2097 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
2099 struct rtadv
*rtadv
= &zrouter
.rtadv
;
2103 thread_add_read(zrouter
.master
, rtadv_read
, zns
, val
,
2105 thread_add_event(zrouter
.master
, rtadv_timer
, zns
, 0,
2109 if (rtadv
->ra_timer
) {
2110 thread_cancel(rtadv
->ra_timer
);
2111 rtadv
->ra_timer
= NULL
;
2113 if (rtadv
->ra_read
) {
2114 thread_cancel(rtadv
->ra_read
);
2115 rtadv
->ra_read
= NULL
;
2119 thread_add_timer(zrouter
.master
, rtadv_timer
, zns
, val
,
2122 case RTADV_TIMER_MSEC
:
2123 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zns
, val
,
2127 thread_add_read(zrouter
.master
, rtadv_read
, zns
, val
,
2136 void rtadv_init(struct zebra_ns
*zns
)
2138 zrouter
.rtadv
.sock
= rtadv_make_socket(zns
->ns_id
);
2141 void rtadv_terminate(struct zebra_ns
*zns
)
2143 rtadv_event(zns
, RTADV_STOP
, 0);
2144 if (zrouter
.rtadv
.sock
>= 0) {
2145 close(zrouter
.rtadv
.sock
);
2146 zrouter
.rtadv
.sock
= -1;
2149 zrouter
.rtadv
.adv_if_count
= 0;
2150 zrouter
.rtadv
.adv_msec_if_count
= 0;
2153 void rtadv_cmd_init(void)
2155 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2156 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2158 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2159 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2160 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2161 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2162 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2163 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2164 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2165 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2166 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2167 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2168 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2169 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2170 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2171 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2172 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2173 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2174 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2175 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2176 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2177 install_element(INTERFACE_NODE
,
2178 &ipv6_nd_adv_interval_config_option_cmd
);
2179 install_element(INTERFACE_NODE
,
2180 &no_ipv6_nd_adv_interval_config_option_cmd
);
2181 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2182 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2183 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2184 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2185 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2186 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2187 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2188 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2189 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2190 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2193 static int if_join_all_router(int sock
, struct interface
*ifp
)
2197 struct ipv6_mreq mreq
;
2199 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2200 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2201 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2203 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2206 flog_err_sys(EC_LIB_SOCKET
,
2207 "%s(%u): Failed to join group, socket %u error %s",
2208 ifp
->name
, ifp
->ifindex
, sock
,
2209 safe_strerror(errno
));
2211 if (IS_ZEBRA_DEBUG_EVENT
)
2213 "%s(%u): Join All-Routers multicast group, socket %u",
2214 ifp
->name
, ifp
->ifindex
, sock
);
2219 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2223 struct ipv6_mreq mreq
;
2225 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2226 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2227 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2229 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2234 "%s(%u): Failed to leave group, socket %u error %s",
2235 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
2237 if (IS_ZEBRA_DEBUG_EVENT
)
2239 "%s(%u): Leave All-Routers multicast group, socket %u",
2240 ifp
->name
, ifp
->ifindex
, sock
);
2246 void rtadv_init(struct zebra_ns
*zns
)
2250 void rtadv_terminate(struct zebra_ns
*zns
)
2254 void rtadv_cmd_init(void)
2258 #endif /* HAVE_RTADV */