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 #ifndef VTYSH_EXTRACT_PL
54 #include "zebra/rtadv_clippy.c"
57 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_PREFIX
, "Router Advertisement Prefix")
60 #include <netinet/icmp6.h>
63 /* If RFC2133 definition is used. */
64 #ifndef IPV6_JOIN_GROUP
65 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
67 #ifndef IPV6_LEAVE_GROUP
68 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
71 #define ALLNODE "ff02::1"
72 #define ALLROUTER "ff02::2"
74 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_RDNSS
, "Router Advertisement RDNSS")
75 DEFINE_MTYPE_STATIC(ZEBRA
, RTADV_DNSSL
, "Router Advertisement DNSSL")
77 /* Order is intentional. Matches RFC4191. This array is also used for
78 command matching, so only modify with care. */
79 static const char *const rtadv_pref_strs
[] = {
80 "medium", "high", "INVALID", "low", 0
91 static void rtadv_event(struct zebra_vrf
*, enum rtadv_event
, int);
93 static int if_join_all_router(int, struct interface
*);
94 static int if_leave_all_router(int, struct interface
*);
96 static int rtadv_get_socket(struct zebra_vrf
*zvrf
)
98 if (zvrf
->rtadv
.sock
> 0)
99 return zvrf
->rtadv
.sock
;
100 return zrouter
.rtadv_sock
;
103 static int rtadv_increment_received(struct zebra_vrf
*zvrf
, ifindex_t
*ifindex
)
106 struct interface
*iface
;
107 struct zebra_if
*zif
;
109 iface
= if_lookup_by_index(*ifindex
, zvrf
->vrf
->vrf_id
);
110 if (iface
&& iface
->info
) {
118 static int rtadv_recv_packet(struct zebra_vrf
*zvrf
, int sock
, uint8_t *buf
,
119 int buflen
, struct sockaddr_in6
*from
,
120 ifindex_t
*ifindex
, int *hoplimit
)
125 struct cmsghdr
*cmsgptr
;
130 /* Fill in message and iovec. */
131 memset(&msg
, 0, sizeof(msg
));
132 msg
.msg_name
= (void *)from
;
133 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
136 msg
.msg_control
= (void *)adata
;
137 msg
.msg_controllen
= sizeof(adata
);
139 iov
.iov_len
= buflen
;
141 /* If recvmsg fail return minus value. */
142 ret
= recvmsg(sock
, &msg
, 0);
146 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
147 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
148 /* I want interface index which this packet comes from. */
149 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
150 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
151 struct in6_pktinfo
*ptr
;
153 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
154 *ifindex
= ptr
->ipi6_ifindex
;
155 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
158 /* Incoming packet's hop limit. */
159 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
160 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
161 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
166 rtadv_increment_received(zvrf
, ifindex
);
170 #define RTADV_MSG_SIZE 4096
172 /* Send router advertisement packet. */
173 static void rtadv_send_packet(int sock
, struct interface
*ifp
,
174 enum ipv6_nd_suppress_ra_status stop
)
178 struct cmsghdr
*cmsgptr
;
179 struct in6_pktinfo
*pkt
;
180 struct sockaddr_in6 addr
;
181 static void *adata
= NULL
;
182 unsigned char buf
[RTADV_MSG_SIZE
];
183 struct nd_router_advert
*rtadv
;
186 struct zebra_if
*zif
;
187 struct rtadv_prefix
*rprefix
;
188 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0, 0, 0, 1};
190 struct listnode
*node
;
191 uint16_t pkt_RouterLifetime
;
194 * Allocate control message bufffer. This is dynamic because
195 * CMSG_SPACE is not guaranteed not to call a function. Note that
196 * the size will be different on different architectures due to
197 * differing alignment rules.
200 /* XXX Free on shutdown. */
201 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
205 "rtadv_send_packet: can't malloc control data");
210 /* Logging of packet. */
211 if (IS_ZEBRA_DEBUG_PACKET
) {
212 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
214 zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp
->name
,
215 VRF_LOGNAME(vrf
), ifp
->ifindex
, sock
);
218 /* Fill in sockaddr_in6. */
219 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
220 addr
.sin6_family
= AF_INET6
;
222 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
223 #endif /* SIN6_LEN */
224 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
225 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
227 /* Fetch interface information. */
230 /* Make router advertisement message. */
231 rtadv
= (struct nd_router_advert
*)buf
;
233 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
234 rtadv
->nd_ra_code
= 0;
235 rtadv
->nd_ra_cksum
= 0;
237 rtadv
->nd_ra_curhoplimit
= zif
->rtadv
.AdvCurHopLimit
;
239 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
240 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
242 : zif
->rtadv
.DefaultPreference
;
243 rtadv
->nd_ra_flags_reserved
<<= 3;
245 if (zif
->rtadv
.AdvManagedFlag
)
246 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
247 if (zif
->rtadv
.AdvOtherConfigFlag
)
248 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
249 if (zif
->rtadv
.AdvHomeAgentFlag
)
250 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
251 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
252 * AdvDefaultLifetime is by default based on the value of
253 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
254 * field of Router Advertisements. Given that this field is expressed
255 * in seconds, a small MaxRtrAdvInterval value can result in a zero
256 * value for this field. To prevent this, routers SHOULD keep
257 * AdvDefaultLifetime in at least one second, even if the use of
258 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
260 zif
->rtadv
.AdvDefaultLifetime
!= -1
261 ? zif
->rtadv
.AdvDefaultLifetime
262 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
264 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
265 rtadv
->nd_ra_router_lifetime
=
266 (stop
== RA_SUPPRESS
) ? htons(0) : htons(pkt_RouterLifetime
);
267 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
268 rtadv
->nd_ra_retransmit
= htonl(zif
->rtadv
.AdvRetransTimer
);
270 len
= sizeof(struct nd_router_advert
);
272 /* If both the Home Agent Preference and Home Agent Lifetime are set to
273 * their default values specified above, this option SHOULD NOT be
274 * included in the Router Advertisement messages sent by this home
275 * agent. -- RFC6275, 7.4 */
276 if (zif
->rtadv
.AdvHomeAgentFlag
277 && (zif
->rtadv
.HomeAgentPreference
278 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
279 struct nd_opt_homeagent_info
*ndopt_hai
=
280 (struct nd_opt_homeagent_info
*)(buf
+ len
);
281 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
282 ndopt_hai
->nd_opt_hai_len
= 1;
283 ndopt_hai
->nd_opt_hai_reserved
= 0;
284 ndopt_hai
->nd_opt_hai_preference
=
285 htons(zif
->rtadv
.HomeAgentPreference
);
286 /* 16-bit unsigned integer. The lifetime associated with the
288 * agent in units of seconds. The default value is the same as
290 * Router Lifetime, as specified in the main body of the Router
291 * Advertisement. The maximum value corresponds to 18.2 hours.
293 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
294 ndopt_hai
->nd_opt_hai_lifetime
=
295 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
296 ? zif
->rtadv
.HomeAgentLifetime
297 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
302 len
+= sizeof(struct nd_opt_homeagent_info
);
305 if (zif
->rtadv
.AdvIntervalOption
) {
306 struct nd_opt_adv_interval
*ndopt_adv
=
307 (struct nd_opt_adv_interval
*)(buf
+ len
);
308 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
309 ndopt_adv
->nd_opt_ai_len
= 1;
310 ndopt_adv
->nd_opt_ai_reserved
= 0;
311 ndopt_adv
->nd_opt_ai_interval
=
312 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
313 len
+= sizeof(struct nd_opt_adv_interval
);
316 /* Fill in prefix. */
317 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
318 struct nd_opt_prefix_info
*pinfo
;
320 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
322 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
323 pinfo
->nd_opt_pi_len
= 4;
324 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
326 pinfo
->nd_opt_pi_flags_reserved
= 0;
327 if (rprefix
->AdvOnLinkFlag
)
328 pinfo
->nd_opt_pi_flags_reserved
|=
329 ND_OPT_PI_FLAG_ONLINK
;
330 if (rprefix
->AdvAutonomousFlag
)
331 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
332 if (rprefix
->AdvRouterAddressFlag
)
333 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
335 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
336 pinfo
->nd_opt_pi_preferred_time
=
337 htonl(rprefix
->AdvPreferredLifetime
);
338 pinfo
->nd_opt_pi_reserved2
= 0;
340 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
341 &rprefix
->prefix
.prefix
);
343 len
+= sizeof(struct nd_opt_prefix_info
);
346 /* Hardware address. */
347 if (ifp
->hw_addr_len
!= 0) {
348 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
350 /* Option length should be rounded up to next octet if
351 the link address does not end on an octet boundary. */
352 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
354 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
355 len
+= ifp
->hw_addr_len
;
357 /* Pad option to end on an octet boundary. */
358 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
359 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
363 if (zif
->rtadv
.AdvLinkMTU
) {
364 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
365 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
366 opt
->nd_opt_mtu_len
= 1;
367 opt
->nd_opt_mtu_reserved
= 0;
368 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
369 len
+= sizeof(struct nd_opt_mtu
);
373 * There is no limit on the number of configurable recursive DNS
374 * servers or search list entries. We don't want the RA message
375 * to exceed the link's MTU (risking fragmentation) or even
376 * blow the stack buffer allocated for it.
378 size_t max_len
= MIN(ifp
->mtu6
- 40, sizeof(buf
));
380 /* Recursive DNS servers */
381 struct rtadv_rdnss
*rdnss
;
383 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
385 sizeof(struct nd_opt_rdnss
) + sizeof(struct in6_addr
);
387 if (len
+ opt_len
> max_len
) {
388 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
391 "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
392 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
);
395 struct nd_opt_rdnss
*opt
= (struct nd_opt_rdnss
*)(buf
+ len
);
397 opt
->nd_opt_rdnss_type
= ND_OPT_RDNSS
;
398 opt
->nd_opt_rdnss_len
= opt_len
/ 8;
399 opt
->nd_opt_rdnss_reserved
= 0;
400 opt
->nd_opt_rdnss_lifetime
= htonl(
403 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
405 len
+= sizeof(struct nd_opt_rdnss
);
407 IPV6_ADDR_COPY(buf
+ len
, &rdnss
->addr
);
408 len
+= sizeof(struct in6_addr
);
411 /* DNS search list */
412 struct rtadv_dnssl
*dnssl
;
414 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
415 size_t opt_len
= sizeof(struct nd_opt_dnssl
)
416 + ((dnssl
->encoded_len
+ 7) & ~7);
418 if (len
+ opt_len
> max_len
) {
420 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
421 ifp
->name
, ifp
->ifindex
);
424 struct nd_opt_dnssl
*opt
= (struct nd_opt_dnssl
*)(buf
+ len
);
426 opt
->nd_opt_dnssl_type
= ND_OPT_DNSSL
;
427 opt
->nd_opt_dnssl_len
= opt_len
/ 8;
428 opt
->nd_opt_dnssl_reserved
= 0;
429 opt
->nd_opt_dnssl_lifetime
= htonl(
432 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
));
434 len
+= sizeof(struct nd_opt_dnssl
);
436 memcpy(buf
+ len
, dnssl
->encoded_name
, dnssl
->encoded_len
);
437 len
+= dnssl
->encoded_len
;
439 /* Zero-pad to 8-octet boundary */
446 msg
.msg_name
= (void *)&addr
;
447 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
450 msg
.msg_control
= (void *)adata
;
451 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
456 cmsgptr
= CMSG_FIRSTHDR(&msg
);
457 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
458 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
459 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
461 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
462 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
463 pkt
->ipi6_ifindex
= ifp
->ifindex
;
465 ret
= sendmsg(sock
, &msg
, 0);
467 flog_err_sys(EC_LIB_SOCKET
,
468 "%s(%u): Tx RA failed, socket %u error %d (%s)",
469 ifp
->name
, ifp
->ifindex
, sock
, errno
,
470 safe_strerror(errno
));
475 static int rtadv_timer(struct thread
*thread
)
477 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
479 struct interface
*ifp
;
480 struct zebra_if
*zif
;
483 zvrf
->rtadv
.ra_timer
= NULL
;
484 if (zvrf
->rtadv
.adv_msec_if_count
== 0) {
485 period
= 1000; /* 1 s */
486 rtadv_event(zvrf
, RTADV_TIMER
, 1 /* 1 s */);
488 period
= 10; /* 10 ms */
489 rtadv_event(zvrf
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
492 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
493 FOR_ALL_INTERFACES (vrf
, ifp
) {
494 if (if_is_loopback(ifp
)
495 || CHECK_FLAG(ifp
->status
,
496 ZEBRA_INTERFACE_VRF_LOOPBACK
)
497 || !if_is_operative(ifp
))
502 if (zif
->rtadv
.AdvSendAdvertisements
) {
503 if (zif
->rtadv
.inFastRexmit
504 && zif
->rtadv
.UseFastRexmit
) {
505 /* We assume we fast rexmit every sec so
508 if (--zif
->rtadv
.NumFastReXmitsRemain
510 zif
->rtadv
.inFastRexmit
= 0;
512 if (IS_ZEBRA_DEBUG_SEND
) {
518 "Fast RA Rexmit on interface %s(%s:%u)",
524 rtadv_send_packet(rtadv_get_socket(zvrf
),
527 zif
->rtadv
.AdvIntervalTimer
-= period
;
528 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
530 MaxRtrAdvInterval each
531 time isn't what section
532 6.2.4 of RFC4861 tells to do.
534 zif
->rtadv
.AdvIntervalTimer
=
538 rtadv_get_socket(zvrf
),
548 static void rtadv_process_solicit(struct interface
*ifp
)
550 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
551 struct zebra_if
*zif
;
557 * If FastRetransmit is enabled, send the RA immediately.
558 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
559 * (3 seconds) since the last RA was sent, send it now and reset
560 * the timer to start at the max (configured) again.
561 * If not enabled and it is less than 3 seconds since the last
562 * RA packet was sent, set the timer for 3 seconds so the next
563 * one will be sent with a minimum of 3 seconds between RAs.
566 if ((zif
->rtadv
.UseFastRexmit
)
567 || (zif
->rtadv
.AdvIntervalTimer
<=
568 (zif
->rtadv
.MaxRtrAdvInterval
- MIN_DELAY_BETWEEN_RAS
))) {
569 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
, RA_ENABLE
);
570 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
572 zif
->rtadv
.AdvIntervalTimer
= MIN_DELAY_BETWEEN_RAS
;
576 * This function processes optional attributes off of
577 * end of a RA packet received. At this point in
578 * time we only care about this in one situation
579 * which is when a interface does not have a LL
580 * v6 address. We still need to be able to install
581 * the mac address for v4 to v6 resolution
583 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
584 struct interface
*ifp
,
585 struct sockaddr_in6
*addr
)
590 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
592 switch(opt_hdr
->nd_opt_type
) {
593 case ND_OPT_SOURCE_LINKADDR
:
594 mac
= (char *)(optional
+2);
595 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
596 &addr
->sin6_addr
, 1);
602 len
-= 8 * opt_hdr
->nd_opt_len
;
603 optional
+= 8 * opt_hdr
->nd_opt_len
;
607 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
608 struct interface
*ifp
,
609 struct sockaddr_in6
*addr
)
611 struct nd_router_advert
*radvert
;
612 char addr_str
[INET6_ADDRSTRLEN
];
613 struct zebra_if
*zif
;
618 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
620 if (len
< sizeof(struct nd_router_advert
)) {
621 if (IS_ZEBRA_DEBUG_PACKET
) {
622 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
625 "%s(%s:%u): Rx RA with invalid length %d from %s",
626 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, len
,
632 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
633 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
634 len
- sizeof(struct nd_router_advert
),
636 if (IS_ZEBRA_DEBUG_PACKET
) {
637 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
640 "%s(%s:%u): Rx RA with non-linklocal source address from %s",
641 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
,
647 radvert
= (struct nd_router_advert
*)msg
;
649 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
650 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
652 EC_ZEBRA_RA_PARAM_MISMATCH
,
653 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
654 ifp
->name
, ifp
->ifindex
, addr_str
);
657 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
658 && !zif
->rtadv
.AdvManagedFlag
) {
660 EC_ZEBRA_RA_PARAM_MISMATCH
,
661 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
662 ifp
->name
, ifp
->ifindex
, addr_str
);
665 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
666 && !zif
->rtadv
.AdvOtherConfigFlag
) {
668 EC_ZEBRA_RA_PARAM_MISMATCH
,
669 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
670 ifp
->name
, ifp
->ifindex
, addr_str
);
673 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
674 && (ntohl(radvert
->nd_ra_reachable
)
675 != zif
->rtadv
.AdvReachableTime
)) {
677 EC_ZEBRA_RA_PARAM_MISMATCH
,
678 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
679 ifp
->name
, ifp
->ifindex
, addr_str
);
682 if ((ntohl(radvert
->nd_ra_retransmit
)
683 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
685 EC_ZEBRA_RA_PARAM_MISMATCH
,
686 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
687 ifp
->name
, ifp
->ifindex
, addr_str
);
690 /* Create entry for neighbor if not known. */
692 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
693 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
695 if (!nbr_connected_check(ifp
, &p
))
696 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
700 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
701 ifindex_t ifindex
, int hoplimit
,
702 struct sockaddr_in6
*from
,
703 struct zebra_vrf
*zvrf
)
705 struct icmp6_hdr
*icmph
;
706 struct interface
*ifp
;
707 struct zebra_if
*zif
;
708 char addr_str
[INET6_ADDRSTRLEN
];
710 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
712 /* Interface search. */
713 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
715 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
716 "RA/RS received on unknown IF %u from %s", ifindex
,
721 if (IS_ZEBRA_DEBUG_PACKET
) {
722 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
724 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp
->name
,
725 VRF_LOGNAME(vrf
), ifp
->ifindex
, len
, addr_str
);
728 if (if_is_loopback(ifp
)
729 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
732 /* Check interface configuration. */
734 if (!zif
->rtadv
.AdvSendAdvertisements
)
737 /* ICMP message length check. */
738 if (len
< sizeof(struct icmp6_hdr
)) {
739 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
742 "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
743 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, len
);
747 icmph
= (struct icmp6_hdr
*)buf
;
749 /* ICMP message type check. */
750 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
751 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
752 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
754 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
755 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
,
760 /* Hoplimit check. */
761 if (hoplimit
>= 0 && hoplimit
!= 255) {
762 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
764 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
765 VRF_LOGNAME(vrf
), ifp
->ifindex
, hoplimit
);
769 /* Check ICMP message type. */
770 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
771 rtadv_process_solicit(ifp
);
772 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
773 rtadv_process_advert(buf
, len
, ifp
, from
);
778 static int rtadv_read(struct thread
*thread
)
782 uint8_t buf
[RTADV_MSG_SIZE
];
783 struct sockaddr_in6 from
;
784 ifindex_t ifindex
= 0;
786 struct zebra_vrf
*zvrf
= THREAD_ARG(thread
);
788 sock
= THREAD_FD(thread
);
789 zvrf
->rtadv
.ra_read
= NULL
;
791 /* Register myself. */
792 rtadv_event(zvrf
, RTADV_READ
, sock
);
794 len
= rtadv_recv_packet(zvrf
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
798 flog_err_sys(EC_LIB_SOCKET
,
799 "RA/RS recv failed, socket %u error %s", sock
,
800 safe_strerror(errno
));
804 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zvrf
);
809 static int rtadv_make_socket(ns_id_t ns_id
)
813 struct icmp6_filter filter
;
815 frr_with_privs(&zserv_privs
) {
817 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
825 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
830 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
835 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
840 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
845 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
851 ICMP6_FILTER_SETBLOCKALL(&filter
);
852 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
853 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
855 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
856 sizeof(struct icmp6_filter
));
858 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
866 static struct rtadv_prefix
*rtadv_prefix_new(void)
868 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
871 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
873 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
876 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
877 struct prefix_ipv6
*p
)
879 struct listnode
*node
;
880 struct rtadv_prefix
*rprefix
;
882 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
883 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
889 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
890 struct prefix_ipv6
*p
)
892 struct rtadv_prefix
*rprefix
;
894 rprefix
= rtadv_prefix_lookup(rplist
, p
);
898 rprefix
= rtadv_prefix_new();
899 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
900 listnode_add(rplist
, rprefix
);
905 static void rtadv_prefix_set_defaults(struct rtadv_prefix
*rp
)
907 rp
->AdvAutonomousFlag
= 1;
908 rp
->AdvOnLinkFlag
= 1;
909 rp
->AdvRouterAddressFlag
= 0;
910 rp
->AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
911 rp
->AdvValidLifetime
= RTADV_VALID_LIFETIME
;
914 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
916 struct rtadv_prefix
*rprefix
;
918 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
921 * Set parameters based on where the prefix is created.
922 * If auto-created based on kernel address addition, set the
923 * default values. If created from a manual "ipv6 nd prefix"
924 * command, take the parameters from the manual command. Note
925 * that if the manual command exists, the default values will
926 * not overwrite the manual values.
928 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
929 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_AUTO
)
930 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
932 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
934 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
935 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
936 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
937 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
938 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
939 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
940 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
941 rprefix
->AdvPrefixCreate
= PREFIX_SRC_BOTH
;
943 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
944 rtadv_prefix_set_defaults(rprefix
);
949 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
951 struct rtadv_prefix
*rprefix
;
953 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
954 if (rprefix
!= NULL
) {
957 * When deleting an address from the list, need to take care
958 * it wasn't defined both automatically via kernel
959 * address addition as well as manually by vtysh cli. If both,
960 * we don't actually delete but may change the parameters
961 * back to default if a manually defined entry is deleted.
963 if (rp
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
) {
964 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
965 rprefix
->AdvPrefixCreate
= PREFIX_SRC_AUTO
;
966 rtadv_prefix_set_defaults(rprefix
);
969 } else if (rp
->AdvPrefixCreate
== PREFIX_SRC_AUTO
) {
970 if (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
) {
971 rprefix
->AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
976 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
977 rtadv_prefix_free(rprefix
);
983 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
984 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
986 struct rtadv_prefix rp
;
989 apply_mask_ipv6(&rp
.prefix
);
990 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
991 rtadv_prefix_set(zif
, &rp
);
994 /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
995 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
997 struct rtadv_prefix rp
;
999 rp
.prefix
= *((struct prefix_ipv6
*)p
);
1000 apply_mask_ipv6(&rp
.prefix
);
1001 rp
.AdvPrefixCreate
= PREFIX_SRC_AUTO
;
1002 rtadv_prefix_reset(zif
, &rp
);
1005 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
1006 enum ipv6_nd_suppress_ra_status status
)
1008 struct zebra_if
*zif
;
1009 struct zebra_vrf
*zvrf
;
1012 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1014 if (status
== RA_SUPPRESS
) {
1015 /* RA is currently enabled */
1016 if (zif
->rtadv
.AdvSendAdvertisements
) {
1017 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
,
1019 zif
->rtadv
.AdvSendAdvertisements
= 0;
1020 zif
->rtadv
.AdvIntervalTimer
= 0;
1021 zvrf
->rtadv
.adv_if_count
--;
1023 if_leave_all_router(rtadv_get_socket(zvrf
), ifp
);
1025 if (zvrf
->rtadv
.adv_if_count
== 0)
1026 rtadv_event(zvrf
, RTADV_STOP
, 0);
1029 if (!zif
->rtadv
.AdvSendAdvertisements
) {
1030 zif
->rtadv
.AdvSendAdvertisements
= 1;
1031 zif
->rtadv
.AdvIntervalTimer
= 0;
1032 zvrf
->rtadv
.adv_if_count
++;
1034 if ((zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
1035 && zif
->rtadv
.UseFastRexmit
) {
1037 * Enable Fast RA only when RA interval is in
1038 * secs and Fast RA retransmit is enabled
1040 zif
->rtadv
.inFastRexmit
= 1;
1041 zif
->rtadv
.NumFastReXmitsRemain
=
1042 RTADV_NUM_FAST_REXMITS
;
1045 if_join_all_router(rtadv_get_socket(zvrf
), ifp
);
1047 if (zvrf
->rtadv
.adv_if_count
== 1)
1048 rtadv_event(zvrf
, RTADV_START
,
1049 rtadv_get_socket(zvrf
));
1055 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1056 * Note that while the client could request RA on an interface on which the
1057 * operator has not enabled RA, RA won't be disabled upon client request
1058 * if the operator has explicitly enabled RA. The enable request can also
1059 * specify a RA interval (in seconds).
1061 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
1065 struct interface
*ifp
;
1066 struct zebra_if
*zif
;
1067 int ra_interval_rxd
;
1071 /* Get interface index and RA interval. */
1072 STREAM_GETL(s
, ifindex
);
1073 STREAM_GETL(s
, ra_interval_rxd
);
1075 if (ra_interval_rxd
< 0) {
1077 "Requested RA interval %d is garbage; ignoring request",
1082 unsigned int ra_interval
= ra_interval_rxd
;
1084 if (IS_ZEBRA_DEBUG_EVENT
) {
1085 struct vrf
*vrf
= zvrf
->vrf
;
1087 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1088 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1089 enable
? "enable" : "disable",
1090 zebra_route_string(client
->proto
), ra_interval
);
1093 /* Locate interface and check VRF match. */
1094 ifp
= if_lookup_by_index(ifindex
, zvrf
->vrf
->vrf_id
);
1096 struct vrf
*vrf
= zvrf
->vrf
;
1098 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
1099 "%s:%u: IF %u RA %s client %s - interface unknown",
1100 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1101 enable
? "enable" : "disable",
1102 zebra_route_string(client
->proto
));
1105 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
1106 struct vrf
*vrf
= zvrf
->vrf
;
1109 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1110 VRF_LOGNAME(vrf
), zvrf_id(zvrf
), ifindex
,
1111 enable
? "enable" : "disable",
1112 zebra_route_string(client
->proto
), ifp
->vrf_id
);
1118 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1119 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1121 && (ra_interval
* 1000) < (unsigned int) zif
->rtadv
.MaxRtrAdvInterval
1122 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
1123 VTY_RA_INTERVAL_CONFIGURED
))
1124 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
1126 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
1127 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
1128 VTY_RA_INTERVAL_CONFIGURED
))
1129 zif
->rtadv
.MaxRtrAdvInterval
=
1130 RTADV_MAX_RTR_ADV_INTERVAL
;
1131 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1132 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1139 * send router lifetime value of zero in RAs on this interface since we're
1140 * ceasing to advertise and want to let our neighbors know.
1141 * RFC 4861 secion 6.2.5
1143 void rtadv_stop_ra(struct interface
*ifp
)
1145 struct zebra_if
*zif
;
1146 struct zebra_vrf
*zvrf
;
1149 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1151 if (zif
->rtadv
.AdvSendAdvertisements
)
1152 rtadv_send_packet(rtadv_get_socket(zvrf
), ifp
, RA_SUPPRESS
);
1156 * Send router lifetime value of zero in RAs on all interfaces since we're
1157 * ceasing to advertise globally and want to let all of our neighbors know
1158 * RFC 4861 secion 6.2.5
1160 * Delete all ipv6 global prefixes added to the router advertisement prefix
1161 * lists prior to ceasing.
1163 void rtadv_stop_ra_all(void)
1166 struct interface
*ifp
;
1167 struct listnode
*node
, *nnode
;
1168 struct zebra_if
*zif
;
1169 struct rtadv_prefix
*rprefix
;
1171 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1172 FOR_ALL_INTERFACES (vrf
, ifp
) {
1175 for (ALL_LIST_ELEMENTS(zif
->rtadv
.AdvPrefixList
,
1176 node
, nnode
, rprefix
))
1177 rtadv_prefix_reset(zif
, rprefix
);
1183 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
1185 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
1187 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
1189 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
1192 DEFUN (ipv6_nd_ra_fast_retrans
,
1193 ipv6_nd_ra_fast_retrans_cmd
,
1194 "ipv6 nd ra-fast-retrans",
1195 "Interface IPv6 config commands\n"
1196 "Neighbor discovery\n"
1197 "Fast retransmit of RA packets\n")
1199 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1200 struct zebra_if
*zif
= ifp
->info
;
1202 if (if_is_loopback(ifp
)
1203 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1205 "Cannot configure IPv6 Router Advertisements on this interface\n");
1206 return CMD_WARNING_CONFIG_FAILED
;
1209 zif
->rtadv
.UseFastRexmit
= true;
1214 DEFUN (no_ipv6_nd_ra_fast_retrans
,
1215 no_ipv6_nd_ra_fast_retrans_cmd
,
1216 "no ipv6 nd ra-fast-retrans",
1218 "Interface IPv6 config commands\n"
1219 "Neighbor discovery\n"
1220 "Fast retransmit of RA packets\n")
1222 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1223 struct zebra_if
*zif
= ifp
->info
;
1225 if (if_is_loopback(ifp
)
1226 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1228 "Cannot configure IPv6 Router Advertisements on this interface\n");
1229 return CMD_WARNING_CONFIG_FAILED
;
1232 zif
->rtadv
.UseFastRexmit
= false;
1237 DEFPY (ipv6_nd_ra_hop_limit
,
1238 ipv6_nd_ra_hop_limit_cmd
,
1239 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1240 "Interface IPv6 config commands\n"
1241 "Neighbor discovery\n"
1242 "Advertisement Hop Limit\n"
1243 "Advertisement Hop Limit in hops (default:64)\n")
1245 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1246 struct zebra_if
*zif
= ifp
->info
;
1248 if (if_is_loopback(ifp
)
1249 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1251 "Cannot configure IPv6 Router Advertisements on this interface\n");
1252 return CMD_WARNING_CONFIG_FAILED
;
1255 zif
->rtadv
.AdvCurHopLimit
= hopcount
;
1260 DEFPY (no_ipv6_nd_ra_hop_limit
,
1261 no_ipv6_nd_ra_hop_limit_cmd
,
1262 "no ipv6 nd ra-hop-limit [(0-255)]",
1264 "Interface IPv6 config commands\n"
1265 "Neighbor discovery\n"
1266 "Advertisement Hop Limit\n"
1267 "Advertisement Hop Limit in hops\n")
1269 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1270 struct zebra_if
*zif
= ifp
->info
;
1272 if (if_is_loopback(ifp
)
1273 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1275 "Cannot configure IPv6 Router Advertisements on this interface\n");
1276 return CMD_WARNING_CONFIG_FAILED
;
1279 zif
->rtadv
.AdvCurHopLimit
= RTADV_DEFAULT_HOPLIMIT
;
1284 DEFPY (ipv6_nd_ra_retrans_interval
,
1285 ipv6_nd_ra_retrans_interval_cmd
,
1286 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1287 "Interface IPv6 config commands\n"
1288 "Neighbor discovery\n"
1289 "Advertisement Retransmit Interval\n"
1290 "Advertisement Retransmit Interval in msec\n")
1292 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1293 struct zebra_if
*zif
= ifp
->info
;
1295 if (if_is_loopback(ifp
)
1296 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1298 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1299 return CMD_WARNING_CONFIG_FAILED
;
1302 zif
->rtadv
.AdvRetransTimer
= interval
;
1307 DEFPY (no_ipv6_nd_ra_retrans_interval
,
1308 no_ipv6_nd_ra_retrans_interval_cmd
,
1309 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1311 "Interface IPv6 config commands\n"
1312 "Neighbor discovery\n"
1313 "Advertisement Retransmit Interval\n"
1314 "Advertisement Retransmit Interval in msec\n")
1316 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1317 struct zebra_if
*zif
= ifp
->info
;
1319 if (if_is_loopback(ifp
)
1320 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1322 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1323 return CMD_WARNING_CONFIG_FAILED
;
1326 zif
->rtadv
.AdvRetransTimer
= 0;
1331 DEFUN (ipv6_nd_suppress_ra
,
1332 ipv6_nd_suppress_ra_cmd
,
1333 "ipv6 nd suppress-ra",
1334 "Interface IPv6 config commands\n"
1335 "Neighbor discovery\n"
1336 "Suppress Router Advertisement\n")
1338 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1339 struct zebra_if
*zif
= ifp
->info
;
1341 if (if_is_loopback(ifp
)
1342 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1344 "Cannot configure IPv6 Router Advertisements on this interface\n");
1345 return CMD_WARNING_CONFIG_FAILED
;
1348 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1349 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
1351 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1355 DEFUN (no_ipv6_nd_suppress_ra
,
1356 no_ipv6_nd_suppress_ra_cmd
,
1357 "no ipv6 nd suppress-ra",
1359 "Interface IPv6 config commands\n"
1360 "Neighbor discovery\n"
1361 "Suppress Router Advertisement\n")
1363 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1364 struct zebra_if
*zif
= ifp
->info
;
1366 if (if_is_loopback(ifp
)
1367 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
1369 "Cannot configure IPv6 Router Advertisements on this interface\n");
1370 return CMD_WARNING_CONFIG_FAILED
;
1373 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
1374 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
1378 DEFUN (ipv6_nd_ra_interval_msec
,
1379 ipv6_nd_ra_interval_msec_cmd
,
1380 "ipv6 nd ra-interval msec (70-1800000)",
1381 "Interface IPv6 config commands\n"
1382 "Neighbor discovery\n"
1383 "Router Advertisement interval\n"
1384 "Router Advertisement interval in milliseconds\n"
1385 "Router Advertisement interval in milliseconds\n")
1388 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1390 struct zebra_if
*zif
= ifp
->info
;
1391 struct zebra_vrf
*zvrf
;
1393 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1395 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1396 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1397 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
1399 "This ra-interval would conflict with configured ra-lifetime!\n");
1400 return CMD_WARNING_CONFIG_FAILED
;
1403 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1404 zvrf
->rtadv
.adv_msec_if_count
--;
1406 if (interval
% 1000)
1407 zvrf
->rtadv
.adv_msec_if_count
++;
1409 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1410 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1411 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1412 zif
->rtadv
.AdvIntervalTimer
= 0;
1417 DEFUN (ipv6_nd_ra_interval
,
1418 ipv6_nd_ra_interval_cmd
,
1419 "ipv6 nd ra-interval (1-1800)",
1420 "Interface IPv6 config commands\n"
1421 "Neighbor discovery\n"
1422 "Router Advertisement interval\n"
1423 "Router Advertisement interval in seconds\n")
1426 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1428 struct zebra_if
*zif
= ifp
->info
;
1429 struct zebra_vrf
*zvrf
;
1431 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1433 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1434 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1435 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1437 "This ra-interval would conflict with configured ra-lifetime!\n");
1438 return CMD_WARNING_CONFIG_FAILED
;
1441 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1442 zvrf
->rtadv
.adv_msec_if_count
--;
1444 /* convert to milliseconds */
1445 interval
= interval
* 1000;
1447 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1448 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1449 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1450 zif
->rtadv
.AdvIntervalTimer
= 0;
1455 DEFUN (no_ipv6_nd_ra_interval
,
1456 no_ipv6_nd_ra_interval_cmd
,
1457 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1459 "Interface IPv6 config commands\n"
1460 "Neighbor discovery\n"
1461 "Router Advertisement interval\n"
1462 "Router Advertisement interval in seconds\n"
1463 "Specify millisecond router advertisement interval\n"
1464 "Router Advertisement interval in milliseconds\n")
1466 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1467 struct zebra_if
*zif
= ifp
->info
;
1468 struct zebra_vrf
*zvrf
= NULL
;
1470 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1472 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1473 zvrf
->rtadv
.adv_msec_if_count
--;
1475 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1477 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1478 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1480 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1482 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1483 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1488 DEFUN (ipv6_nd_ra_lifetime
,
1489 ipv6_nd_ra_lifetime_cmd
,
1490 "ipv6 nd ra-lifetime (0-9000)",
1491 "Interface IPv6 config commands\n"
1492 "Neighbor discovery\n"
1494 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1497 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1498 struct zebra_if
*zif
= ifp
->info
;
1501 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1503 /* The value to be placed in the Router Lifetime field
1504 * of Router Advertisements sent from the interface,
1505 * in seconds. MUST be either zero or between
1506 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1507 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1509 "This ra-lifetime would conflict with configured ra-interval\n");
1510 return CMD_WARNING_CONFIG_FAILED
;
1513 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1518 DEFUN (no_ipv6_nd_ra_lifetime
,
1519 no_ipv6_nd_ra_lifetime_cmd
,
1520 "no ipv6 nd ra-lifetime [(0-9000)]",
1522 "Interface IPv6 config commands\n"
1523 "Neighbor discovery\n"
1525 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1527 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1528 struct zebra_if
*zif
= ifp
->info
;
1530 zif
->rtadv
.AdvDefaultLifetime
= -1;
1535 DEFUN (ipv6_nd_reachable_time
,
1536 ipv6_nd_reachable_time_cmd
,
1537 "ipv6 nd reachable-time (1-3600000)",
1538 "Interface IPv6 config commands\n"
1539 "Neighbor discovery\n"
1541 "Reachable time in milliseconds\n")
1544 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1545 struct zebra_if
*zif
= ifp
->info
;
1546 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1550 DEFUN (no_ipv6_nd_reachable_time
,
1551 no_ipv6_nd_reachable_time_cmd
,
1552 "no ipv6 nd reachable-time [(1-3600000)]",
1554 "Interface IPv6 config commands\n"
1555 "Neighbor discovery\n"
1557 "Reachable time in milliseconds\n")
1559 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1560 struct zebra_if
*zif
= ifp
->info
;
1562 zif
->rtadv
.AdvReachableTime
= 0;
1567 DEFUN (ipv6_nd_homeagent_preference
,
1568 ipv6_nd_homeagent_preference_cmd
,
1569 "ipv6 nd home-agent-preference (0-65535)",
1570 "Interface IPv6 config commands\n"
1571 "Neighbor discovery\n"
1572 "Home Agent preference\n"
1573 "preference value (default is 0, least preferred)\n")
1576 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1577 struct zebra_if
*zif
= ifp
->info
;
1578 zif
->rtadv
.HomeAgentPreference
=
1579 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1583 DEFUN (no_ipv6_nd_homeagent_preference
,
1584 no_ipv6_nd_homeagent_preference_cmd
,
1585 "no ipv6 nd home-agent-preference [(0-65535)]",
1587 "Interface IPv6 config commands\n"
1588 "Neighbor discovery\n"
1589 "Home Agent preference\n"
1590 "preference value (default is 0, least preferred)\n")
1592 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1593 struct zebra_if
*zif
= ifp
->info
;
1595 zif
->rtadv
.HomeAgentPreference
= 0;
1600 DEFUN (ipv6_nd_homeagent_lifetime
,
1601 ipv6_nd_homeagent_lifetime_cmd
,
1602 "ipv6 nd home-agent-lifetime (0-65520)",
1603 "Interface IPv6 config commands\n"
1604 "Neighbor discovery\n"
1605 "Home Agent lifetime\n"
1606 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1609 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1610 struct zebra_if
*zif
= ifp
->info
;
1611 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1615 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1616 no_ipv6_nd_homeagent_lifetime_cmd
,
1617 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1619 "Interface IPv6 config commands\n"
1620 "Neighbor discovery\n"
1621 "Home Agent lifetime\n"
1622 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1624 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1625 struct zebra_if
*zif
= ifp
->info
;
1627 zif
->rtadv
.HomeAgentLifetime
= -1;
1632 DEFUN (ipv6_nd_managed_config_flag
,
1633 ipv6_nd_managed_config_flag_cmd
,
1634 "ipv6 nd managed-config-flag",
1635 "Interface IPv6 config commands\n"
1636 "Neighbor discovery\n"
1637 "Managed address configuration flag\n")
1639 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1640 struct zebra_if
*zif
= ifp
->info
;
1642 zif
->rtadv
.AdvManagedFlag
= 1;
1647 DEFUN (no_ipv6_nd_managed_config_flag
,
1648 no_ipv6_nd_managed_config_flag_cmd
,
1649 "no ipv6 nd managed-config-flag",
1651 "Interface IPv6 config commands\n"
1652 "Neighbor discovery\n"
1653 "Managed address configuration flag\n")
1655 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1656 struct zebra_if
*zif
= ifp
->info
;
1658 zif
->rtadv
.AdvManagedFlag
= 0;
1663 DEFUN (ipv6_nd_homeagent_config_flag
,
1664 ipv6_nd_homeagent_config_flag_cmd
,
1665 "ipv6 nd home-agent-config-flag",
1666 "Interface IPv6 config commands\n"
1667 "Neighbor discovery\n"
1668 "Home Agent configuration flag\n")
1670 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1671 struct zebra_if
*zif
= ifp
->info
;
1673 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1678 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1679 no_ipv6_nd_homeagent_config_flag_cmd
,
1680 "no ipv6 nd home-agent-config-flag",
1682 "Interface IPv6 config commands\n"
1683 "Neighbor discovery\n"
1684 "Home Agent configuration flag\n")
1686 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1687 struct zebra_if
*zif
= ifp
->info
;
1689 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1694 DEFUN (ipv6_nd_adv_interval_config_option
,
1695 ipv6_nd_adv_interval_config_option_cmd
,
1696 "ipv6 nd adv-interval-option",
1697 "Interface IPv6 config commands\n"
1698 "Neighbor discovery\n"
1699 "Advertisement Interval Option\n")
1701 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1702 struct zebra_if
*zif
= ifp
->info
;
1704 zif
->rtadv
.AdvIntervalOption
= 1;
1709 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1710 no_ipv6_nd_adv_interval_config_option_cmd
,
1711 "no ipv6 nd adv-interval-option",
1713 "Interface IPv6 config commands\n"
1714 "Neighbor discovery\n"
1715 "Advertisement Interval Option\n")
1717 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1718 struct zebra_if
*zif
= ifp
->info
;
1720 zif
->rtadv
.AdvIntervalOption
= 0;
1725 DEFUN (ipv6_nd_other_config_flag
,
1726 ipv6_nd_other_config_flag_cmd
,
1727 "ipv6 nd other-config-flag",
1728 "Interface IPv6 config commands\n"
1729 "Neighbor discovery\n"
1730 "Other statefull configuration flag\n")
1732 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1733 struct zebra_if
*zif
= ifp
->info
;
1735 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1740 DEFUN (no_ipv6_nd_other_config_flag
,
1741 no_ipv6_nd_other_config_flag_cmd
,
1742 "no ipv6 nd other-config-flag",
1744 "Interface IPv6 config commands\n"
1745 "Neighbor discovery\n"
1746 "Other statefull configuration flag\n")
1748 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1749 struct zebra_if
*zif
= ifp
->info
;
1751 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1756 DEFUN (ipv6_nd_prefix
,
1758 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1759 "Interface IPv6 config commands\n"
1760 "Neighbor discovery\n"
1761 "Prefix information\n"
1763 "Valid lifetime in seconds\n"
1764 "Infinite valid lifetime\n"
1765 "Preferred lifetime in seconds\n"
1766 "Infinite preferred lifetime\n"
1767 "Set Router Address flag\n"
1768 "Do not use prefix for onlink determination\n"
1769 "Do not use prefix for autoconfiguration\n"
1770 "Do not use prefix for autoconfiguration\n"
1771 "Do not use prefix for onlink determination\n")
1774 char *prefix
= argv
[3]->arg
;
1775 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1776 || strmatch(argv
[4]->text
, "infinite"));
1777 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1779 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1781 char *lifetime
= NULL
, *preflifetime
= NULL
;
1782 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1784 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1786 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1791 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1793 offlink
= (argc
> idx_routeropts
+ 1
1794 || strmatch(argv
[idx_routeropts
]->text
,
1796 noautoconf
= (argc
> idx_routeropts
+ 1
1797 || strmatch(argv
[idx_routeropts
]->text
,
1803 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1804 struct zebra_if
*zebra_if
= ifp
->info
;
1806 struct rtadv_prefix rp
;
1808 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1810 vty_out(vty
, "Malformed IPv6 prefix\n");
1811 return CMD_WARNING_CONFIG_FAILED
;
1813 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1814 rp
.AdvOnLinkFlag
= !offlink
;
1815 rp
.AdvAutonomousFlag
= !noautoconf
;
1816 rp
.AdvRouterAddressFlag
= routeraddr
;
1817 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1818 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1819 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1822 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1824 : strtoll(lifetime
, NULL
, 10);
1825 rp
.AdvPreferredLifetime
=
1826 strmatch(preflifetime
, "infinite")
1828 : strtoll(preflifetime
, NULL
, 10);
1829 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1830 vty_out(vty
, "Invalid preferred lifetime\n");
1831 return CMD_WARNING_CONFIG_FAILED
;
1835 rtadv_prefix_set(zebra_if
, &rp
);
1840 DEFUN (no_ipv6_nd_prefix
,
1841 no_ipv6_nd_prefix_cmd
,
1842 "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]>]",
1844 "Interface IPv6 config commands\n"
1845 "Neighbor discovery\n"
1846 "Prefix information\n"
1848 "Valid lifetime in seconds\n"
1849 "Infinite valid lifetime\n"
1850 "Preferred lifetime in seconds\n"
1851 "Infinite preferred lifetime\n"
1852 "Set Router Address flag\n"
1853 "Do not use prefix for onlink determination\n"
1854 "Do not use prefix for autoconfiguration\n"
1855 "Do not use prefix for autoconfiguration\n"
1856 "Do not use prefix for onlink determination\n")
1858 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1859 struct zebra_if
*zebra_if
= ifp
->info
;
1861 struct rtadv_prefix rp
;
1862 char *prefix
= argv
[4]->arg
;
1864 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1866 vty_out(vty
, "Malformed IPv6 prefix\n");
1867 return CMD_WARNING_CONFIG_FAILED
;
1869 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1870 rp
.AdvPrefixCreate
= PREFIX_SRC_MANUAL
;
1872 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1874 vty_out(vty
, "Non-existant IPv6 prefix\n");
1875 return CMD_WARNING_CONFIG_FAILED
;
1881 DEFUN (ipv6_nd_router_preference
,
1882 ipv6_nd_router_preference_cmd
,
1883 "ipv6 nd router-preference <high|medium|low>",
1884 "Interface IPv6 config commands\n"
1885 "Neighbor discovery\n"
1886 "Default router preference\n"
1887 "High default router preference\n"
1888 "Medium default router preference (default)\n"
1889 "Low default router preference\n")
1891 int idx_high_medium_low
= 3;
1892 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1893 struct zebra_if
*zif
= ifp
->info
;
1896 while (0 != rtadv_pref_strs
[i
]) {
1897 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1900 zif
->rtadv
.DefaultPreference
= i
;
1906 return CMD_ERR_NO_MATCH
;
1909 DEFUN (no_ipv6_nd_router_preference
,
1910 no_ipv6_nd_router_preference_cmd
,
1911 "no ipv6 nd router-preference [<high|medium|low>]",
1913 "Interface IPv6 config commands\n"
1914 "Neighbor discovery\n"
1915 "Default router preference\n"
1916 "High default router preference\n"
1917 "Medium default router preference (default)\n"
1918 "Low default router preference\n")
1920 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1921 struct zebra_if
*zif
= ifp
->info
;
1923 zif
->rtadv
.DefaultPreference
=
1924 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1931 "ipv6 nd mtu (1-65535)",
1932 "Interface IPv6 config commands\n"
1933 "Neighbor discovery\n"
1938 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1939 struct zebra_if
*zif
= ifp
->info
;
1940 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1944 DEFUN (no_ipv6_nd_mtu
,
1946 "no ipv6 nd mtu [(1-65535)]",
1948 "Interface IPv6 config commands\n"
1949 "Neighbor discovery\n"
1953 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1954 struct zebra_if
*zif
= ifp
->info
;
1955 zif
->rtadv
.AdvLinkMTU
= 0;
1959 static struct rtadv_rdnss
*rtadv_rdnss_new(void)
1961 return XCALLOC(MTYPE_RTADV_RDNSS
, sizeof(struct rtadv_rdnss
));
1964 static void rtadv_rdnss_free(struct rtadv_rdnss
*rdnss
)
1966 XFREE(MTYPE_RTADV_RDNSS
, rdnss
);
1969 static struct rtadv_rdnss
*rtadv_rdnss_lookup(struct list
*list
,
1970 struct rtadv_rdnss
*rdnss
)
1972 struct listnode
*node
;
1973 struct rtadv_rdnss
*p
;
1975 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
1976 if (IPV6_ADDR_SAME(&p
->addr
, &rdnss
->addr
))
1981 static struct rtadv_rdnss
*rtadv_rdnss_get(struct list
*list
,
1982 struct rtadv_rdnss
*rdnss
)
1984 struct rtadv_rdnss
*p
;
1986 p
= rtadv_rdnss_lookup(list
, rdnss
);
1990 p
= rtadv_rdnss_new();
1991 memcpy(p
, rdnss
, sizeof(struct rtadv_rdnss
));
1992 listnode_add(list
, p
);
1997 static void rtadv_rdnss_set(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
1999 struct rtadv_rdnss
*p
;
2001 p
= rtadv_rdnss_get(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2002 p
->lifetime
= rdnss
->lifetime
;
2003 p
->lifetime_set
= rdnss
->lifetime_set
;
2006 static int rtadv_rdnss_reset(struct zebra_if
*zif
, struct rtadv_rdnss
*rdnss
)
2008 struct rtadv_rdnss
*p
;
2010 p
= rtadv_rdnss_lookup(zif
->rtadv
.AdvRDNSSList
, rdnss
);
2012 listnode_delete(zif
->rtadv
.AdvRDNSSList
, p
);
2013 rtadv_rdnss_free(p
);
2020 static struct rtadv_dnssl
*rtadv_dnssl_new(void)
2022 return XCALLOC(MTYPE_RTADV_DNSSL
, sizeof(struct rtadv_dnssl
));
2025 static void rtadv_dnssl_free(struct rtadv_dnssl
*dnssl
)
2027 XFREE(MTYPE_RTADV_DNSSL
, dnssl
);
2030 static struct rtadv_dnssl
*rtadv_dnssl_lookup(struct list
*list
,
2031 struct rtadv_dnssl
*dnssl
)
2033 struct listnode
*node
;
2034 struct rtadv_dnssl
*p
;
2036 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
))
2037 if (!strcasecmp(p
->name
, dnssl
->name
))
2042 static struct rtadv_dnssl
*rtadv_dnssl_get(struct list
*list
,
2043 struct rtadv_dnssl
*dnssl
)
2045 struct rtadv_dnssl
*p
;
2047 p
= rtadv_dnssl_lookup(list
, dnssl
);
2051 p
= rtadv_dnssl_new();
2052 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2053 listnode_add(list
, p
);
2058 static void rtadv_dnssl_set(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2060 struct rtadv_dnssl
*p
;
2062 p
= rtadv_dnssl_get(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2063 memcpy(p
, dnssl
, sizeof(struct rtadv_dnssl
));
2066 static int rtadv_dnssl_reset(struct zebra_if
*zif
, struct rtadv_dnssl
*dnssl
)
2068 struct rtadv_dnssl
*p
;
2070 p
= rtadv_dnssl_lookup(zif
->rtadv
.AdvDNSSLList
, dnssl
);
2072 listnode_delete(zif
->rtadv
.AdvDNSSLList
, p
);
2073 rtadv_dnssl_free(p
);
2081 * Convert dotted domain name (with or without trailing root zone dot) to
2082 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2083 * to strlen(in) + 2 octets to out.
2085 * Returns the number of octets written to out or -1 if in does not constitute
2086 * a valid domain name.
2088 static int rtadv_dnssl_encode(uint8_t *out
, const char *in
)
2090 const char *label_start
, *label_end
;
2096 while (*label_start
) {
2099 label_end
= strchr(label_start
, '.');
2100 if (label_end
== NULL
)
2101 label_end
= label_start
+ strlen(label_start
);
2103 label_len
= label_end
- label_start
;
2104 if (label_len
>= 64)
2105 return -1; /* labels must be 63 octets or less */
2107 out
[outp
++] = (uint8_t)label_len
;
2108 memcpy(out
+ outp
, label_start
, label_len
);
2110 label_start
+= label_len
;
2111 if (*label_start
== '.')
2119 DEFUN(ipv6_nd_rdnss
,
2121 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2122 "Interface IPv6 config commands\n"
2123 "Neighbor discovery\n"
2124 "Recursive DNS server information\n"
2126 "Valid lifetime in seconds\n"
2127 "Infinite valid lifetime\n")
2129 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2130 struct zebra_if
*zif
= ifp
->info
;
2131 struct rtadv_rdnss rdnss
= {};
2133 if (inet_pton(AF_INET6
, argv
[3]->arg
, &rdnss
.addr
) != 1) {
2134 vty_out(vty
, "Malformed IPv6 address\n");
2135 return CMD_WARNING_CONFIG_FAILED
;
2138 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2140 rdnss
.lifetime
= strmatch(lifetime
, "infinite")
2142 : strtoll(lifetime
, NULL
, 10);
2143 rdnss
.lifetime_set
= 1;
2146 rtadv_rdnss_set(zif
, &rdnss
);
2151 DEFUN(no_ipv6_nd_rdnss
,
2152 no_ipv6_nd_rdnss_cmd
,
2153 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2155 "Interface IPv6 config commands\n"
2156 "Neighbor discovery\n"
2157 "Recursive DNS server information\n"
2159 "Valid lifetime in seconds\n"
2160 "Infinite valid lifetime\n")
2162 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2163 struct zebra_if
*zif
= ifp
->info
;
2164 struct rtadv_rdnss rdnss
= {};
2166 if (inet_pton(AF_INET6
, argv
[4]->arg
, &rdnss
.addr
) != 1) {
2167 vty_out(vty
, "Malformed IPv6 address\n");
2168 return CMD_WARNING_CONFIG_FAILED
;
2170 if (rtadv_rdnss_reset(zif
, &rdnss
) != 1) {
2171 vty_out(vty
, "Non-existant RDNSS address\n");
2172 return CMD_WARNING_CONFIG_FAILED
;
2178 DEFUN(ipv6_nd_dnssl
,
2180 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2181 "Interface IPv6 config commands\n"
2182 "Neighbor discovery\n"
2183 "DNS search list information\n"
2184 "Domain name suffix\n"
2185 "Valid lifetime in seconds\n"
2186 "Infinite valid lifetime\n")
2188 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2189 struct zebra_if
*zif
= ifp
->info
;
2190 struct rtadv_dnssl dnssl
= {};
2194 len
= strlcpy(dnssl
.name
, argv
[3]->arg
, sizeof(dnssl
.name
));
2195 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2196 vty_out(vty
, "Malformed DNS search domain\n");
2197 return CMD_WARNING_CONFIG_FAILED
;
2199 if (dnssl
.name
[len
- 1] == '.') {
2201 * Allow, but don't require, a trailing dot signifying the root
2202 * zone. Canonicalize by cutting it off if present.
2204 dnssl
.name
[len
- 1] = '\0';
2208 char *lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
2210 dnssl
.lifetime
= strmatch(lifetime
, "infinite")
2212 : strtoll(lifetime
, NULL
, 10);
2213 dnssl
.lifetime_set
= 1;
2216 ret
= rtadv_dnssl_encode(dnssl
.encoded_name
, dnssl
.name
);
2218 vty_out(vty
, "Malformed DNS search domain\n");
2219 return CMD_WARNING_CONFIG_FAILED
;
2221 dnssl
.encoded_len
= ret
;
2222 rtadv_dnssl_set(zif
, &dnssl
);
2227 DEFUN(no_ipv6_nd_dnssl
,
2228 no_ipv6_nd_dnssl_cmd
,
2229 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2231 "Interface IPv6 config commands\n"
2232 "Neighbor discovery\n"
2233 "DNS search list information\n"
2234 "Domain name suffix\n"
2235 "Valid lifetime in seconds\n"
2236 "Infinite valid lifetime\n")
2238 VTY_DECLVAR_CONTEXT(interface
, ifp
);
2239 struct zebra_if
*zif
= ifp
->info
;
2240 struct rtadv_dnssl dnssl
= {};
2243 len
= strlcpy(dnssl
.name
, argv
[4]->arg
, sizeof(dnssl
.name
));
2244 if (len
== 0 || len
>= sizeof(dnssl
.name
)) {
2245 vty_out(vty
, "Malformed DNS search domain\n");
2246 return CMD_WARNING_CONFIG_FAILED
;
2248 if (dnssl
.name
[len
- 1] == '.') {
2249 dnssl
.name
[len
- 1] = '\0';
2252 if (rtadv_dnssl_reset(zif
, &dnssl
) != 1) {
2253 vty_out(vty
, "Non-existant DNS search domain\n");
2254 return CMD_WARNING_CONFIG_FAILED
;
2261 /* Dump interface ND information to vty. */
2262 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
2264 struct zebra_if
*zif
;
2265 struct rtadvconf
*rtadv
;
2268 zif
= (struct zebra_if
*)ifp
->info
;
2269 rtadv
= &zif
->rtadv
;
2271 if (rtadv
->AdvSendAdvertisements
) {
2273 " ND advertised reachable time is %d milliseconds\n",
2274 rtadv
->AdvReachableTime
);
2276 " ND advertised retransmit interval is %u milliseconds\n",
2277 rtadv
->AdvRetransTimer
);
2278 vty_out(vty
, " ND advertised hop-count limit is %d hops\n",
2279 rtadv
->AdvCurHopLimit
);
2280 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
2281 zif
->ra_sent
, zif
->ra_rcvd
);
2282 interval
= rtadv
->MaxRtrAdvInterval
;
2283 if (interval
% 1000)
2285 " ND router advertisements are sent every %d milliseconds\n",
2289 " ND router advertisements are sent every %d seconds\n",
2291 if (!rtadv
->UseFastRexmit
)
2293 " ND router advertisements do not use fast retransmit\n");
2295 if (rtadv
->AdvDefaultLifetime
!= -1)
2297 " ND router advertisements live for %d seconds\n",
2298 rtadv
->AdvDefaultLifetime
);
2301 " ND router advertisements lifetime tracks ra-interval\n");
2303 " ND router advertisement default router preference is %s\n",
2304 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
2305 if (rtadv
->AdvManagedFlag
)
2307 " Hosts use DHCP to obtain routable addresses.\n");
2310 " Hosts use stateless autoconfig for addresses.\n");
2311 if (rtadv
->AdvHomeAgentFlag
) {
2313 " ND router advertisements with Home Agent flag bit set.\n");
2314 if (rtadv
->HomeAgentLifetime
!= -1)
2316 " Home Agent lifetime is %u seconds\n",
2317 rtadv
->HomeAgentLifetime
);
2320 " Home Agent lifetime tracks ra-lifetime\n");
2321 vty_out(vty
, " Home Agent preference is %u\n",
2322 rtadv
->HomeAgentPreference
);
2324 if (rtadv
->AdvIntervalOption
)
2326 " ND router advertisements with Adv. Interval option.\n");
2332 /* Write configuration about router advertisement. */
2333 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
2335 struct zebra_if
*zif
;
2336 struct listnode
*node
;
2337 struct rtadv_prefix
*rprefix
;
2338 struct rtadv_rdnss
*rdnss
;
2339 struct rtadv_dnssl
*dnssl
;
2344 if (!(if_is_loopback(ifp
)
2345 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
2346 if (zif
->rtadv
.AdvSendAdvertisements
2347 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
2348 vty_out(vty
, " no ipv6 nd suppress-ra\n");
2351 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
2352 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
2353 if (interval
% 1000)
2354 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
2356 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
2357 vty_out(vty
, " ipv6 nd ra-interval %d\n",
2361 if (zif
->rtadv
.AdvIntervalOption
)
2362 vty_out(vty
, " ipv6 nd adv-interval-option\n");
2364 if (!zif
->rtadv
.UseFastRexmit
)
2365 vty_out(vty
, " no ipv6 nd ra-fast-retrans\n");
2367 if (zif
->rtadv
.AdvRetransTimer
!= 0)
2368 vty_out(vty
, " ipv6 nd ra-retrans-interval %u\n",
2369 zif
->rtadv
.AdvRetransTimer
);
2371 if (zif
->rtadv
.AdvCurHopLimit
!= RTADV_DEFAULT_HOPLIMIT
)
2372 vty_out(vty
, " ipv6 nd ra-hop-limit %d\n",
2373 zif
->rtadv
.AdvCurHopLimit
);
2375 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
2376 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
2377 zif
->rtadv
.AdvDefaultLifetime
);
2379 if (zif
->rtadv
.HomeAgentPreference
)
2380 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
2381 zif
->rtadv
.HomeAgentPreference
);
2383 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
2384 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
2385 zif
->rtadv
.HomeAgentLifetime
);
2387 if (zif
->rtadv
.AdvHomeAgentFlag
)
2388 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
2390 if (zif
->rtadv
.AdvReachableTime
)
2391 vty_out(vty
, " ipv6 nd reachable-time %d\n",
2392 zif
->rtadv
.AdvReachableTime
);
2394 if (zif
->rtadv
.AdvManagedFlag
)
2395 vty_out(vty
, " ipv6 nd managed-config-flag\n");
2397 if (zif
->rtadv
.AdvOtherConfigFlag
)
2398 vty_out(vty
, " ipv6 nd other-config-flag\n");
2400 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
2401 vty_out(vty
, " ipv6 nd router-preference %s\n",
2402 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
2404 if (zif
->rtadv
.AdvLinkMTU
)
2405 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
2407 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
2408 if ((rprefix
->AdvPrefixCreate
== PREFIX_SRC_MANUAL
)
2409 || (rprefix
->AdvPrefixCreate
== PREFIX_SRC_BOTH
)) {
2410 vty_out(vty
, " ipv6 nd prefix %pFX", &rprefix
->prefix
);
2411 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
2412 || (rprefix
->AdvPreferredLifetime
2413 != RTADV_PREFERRED_LIFETIME
)) {
2414 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
2415 vty_out(vty
, " infinite");
2418 rprefix
->AdvValidLifetime
);
2419 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
2420 vty_out(vty
, " infinite");
2423 rprefix
->AdvPreferredLifetime
);
2425 if (!rprefix
->AdvOnLinkFlag
)
2426 vty_out(vty
, " off-link");
2427 if (!rprefix
->AdvAutonomousFlag
)
2428 vty_out(vty
, " no-autoconfig");
2429 if (rprefix
->AdvRouterAddressFlag
)
2430 vty_out(vty
, " router-address");
2435 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvRDNSSList
, node
, rdnss
)) {
2436 char buf
[INET6_ADDRSTRLEN
];
2438 vty_out(vty
, " ipv6 nd rdnss %s",
2439 inet_ntop(AF_INET6
, &rdnss
->addr
, buf
, sizeof(buf
)));
2440 if (rdnss
->lifetime_set
) {
2441 if (rdnss
->lifetime
== UINT32_MAX
)
2442 vty_out(vty
, " infinite");
2444 vty_out(vty
, " %u", rdnss
->lifetime
);
2448 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvDNSSLList
, node
, dnssl
)) {
2449 vty_out(vty
, " ipv6 nd dnssl %s", dnssl
->name
);
2450 if (dnssl
->lifetime_set
) {
2451 if (dnssl
->lifetime
== UINT32_MAX
)
2452 vty_out(vty
, " infinite");
2454 vty_out(vty
, " %u", dnssl
->lifetime
);
2462 static void rtadv_event(struct zebra_vrf
*zvrf
, enum rtadv_event event
, int val
)
2464 struct rtadv
*rtadv
= &zvrf
->rtadv
;
2466 if (IS_ZEBRA_DEBUG_EVENT
) {
2467 struct vrf
*vrf
= zvrf
->vrf
;
2469 zlog_debug("%s(%s) with event: %d and val: %d", __func__
,
2470 VRF_LOGNAME(vrf
), event
, val
);
2475 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2477 thread_add_event(zrouter
.master
, rtadv_timer
, zvrf
, 0,
2481 THREAD_OFF(rtadv
->ra_timer
);
2482 THREAD_OFF(rtadv
->ra_read
);
2485 thread_add_timer(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2488 case RTADV_TIMER_MSEC
:
2489 thread_add_timer_msec(zrouter
.master
, rtadv_timer
, zvrf
, val
,
2493 thread_add_read(zrouter
.master
, rtadv_read
, zvrf
, val
,
2502 void rtadv_init(struct zebra_vrf
*zvrf
)
2504 if (vrf_is_backend_netns()) {
2505 zvrf
->rtadv
.sock
= rtadv_make_socket(zvrf
->zns
->ns_id
);
2506 zrouter
.rtadv_sock
= -1;
2508 zvrf
->rtadv
.sock
= -1;
2509 if (zrouter
.rtadv_sock
< 0)
2510 zrouter
.rtadv_sock
=
2511 rtadv_make_socket(zvrf
->zns
->ns_id
);
2515 void rtadv_vrf_terminate(struct zebra_vrf
*zvrf
)
2517 rtadv_event(zvrf
, RTADV_STOP
, 0);
2518 if (zvrf
->rtadv
.sock
>= 0) {
2519 close(zvrf
->rtadv
.sock
);
2520 zvrf
->rtadv
.sock
= -1;
2523 zvrf
->rtadv
.adv_if_count
= 0;
2524 zvrf
->rtadv
.adv_msec_if_count
= 0;
2527 void rtadv_terminate(void)
2529 if (zrouter
.rtadv_sock
>= 0) {
2530 close(zrouter
.rtadv_sock
);
2531 zrouter
.rtadv_sock
= -1;
2535 void rtadv_cmd_init(void)
2537 hook_register(zebra_if_extra_info
, nd_dump_vty
);
2538 hook_register(zebra_if_config_wr
, rtadv_config_write
);
2540 install_element(INTERFACE_NODE
, &ipv6_nd_ra_fast_retrans_cmd
);
2541 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_fast_retrans_cmd
);
2542 install_element(INTERFACE_NODE
, &ipv6_nd_ra_retrans_interval_cmd
);
2543 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_retrans_interval_cmd
);
2544 install_element(INTERFACE_NODE
, &ipv6_nd_ra_hop_limit_cmd
);
2545 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_hop_limit_cmd
);
2546 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
2547 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
2548 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
2549 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
2550 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
2551 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
2552 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
2553 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
2554 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
2555 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
2556 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
2557 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
2558 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
2559 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
2560 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
2561 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
2562 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
2563 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
2564 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
2565 install_element(INTERFACE_NODE
,
2566 &ipv6_nd_adv_interval_config_option_cmd
);
2567 install_element(INTERFACE_NODE
,
2568 &no_ipv6_nd_adv_interval_config_option_cmd
);
2569 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
2570 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
2571 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
2572 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
2573 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
2574 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
2575 install_element(INTERFACE_NODE
, &ipv6_nd_rdnss_cmd
);
2576 install_element(INTERFACE_NODE
, &no_ipv6_nd_rdnss_cmd
);
2577 install_element(INTERFACE_NODE
, &ipv6_nd_dnssl_cmd
);
2578 install_element(INTERFACE_NODE
, &no_ipv6_nd_dnssl_cmd
);
2581 static int if_join_all_router(int sock
, struct interface
*ifp
)
2585 struct ipv6_mreq mreq
;
2587 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2588 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2589 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2591 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
2594 flog_err_sys(EC_LIB_SOCKET
,
2595 "%s(%u): Failed to join group, socket %u error %s",
2596 ifp
->name
, ifp
->ifindex
, sock
,
2597 safe_strerror(errno
));
2599 if (IS_ZEBRA_DEBUG_EVENT
) {
2600 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
2603 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2604 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, sock
);
2610 static int if_leave_all_router(int sock
, struct interface
*ifp
)
2614 struct ipv6_mreq mreq
;
2616 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
2617 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
2618 mreq
.ipv6mr_interface
= ifp
->ifindex
;
2620 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
2623 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
2627 "%s(%s:%u): Failed to leave group, socket %u error %s",
2628 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, sock
,
2629 safe_strerror(errno
));
2631 if (IS_ZEBRA_DEBUG_EVENT
) {
2632 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
2635 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
2636 ifp
->name
, VRF_LOGNAME(vrf
), ifp
->ifindex
, sock
);
2642 void rtadv_init(struct zebra_vrf
*zvrf
)
2646 void rtadv_terminate(void)
2650 void rtadv_cmd_init(void)
2655 void rtadv_add_prefix(struct zebra_if
*zif
, const struct prefix_ipv6
*p
)
2660 void rtadv_delete_prefix(struct zebra_if
*zif
, const struct prefix
*p
)
2665 void rtadv_stop_ra(struct interface
*ifp
)
2670 void rtadv_stop_ra_all(void)
2676 * If the end user does not have RADV enabled we should
2677 * handle this better
2679 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
2681 if (IS_ZEBRA_DEBUG_PACKET
)
2683 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
2684 zserv_command_string(hdr
->command
));
2689 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
2691 if (IS_ZEBRA_DEBUG_PACKET
)
2693 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
2694 zserv_command_string(hdr
->command
));
2699 #endif /* HAVE_RTADV */