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"
48 extern struct zebra_privs_t zserv_privs
;
50 #if defined(HAVE_RTADV)
53 #include <netinet/icmp6.h>
56 /* If RFC2133 definition is used. */
57 #ifndef IPV6_JOIN_GROUP
58 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
60 #ifndef IPV6_LEAVE_GROUP
61 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
64 #define ALLNODE "ff02::1"
65 #define ALLROUTER "ff02::2"
67 /* Order is intentional. Matches RFC4191. This array is also used for
68 command matching, so only modify with care. */
69 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
79 static void rtadv_event(struct zebra_ns
*, enum rtadv_event
, int);
81 static int if_join_all_router(int, struct interface
*);
82 static int if_leave_all_router(int, struct interface
*);
84 static int rtadv_increment_received(struct zebra_ns
*zns
, ifindex_t
*ifindex
)
87 struct interface
*iface
;
90 iface
= if_lookup_by_index_per_ns(zns
, *ifindex
);
91 if (iface
&& iface
->info
) {
99 static int rtadv_recv_packet(struct zebra_ns
*zns
, int sock
, uint8_t *buf
,
100 int buflen
, struct sockaddr_in6
*from
,
101 ifindex_t
*ifindex
, int *hoplimit
)
106 struct cmsghdr
*cmsgptr
;
111 /* Fill in message and iovec. */
112 memset(&msg
, 0, sizeof(msg
));
113 msg
.msg_name
= (void *)from
;
114 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
117 msg
.msg_control
= (void *)adata
;
118 msg
.msg_controllen
= sizeof adata
;
120 iov
.iov_len
= buflen
;
122 /* If recvmsg fail return minus value. */
123 ret
= recvmsg(sock
, &msg
, 0);
127 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
128 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
129 /* I want interface index which this packet comes from. */
130 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
131 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
132 struct in6_pktinfo
*ptr
;
134 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
135 *ifindex
= ptr
->ipi6_ifindex
;
136 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
139 /* Incoming packet's hop limit. */
140 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
141 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
142 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
147 rtadv_increment_received(zns
, ifindex
);
151 #define RTADV_MSG_SIZE 4096
153 /* Send router advertisement packet. */
154 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
158 struct cmsghdr
*cmsgptr
;
159 struct in6_pktinfo
*pkt
;
160 struct sockaddr_in6 addr
;
161 static void *adata
= NULL
;
162 unsigned char buf
[RTADV_MSG_SIZE
];
163 struct nd_router_advert
*rtadv
;
166 struct zebra_if
*zif
;
167 struct rtadv_prefix
*rprefix
;
168 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 0, 0, 0, 0, 1};
170 struct listnode
*node
;
171 uint16_t pkt_RouterLifetime
;
174 * Allocate control message bufffer. This is dynamic because
175 * CMSG_SPACE is not guaranteed not to call a function. Note that
176 * the size will be different on different architectures due to
177 * differing alignment rules.
180 /* XXX Free on shutdown. */
181 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
185 "rtadv_send_packet: can't malloc control data");
190 /* Logging of packet. */
191 if (IS_ZEBRA_DEBUG_PACKET
)
192 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
195 /* Fill in sockaddr_in6. */
196 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
197 addr
.sin6_family
= AF_INET6
;
199 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
200 #endif /* SIN6_LEN */
201 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
202 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
204 /* Fetch interface information. */
207 /* Make router advertisement message. */
208 rtadv
= (struct nd_router_advert
*)buf
;
210 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
211 rtadv
->nd_ra_code
= 0;
212 rtadv
->nd_ra_cksum
= 0;
214 rtadv
->nd_ra_curhoplimit
= 64;
216 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
217 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
219 : zif
->rtadv
.DefaultPreference
;
220 rtadv
->nd_ra_flags_reserved
<<= 3;
222 if (zif
->rtadv
.AdvManagedFlag
)
223 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
224 if (zif
->rtadv
.AdvOtherConfigFlag
)
225 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
226 if (zif
->rtadv
.AdvHomeAgentFlag
)
227 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
228 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
229 * AdvDefaultLifetime is by default based on the value of
230 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
231 * field of Router Advertisements. Given that this field is expressed
232 * in seconds, a small MaxRtrAdvInterval value can result in a zero
233 * value for this field. To prevent this, routers SHOULD keep
234 * AdvDefaultLifetime in at least one second, even if the use of
235 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
237 zif
->rtadv
.AdvDefaultLifetime
!= -1
238 ? zif
->rtadv
.AdvDefaultLifetime
239 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
240 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
241 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
242 rtadv
->nd_ra_retransmit
= htonl(0);
244 len
= sizeof(struct nd_router_advert
);
246 /* If both the Home Agent Preference and Home Agent Lifetime are set to
247 * their default values specified above, this option SHOULD NOT be
248 * included in the Router Advertisement messages sent by this home
249 * agent. -- RFC6275, 7.4 */
250 if (zif
->rtadv
.AdvHomeAgentFlag
251 && (zif
->rtadv
.HomeAgentPreference
252 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
253 struct nd_opt_homeagent_info
*ndopt_hai
=
254 (struct nd_opt_homeagent_info
*)(buf
+ len
);
255 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
256 ndopt_hai
->nd_opt_hai_len
= 1;
257 ndopt_hai
->nd_opt_hai_reserved
= 0;
258 ndopt_hai
->nd_opt_hai_preference
=
259 htons(zif
->rtadv
.HomeAgentPreference
);
260 /* 16-bit unsigned integer. The lifetime associated with the
262 * agent in units of seconds. The default value is the same as
264 * Router Lifetime, as specified in the main body of the Router
265 * Advertisement. The maximum value corresponds to 18.2 hours.
267 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
268 ndopt_hai
->nd_opt_hai_lifetime
=
269 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
270 ? zif
->rtadv
.HomeAgentLifetime
271 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
276 len
+= sizeof(struct nd_opt_homeagent_info
);
279 if (zif
->rtadv
.AdvIntervalOption
) {
280 struct nd_opt_adv_interval
*ndopt_adv
=
281 (struct nd_opt_adv_interval
*)(buf
+ len
);
282 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
283 ndopt_adv
->nd_opt_ai_len
= 1;
284 ndopt_adv
->nd_opt_ai_reserved
= 0;
285 ndopt_adv
->nd_opt_ai_interval
=
286 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
287 len
+= sizeof(struct nd_opt_adv_interval
);
290 /* Fill in prefix. */
291 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
292 struct nd_opt_prefix_info
*pinfo
;
294 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
296 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
297 pinfo
->nd_opt_pi_len
= 4;
298 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
300 pinfo
->nd_opt_pi_flags_reserved
= 0;
301 if (rprefix
->AdvOnLinkFlag
)
302 pinfo
->nd_opt_pi_flags_reserved
|=
303 ND_OPT_PI_FLAG_ONLINK
;
304 if (rprefix
->AdvAutonomousFlag
)
305 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
306 if (rprefix
->AdvRouterAddressFlag
)
307 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
309 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
310 pinfo
->nd_opt_pi_preferred_time
=
311 htonl(rprefix
->AdvPreferredLifetime
);
312 pinfo
->nd_opt_pi_reserved2
= 0;
314 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
315 &rprefix
->prefix
.prefix
);
319 uint8_t buf
[INET6_ADDRSTRLEN
];
321 zlog_debug("DEBUG %s",
322 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
323 buf
, INET6_ADDRSTRLEN
));
327 len
+= sizeof(struct nd_opt_prefix_info
);
330 /* Hardware address. */
331 if (ifp
->hw_addr_len
!= 0) {
332 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
334 /* Option length should be rounded up to next octet if
335 the link address does not end on an octet boundary. */
336 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
338 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
339 len
+= ifp
->hw_addr_len
;
341 /* Pad option to end on an octet boundary. */
342 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
343 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
347 if (zif
->rtadv
.AdvLinkMTU
) {
348 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
349 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
350 opt
->nd_opt_mtu_len
= 1;
351 opt
->nd_opt_mtu_reserved
= 0;
352 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
353 len
+= sizeof(struct nd_opt_mtu
);
356 msg
.msg_name
= (void *)&addr
;
357 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
360 msg
.msg_control
= (void *)adata
;
361 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
366 cmsgptr
= ZCMSG_FIRSTHDR(&msg
);
367 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
368 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
369 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
371 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
372 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
373 pkt
->ipi6_ifindex
= ifp
->ifindex
;
375 ret
= sendmsg(sock
, &msg
, 0);
377 flog_err_sys(LIB_ERR_SOCKET
,
378 "%s(%u): Tx RA failed, socket %u error %d (%s)",
379 ifp
->name
, ifp
->ifindex
, sock
, errno
,
380 safe_strerror(errno
));
385 static int rtadv_timer(struct thread
*thread
)
387 struct zebra_ns
*zns
= THREAD_ARG(thread
);
389 struct interface
*ifp
;
390 struct zebra_if
*zif
;
393 zns
->rtadv
.ra_timer
= NULL
;
394 if (zns
->rtadv
.adv_msec_if_count
== 0) {
395 period
= 1000; /* 1 s */
396 rtadv_event(zns
, RTADV_TIMER
, 1 /* 1 s */);
398 period
= 10; /* 10 ms */
399 rtadv_event(zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
402 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
403 FOR_ALL_INTERFACES (vrf
, ifp
) {
404 if (if_is_loopback(ifp
)
405 || CHECK_FLAG(ifp
->status
,
406 ZEBRA_INTERFACE_VRF_LOOPBACK
)
407 || !if_is_operative(ifp
))
412 if (zif
->rtadv
.AdvSendAdvertisements
) {
413 if (zif
->rtadv
.inFastRexmit
) {
414 /* We assume we fast rexmit every sec so
417 if (--zif
->rtadv
.NumFastReXmitsRemain
419 zif
->rtadv
.inFastRexmit
= 0;
421 if (IS_ZEBRA_DEBUG_SEND
)
423 "Fast RA Rexmit on interface %s",
426 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
428 zif
->rtadv
.AdvIntervalTimer
-= period
;
429 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
431 MaxRtrAdvInterval each
432 time isn't what section
433 6.2.4 of RFC4861 tells to do.
435 zif
->rtadv
.AdvIntervalTimer
=
439 zns
->rtadv
.sock
, ifp
);
448 static void rtadv_process_solicit(struct interface
*ifp
)
450 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
451 struct zebra_ns
*zns
= zvrf
->zns
;
454 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
457 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
458 struct interface
*ifp
,
459 struct sockaddr_in6
*addr
)
461 struct nd_router_advert
*radvert
;
462 char addr_str
[INET6_ADDRSTRLEN
];
463 struct zebra_if
*zif
;
468 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
470 if (len
< sizeof(struct nd_router_advert
)) {
471 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
472 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
475 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
477 "%s(%u): Rx RA with non-linklocal source address from %s",
478 ifp
->name
, ifp
->ifindex
, addr_str
);
482 radvert
= (struct nd_router_advert
*)msg
;
484 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
485 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
487 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
488 ifp
->name
, ifp
->ifindex
, addr_str
);
491 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
492 && !zif
->rtadv
.AdvManagedFlag
) {
494 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
495 ifp
->name
, ifp
->ifindex
, addr_str
);
498 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
499 && !zif
->rtadv
.AdvOtherConfigFlag
) {
501 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
502 ifp
->name
, ifp
->ifindex
, addr_str
);
505 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
506 && (ntohl(radvert
->nd_ra_reachable
)
507 != zif
->rtadv
.AdvReachableTime
)) {
509 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
510 ifp
->name
, ifp
->ifindex
, addr_str
);
513 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
514 && (ntohl(radvert
->nd_ra_retransmit
)
515 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
517 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
518 ifp
->name
, ifp
->ifindex
, addr_str
);
521 /* Create entry for neighbor if not known. */
523 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
524 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
526 if (!nbr_connected_check(ifp
, &p
))
527 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
531 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
532 ifindex_t ifindex
, int hoplimit
,
533 struct sockaddr_in6
*from
,
534 struct zebra_ns
*zns
)
536 struct icmp6_hdr
*icmph
;
537 struct interface
*ifp
;
538 struct zebra_if
*zif
;
539 char addr_str
[INET6_ADDRSTRLEN
];
541 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
543 /* Interface search. */
544 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
546 zlog_warn("RA/RS received on unknown IF %u from %s", ifindex
,
551 if (IS_ZEBRA_DEBUG_PACKET
)
552 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
553 ifp
->ifindex
, len
, addr_str
);
555 if (if_is_loopback(ifp
)
556 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
559 /* Check interface configuration. */
561 if (!zif
->rtadv
.AdvSendAdvertisements
)
564 /* ICMP message length check. */
565 if (len
< sizeof(struct icmp6_hdr
)) {
566 zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
567 ifp
->name
, ifp
->ifindex
, len
);
571 icmph
= (struct icmp6_hdr
*)buf
;
573 /* ICMP message type check. */
574 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
575 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
576 zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
577 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
581 /* Hoplimit check. */
582 if (hoplimit
>= 0 && hoplimit
!= 255) {
583 zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
584 ifp
->ifindex
, hoplimit
);
588 /* Check ICMP message type. */
589 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
590 rtadv_process_solicit(ifp
);
591 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
592 rtadv_process_advert(buf
, len
, ifp
, from
);
597 static int rtadv_read(struct thread
*thread
)
601 uint8_t buf
[RTADV_MSG_SIZE
];
602 struct sockaddr_in6 from
;
603 ifindex_t ifindex
= 0;
605 struct zebra_ns
*zns
= THREAD_ARG(thread
);
607 sock
= THREAD_FD(thread
);
608 zns
->rtadv
.ra_read
= NULL
;
610 /* Register myself. */
611 rtadv_event(zns
, RTADV_READ
, sock
);
613 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
617 zlog_warn("RA/RS recv failed, socket %u error %s", sock
,
618 safe_strerror(errno
));
622 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
627 static int rtadv_make_socket(ns_id_t ns_id
)
631 struct icmp6_filter filter
;
633 frr_elevate_privs(&zserv_privs
) {
635 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
643 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
648 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
653 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
658 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
663 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
669 ICMP6_FILTER_SETBLOCKALL(&filter
);
670 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
671 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
673 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
674 sizeof(struct icmp6_filter
));
676 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
684 static struct rtadv_prefix
*rtadv_prefix_new(void)
686 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
689 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
691 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
694 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
695 struct prefix_ipv6
*p
)
697 struct listnode
*node
;
698 struct rtadv_prefix
*rprefix
;
700 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
701 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
707 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
708 struct prefix_ipv6
*p
)
710 struct rtadv_prefix
*rprefix
;
712 rprefix
= rtadv_prefix_lookup(rplist
, p
);
716 rprefix
= rtadv_prefix_new();
717 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
718 listnode_add(rplist
, rprefix
);
723 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
725 struct rtadv_prefix
*rprefix
;
727 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
729 /* Set parameters. */
730 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
731 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
732 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
733 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
734 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
737 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
739 struct rtadv_prefix
*rprefix
;
741 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
742 if (rprefix
!= NULL
) {
743 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
744 rtadv_prefix_free(rprefix
);
750 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
751 ipv6_nd_suppress_ra_status status
)
753 struct zebra_if
*zif
;
754 struct zebra_vrf
*zvrf
;
755 struct zebra_ns
*zns
;
758 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
761 if (status
== RA_SUPPRESS
) {
762 /* RA is currently enabled */
763 if (zif
->rtadv
.AdvSendAdvertisements
) {
764 zif
->rtadv
.AdvSendAdvertisements
= 0;
765 zif
->rtadv
.AdvIntervalTimer
= 0;
766 zns
->rtadv
.adv_if_count
--;
768 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
770 if (zns
->rtadv
.adv_if_count
== 0)
771 rtadv_event(zns
, RTADV_STOP
, 0);
774 if (!zif
->rtadv
.AdvSendAdvertisements
) {
775 zif
->rtadv
.AdvSendAdvertisements
= 1;
776 zif
->rtadv
.AdvIntervalTimer
= 0;
777 zns
->rtadv
.adv_if_count
++;
779 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
780 /* Enable Fast RA only when RA interval is in
782 zif
->rtadv
.inFastRexmit
= 1;
783 zif
->rtadv
.NumFastReXmitsRemain
=
784 RTADV_NUM_FAST_REXMITS
;
787 if_join_all_router(zns
->rtadv
.sock
, ifp
);
789 if (zns
->rtadv
.adv_if_count
== 1)
790 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
796 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
797 * Note that while the client could request RA on an interface on which the
798 * operator has not enabled RA, RA won't be disabled upon client request
799 * if the operator has explicitly enabled RA. The enable request can also
800 * specify a RA interval (in seconds).
802 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
806 struct interface
*ifp
;
807 struct zebra_if
*zif
;
812 /* Get interface index and RA interval. */
813 STREAM_GETL(s
, ifindex
);
814 STREAM_GETL(s
, ra_interval
);
816 if (IS_ZEBRA_DEBUG_EVENT
)
817 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
818 zvrf_id(zvrf
), ifindex
,
819 enable
? "enable" : "disable",
820 zebra_route_string(client
->proto
), ra_interval
);
822 /* Locate interface and check VRF match. */
823 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
825 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
826 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
827 zebra_route_string(client
->proto
));
830 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
831 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
832 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
833 zebra_route_string(client
->proto
), ifp
->vrf_id
);
839 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
840 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
842 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
843 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
844 VTY_RA_INTERVAL_CONFIGURED
))
845 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
847 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
848 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
849 VTY_RA_INTERVAL_CONFIGURED
))
850 zif
->rtadv
.MaxRtrAdvInterval
=
851 RTADV_MAX_RTR_ADV_INTERVAL
;
852 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
853 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
859 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
861 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
863 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
865 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
868 DEFUN (ipv6_nd_suppress_ra
,
869 ipv6_nd_suppress_ra_cmd
,
870 "ipv6 nd suppress-ra",
871 "Interface IPv6 config commands\n"
872 "Neighbor discovery\n"
873 "Suppress Router Advertisement\n")
875 VTY_DECLVAR_CONTEXT(interface
, ifp
);
876 struct zebra_if
*zif
= ifp
->info
;
878 if (if_is_loopback(ifp
)
879 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
881 "Cannot configure IPv6 Router Advertisements on this interface\n");
882 return CMD_WARNING_CONFIG_FAILED
;
885 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
886 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
888 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
892 DEFUN (no_ipv6_nd_suppress_ra
,
893 no_ipv6_nd_suppress_ra_cmd
,
894 "no ipv6 nd suppress-ra",
896 "Interface IPv6 config commands\n"
897 "Neighbor discovery\n"
898 "Suppress Router Advertisement\n")
900 VTY_DECLVAR_CONTEXT(interface
, ifp
);
901 struct zebra_if
*zif
= ifp
->info
;
903 if (if_is_loopback(ifp
)
904 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
906 "Cannot configure IPv6 Router Advertisements on this interface\n");
907 return CMD_WARNING_CONFIG_FAILED
;
910 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
911 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
915 DEFUN (ipv6_nd_ra_interval_msec
,
916 ipv6_nd_ra_interval_msec_cmd
,
917 "ipv6 nd ra-interval msec (70-1800000)",
918 "Interface IPv6 config commands\n"
919 "Neighbor discovery\n"
920 "Router Advertisement interval\n"
921 "Router Advertisement interval in milliseconds\n"
922 "Router Advertisement interval in milliseconds\n")
925 VTY_DECLVAR_CONTEXT(interface
, ifp
);
927 struct zebra_if
*zif
= ifp
->info
;
928 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
929 struct zebra_ns
*zns
;
932 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
933 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
934 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
936 "This ra-interval would conflict with configured ra-lifetime!\n");
937 return CMD_WARNING_CONFIG_FAILED
;
940 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
941 zns
->rtadv
.adv_msec_if_count
--;
944 zns
->rtadv
.adv_msec_if_count
++;
946 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
947 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
948 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
949 zif
->rtadv
.AdvIntervalTimer
= 0;
954 DEFUN (ipv6_nd_ra_interval
,
955 ipv6_nd_ra_interval_cmd
,
956 "ipv6 nd ra-interval (1-1800)",
957 "Interface IPv6 config commands\n"
958 "Neighbor discovery\n"
959 "Router Advertisement interval\n"
960 "Router Advertisement interval in seconds\n")
963 VTY_DECLVAR_CONTEXT(interface
, ifp
);
965 struct zebra_if
*zif
= ifp
->info
;
966 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
967 struct zebra_ns
*zns
;
970 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
971 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
972 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
974 "This ra-interval would conflict with configured ra-lifetime!\n");
975 return CMD_WARNING_CONFIG_FAILED
;
978 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
979 zns
->rtadv
.adv_msec_if_count
--;
981 /* convert to milliseconds */
982 interval
= interval
* 1000;
984 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
985 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
986 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
987 zif
->rtadv
.AdvIntervalTimer
= 0;
992 DEFUN (no_ipv6_nd_ra_interval
,
993 no_ipv6_nd_ra_interval_cmd
,
994 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
996 "Interface IPv6 config commands\n"
997 "Neighbor discovery\n"
998 "Router Advertisement interval\n"
999 "Router Advertisement interval in seconds\n"
1000 "Specify millisecond router advertisement interval\n"
1001 "Router Advertisement interval in milliseconds\n")
1003 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1004 struct zebra_if
*zif
= ifp
->info
;
1005 struct zebra_vrf
*zvrf
;
1006 struct zebra_ns
*zns
;
1008 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1011 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1012 zns
->rtadv
.adv_msec_if_count
--;
1014 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1016 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1017 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1019 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1021 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1022 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1027 DEFUN (ipv6_nd_ra_lifetime
,
1028 ipv6_nd_ra_lifetime_cmd
,
1029 "ipv6 nd ra-lifetime (0-9000)",
1030 "Interface IPv6 config commands\n"
1031 "Neighbor discovery\n"
1033 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1036 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1037 struct zebra_if
*zif
= ifp
->info
;
1040 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1042 /* The value to be placed in the Router Lifetime field
1043 * of Router Advertisements sent from the interface,
1044 * in seconds. MUST be either zero or between
1045 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1046 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1048 "This ra-lifetime would conflict with configured ra-interval\n");
1049 return CMD_WARNING_CONFIG_FAILED
;
1052 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1057 DEFUN (no_ipv6_nd_ra_lifetime
,
1058 no_ipv6_nd_ra_lifetime_cmd
,
1059 "no ipv6 nd ra-lifetime [(0-9000)]",
1061 "Interface IPv6 config commands\n"
1062 "Neighbor discovery\n"
1064 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1066 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1067 struct zebra_if
*zif
= ifp
->info
;
1069 zif
->rtadv
.AdvDefaultLifetime
= -1;
1074 DEFUN (ipv6_nd_reachable_time
,
1075 ipv6_nd_reachable_time_cmd
,
1076 "ipv6 nd reachable-time (1-3600000)",
1077 "Interface IPv6 config commands\n"
1078 "Neighbor discovery\n"
1080 "Reachable time in milliseconds\n")
1083 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1084 struct zebra_if
*zif
= ifp
->info
;
1085 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1089 DEFUN (no_ipv6_nd_reachable_time
,
1090 no_ipv6_nd_reachable_time_cmd
,
1091 "no ipv6 nd reachable-time [(1-3600000)]",
1093 "Interface IPv6 config commands\n"
1094 "Neighbor discovery\n"
1096 "Reachable time in milliseconds\n")
1098 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1099 struct zebra_if
*zif
= ifp
->info
;
1101 zif
->rtadv
.AdvReachableTime
= 0;
1106 DEFUN (ipv6_nd_homeagent_preference
,
1107 ipv6_nd_homeagent_preference_cmd
,
1108 "ipv6 nd home-agent-preference (0-65535)",
1109 "Interface IPv6 config commands\n"
1110 "Neighbor discovery\n"
1111 "Home Agent preference\n"
1112 "preference value (default is 0, least preferred)\n")
1115 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1116 struct zebra_if
*zif
= ifp
->info
;
1117 zif
->rtadv
.HomeAgentPreference
=
1118 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1122 DEFUN (no_ipv6_nd_homeagent_preference
,
1123 no_ipv6_nd_homeagent_preference_cmd
,
1124 "no ipv6 nd home-agent-preference [(0-65535)]",
1126 "Interface IPv6 config commands\n"
1127 "Neighbor discovery\n"
1128 "Home Agent preference\n"
1129 "preference value (default is 0, least preferred)\n")
1131 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1132 struct zebra_if
*zif
= ifp
->info
;
1134 zif
->rtadv
.HomeAgentPreference
= 0;
1139 DEFUN (ipv6_nd_homeagent_lifetime
,
1140 ipv6_nd_homeagent_lifetime_cmd
,
1141 "ipv6 nd home-agent-lifetime (0-65520)",
1142 "Interface IPv6 config commands\n"
1143 "Neighbor discovery\n"
1144 "Home Agent lifetime\n"
1145 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1148 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1149 struct zebra_if
*zif
= ifp
->info
;
1150 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1154 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1155 no_ipv6_nd_homeagent_lifetime_cmd
,
1156 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1158 "Interface IPv6 config commands\n"
1159 "Neighbor discovery\n"
1160 "Home Agent lifetime\n"
1161 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1163 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1164 struct zebra_if
*zif
= ifp
->info
;
1166 zif
->rtadv
.HomeAgentLifetime
= -1;
1171 DEFUN (ipv6_nd_managed_config_flag
,
1172 ipv6_nd_managed_config_flag_cmd
,
1173 "ipv6 nd managed-config-flag",
1174 "Interface IPv6 config commands\n"
1175 "Neighbor discovery\n"
1176 "Managed address configuration flag\n")
1178 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1179 struct zebra_if
*zif
= ifp
->info
;
1181 zif
->rtadv
.AdvManagedFlag
= 1;
1186 DEFUN (no_ipv6_nd_managed_config_flag
,
1187 no_ipv6_nd_managed_config_flag_cmd
,
1188 "no ipv6 nd managed-config-flag",
1190 "Interface IPv6 config commands\n"
1191 "Neighbor discovery\n"
1192 "Managed address configuration flag\n")
1194 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1195 struct zebra_if
*zif
= ifp
->info
;
1197 zif
->rtadv
.AdvManagedFlag
= 0;
1202 DEFUN (ipv6_nd_homeagent_config_flag
,
1203 ipv6_nd_homeagent_config_flag_cmd
,
1204 "ipv6 nd home-agent-config-flag",
1205 "Interface IPv6 config commands\n"
1206 "Neighbor discovery\n"
1207 "Home Agent configuration flag\n")
1209 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1210 struct zebra_if
*zif
= ifp
->info
;
1212 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1217 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1218 no_ipv6_nd_homeagent_config_flag_cmd
,
1219 "no ipv6 nd home-agent-config-flag",
1221 "Interface IPv6 config commands\n"
1222 "Neighbor discovery\n"
1223 "Home Agent configuration flag\n")
1225 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1226 struct zebra_if
*zif
= ifp
->info
;
1228 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1233 DEFUN (ipv6_nd_adv_interval_config_option
,
1234 ipv6_nd_adv_interval_config_option_cmd
,
1235 "ipv6 nd adv-interval-option",
1236 "Interface IPv6 config commands\n"
1237 "Neighbor discovery\n"
1238 "Advertisement Interval Option\n")
1240 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1241 struct zebra_if
*zif
= ifp
->info
;
1243 zif
->rtadv
.AdvIntervalOption
= 1;
1248 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1249 no_ipv6_nd_adv_interval_config_option_cmd
,
1250 "no ipv6 nd adv-interval-option",
1252 "Interface IPv6 config commands\n"
1253 "Neighbor discovery\n"
1254 "Advertisement Interval Option\n")
1256 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1257 struct zebra_if
*zif
= ifp
->info
;
1259 zif
->rtadv
.AdvIntervalOption
= 0;
1264 DEFUN (ipv6_nd_other_config_flag
,
1265 ipv6_nd_other_config_flag_cmd
,
1266 "ipv6 nd other-config-flag",
1267 "Interface IPv6 config commands\n"
1268 "Neighbor discovery\n"
1269 "Other statefull configuration flag\n")
1271 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1272 struct zebra_if
*zif
= ifp
->info
;
1274 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1279 DEFUN (no_ipv6_nd_other_config_flag
,
1280 no_ipv6_nd_other_config_flag_cmd
,
1281 "no ipv6 nd other-config-flag",
1283 "Interface IPv6 config commands\n"
1284 "Neighbor discovery\n"
1285 "Other statefull configuration flag\n")
1287 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1288 struct zebra_if
*zif
= ifp
->info
;
1290 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1295 DEFUN (ipv6_nd_prefix
,
1297 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1298 "Interface IPv6 config commands\n"
1299 "Neighbor discovery\n"
1300 "Prefix information\n"
1302 "Valid lifetime in seconds\n"
1303 "Infinite valid lifetime\n"
1304 "Preferred lifetime in seconds\n"
1305 "Infinite preferred lifetime\n"
1306 "Set Router Address flag\n"
1307 "Do not use prefix for onlink determination\n"
1308 "Do not use prefix for autoconfiguration\n"
1309 "Do not use prefix for autoconfiguration\n"
1310 "Do not use prefix for onlink determination\n")
1313 char *prefix
= argv
[3]->arg
;
1314 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1315 || strmatch(argv
[4]->text
, "infinite"));
1316 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1318 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1320 char *lifetime
= NULL
, *preflifetime
= NULL
;
1321 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1323 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1325 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1330 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1332 offlink
= (argc
> idx_routeropts
+ 1
1333 || strmatch(argv
[idx_routeropts
]->text
,
1335 noautoconf
= (argc
> idx_routeropts
+ 1
1336 || strmatch(argv
[idx_routeropts
]->text
,
1342 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1343 struct zebra_if
*zebra_if
= ifp
->info
;
1345 struct rtadv_prefix rp
;
1347 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1349 vty_out(vty
, "Malformed IPv6 prefix\n");
1350 return CMD_WARNING_CONFIG_FAILED
;
1352 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1353 rp
.AdvOnLinkFlag
= !offlink
;
1354 rp
.AdvAutonomousFlag
= !noautoconf
;
1355 rp
.AdvRouterAddressFlag
= routeraddr
;
1356 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1357 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1360 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1362 : strtoll(lifetime
, NULL
, 10);
1363 rp
.AdvPreferredLifetime
=
1364 strmatch(preflifetime
, "infinite")
1366 : strtoll(preflifetime
, NULL
, 10);
1367 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1368 vty_out(vty
, "Invalid preferred lifetime\n");
1369 return CMD_WARNING_CONFIG_FAILED
;
1373 rtadv_prefix_set(zebra_if
, &rp
);
1378 DEFUN (no_ipv6_nd_prefix
,
1379 no_ipv6_nd_prefix_cmd
,
1380 "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]>]",
1382 "Interface IPv6 config commands\n"
1383 "Neighbor discovery\n"
1384 "Prefix information\n"
1386 "Valid lifetime in seconds\n"
1387 "Infinite valid lifetime\n"
1388 "Preferred lifetime in seconds\n"
1389 "Infinite preferred lifetime\n"
1390 "Set Router Address flag\n"
1391 "Do not use prefix for onlink determination\n"
1392 "Do not use prefix for autoconfiguration\n"
1393 "Do not use prefix for autoconfiguration\n"
1394 "Do not use prefix for onlink determination\n")
1396 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1397 struct zebra_if
*zebra_if
= ifp
->info
;
1399 struct rtadv_prefix rp
;
1400 char *prefix
= argv
[4]->arg
;
1402 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1404 vty_out(vty
, "Malformed IPv6 prefix\n");
1405 return CMD_WARNING_CONFIG_FAILED
;
1407 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1409 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1411 vty_out(vty
, "Non-existant IPv6 prefix\n");
1412 return CMD_WARNING_CONFIG_FAILED
;
1418 DEFUN (ipv6_nd_router_preference
,
1419 ipv6_nd_router_preference_cmd
,
1420 "ipv6 nd router-preference <high|medium|low>",
1421 "Interface IPv6 config commands\n"
1422 "Neighbor discovery\n"
1423 "Default router preference\n"
1424 "High default router preference\n"
1425 "Medium default router preference (default)\n"
1426 "Low default router preference\n")
1428 int idx_high_medium_low
= 3;
1429 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1430 struct zebra_if
*zif
= ifp
->info
;
1433 while (0 != rtadv_pref_strs
[i
]) {
1434 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1437 zif
->rtadv
.DefaultPreference
= i
;
1443 return CMD_ERR_NO_MATCH
;
1446 DEFUN (no_ipv6_nd_router_preference
,
1447 no_ipv6_nd_router_preference_cmd
,
1448 "no ipv6 nd router-preference [<high|medium|low>]",
1450 "Interface IPv6 config commands\n"
1451 "Neighbor discovery\n"
1452 "Default router preference\n"
1453 "High default router preference\n"
1454 "Medium default router preference (default)\n"
1455 "Low default router preference\n")
1457 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1458 struct zebra_if
*zif
= ifp
->info
;
1460 zif
->rtadv
.DefaultPreference
=
1461 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1468 "ipv6 nd mtu (1-65535)",
1469 "Interface IPv6 config commands\n"
1470 "Neighbor discovery\n"
1475 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1476 struct zebra_if
*zif
= ifp
->info
;
1477 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1481 DEFUN (no_ipv6_nd_mtu
,
1483 "no ipv6 nd mtu [(1-65535)]",
1485 "Interface IPv6 config commands\n"
1486 "Neighbor discovery\n"
1490 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1491 struct zebra_if
*zif
= ifp
->info
;
1492 zif
->rtadv
.AdvLinkMTU
= 0;
1496 /* Dump interface ND information to vty. */
1497 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1499 struct zebra_if
*zif
;
1500 struct rtadvconf
*rtadv
;
1503 zif
= (struct zebra_if
*)ifp
->info
;
1504 rtadv
= &zif
->rtadv
;
1506 if (rtadv
->AdvSendAdvertisements
) {
1508 " ND advertised reachable time is %d milliseconds\n",
1509 rtadv
->AdvReachableTime
);
1511 " ND advertised retransmit interval is %d milliseconds\n",
1512 rtadv
->AdvRetransTimer
);
1513 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1514 zif
->ra_sent
, zif
->ra_rcvd
);
1515 interval
= rtadv
->MaxRtrAdvInterval
;
1516 if (interval
% 1000)
1518 " ND router advertisements are sent every "
1519 "%d milliseconds\n",
1523 " ND router advertisements are sent every "
1526 if (rtadv
->AdvDefaultLifetime
!= -1)
1528 " ND router advertisements live for %d seconds\n",
1529 rtadv
->AdvDefaultLifetime
);
1532 " ND router advertisements lifetime tracks ra-interval\n");
1534 " ND router advertisement default router preference is "
1536 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1537 if (rtadv
->AdvManagedFlag
)
1539 " Hosts use DHCP to obtain routable addresses.\n");
1542 " Hosts use stateless autoconfig for addresses.\n");
1543 if (rtadv
->AdvHomeAgentFlag
) {
1545 " ND router advertisements with Home Agent flag bit set.\n");
1546 if (rtadv
->HomeAgentLifetime
!= -1)
1548 " Home Agent lifetime is %u seconds\n",
1549 rtadv
->HomeAgentLifetime
);
1552 " Home Agent lifetime tracks ra-lifetime\n");
1553 vty_out(vty
, " Home Agent preference is %u\n",
1554 rtadv
->HomeAgentPreference
);
1556 if (rtadv
->AdvIntervalOption
)
1558 " ND router advertisements with Adv. Interval option.\n");
1564 /* Write configuration about router advertisement. */
1565 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1567 struct zebra_if
*zif
;
1568 struct listnode
*node
;
1569 struct rtadv_prefix
*rprefix
;
1570 char buf
[PREFIX_STRLEN
];
1575 if (!(if_is_loopback(ifp
)
1576 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1577 if (zif
->rtadv
.AdvSendAdvertisements
1578 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1579 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1582 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1583 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
1584 if (interval
% 1000)
1585 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
1587 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1588 vty_out(vty
, " ipv6 nd ra-interval %d\n",
1592 if (zif
->rtadv
.AdvIntervalOption
)
1593 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1595 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1596 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1597 zif
->rtadv
.AdvDefaultLifetime
);
1599 if (zif
->rtadv
.HomeAgentPreference
)
1600 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1601 zif
->rtadv
.HomeAgentPreference
);
1603 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1604 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1605 zif
->rtadv
.HomeAgentLifetime
);
1607 if (zif
->rtadv
.AdvHomeAgentFlag
)
1608 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1610 if (zif
->rtadv
.AdvReachableTime
)
1611 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1612 zif
->rtadv
.AdvReachableTime
);
1614 if (zif
->rtadv
.AdvManagedFlag
)
1615 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1617 if (zif
->rtadv
.AdvOtherConfigFlag
)
1618 vty_out(vty
, " ipv6 nd other-config-flag\n");
1620 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1621 vty_out(vty
, " ipv6 nd router-preference %s\n",
1622 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1624 if (zif
->rtadv
.AdvLinkMTU
)
1625 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1627 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1628 vty_out(vty
, " ipv6 nd prefix %s",
1629 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1630 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1631 || (rprefix
->AdvPreferredLifetime
1632 != RTADV_PREFERRED_LIFETIME
)) {
1633 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1634 vty_out(vty
, " infinite");
1636 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1637 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1638 vty_out(vty
, " infinite");
1641 rprefix
->AdvPreferredLifetime
);
1643 if (!rprefix
->AdvOnLinkFlag
)
1644 vty_out(vty
, " off-link");
1645 if (!rprefix
->AdvAutonomousFlag
)
1646 vty_out(vty
, " no-autoconfig");
1647 if (rprefix
->AdvRouterAddressFlag
)
1648 vty_out(vty
, " router-address");
1655 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1657 struct rtadv
*rtadv
= &zns
->rtadv
;
1661 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1663 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1667 if (rtadv
->ra_timer
) {
1668 thread_cancel(rtadv
->ra_timer
);
1669 rtadv
->ra_timer
= NULL
;
1671 if (rtadv
->ra_read
) {
1672 thread_cancel(rtadv
->ra_read
);
1673 rtadv
->ra_read
= NULL
;
1677 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1680 case RTADV_TIMER_MSEC
:
1681 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1685 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1694 void rtadv_init(struct zebra_ns
*zns
)
1696 zns
->rtadv
.sock
= rtadv_make_socket(zns
->ns_id
);
1699 void rtadv_terminate(struct zebra_ns
*zns
)
1701 rtadv_event(zns
, RTADV_STOP
, 0);
1702 if (zns
->rtadv
.sock
>= 0) {
1703 close(zns
->rtadv
.sock
);
1704 zns
->rtadv
.sock
= -1;
1707 zns
->rtadv
.adv_if_count
= 0;
1708 zns
->rtadv
.adv_msec_if_count
= 0;
1711 void rtadv_cmd_init(void)
1713 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1714 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1716 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1717 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1718 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1719 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1720 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1721 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1722 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1723 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1724 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1725 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1726 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1727 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1728 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1729 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1730 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1731 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1732 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1733 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1734 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1735 install_element(INTERFACE_NODE
,
1736 &ipv6_nd_adv_interval_config_option_cmd
);
1737 install_element(INTERFACE_NODE
,
1738 &no_ipv6_nd_adv_interval_config_option_cmd
);
1739 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1740 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1741 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1742 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1743 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1744 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1747 static int if_join_all_router(int sock
, struct interface
*ifp
)
1751 struct ipv6_mreq mreq
;
1753 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1754 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1755 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1757 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1760 zlog_warn("%s(%u): Failed to join group, socket %u error %s",
1761 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1763 if (IS_ZEBRA_DEBUG_EVENT
)
1765 "%s(%u): Join All-Routers multicast group, socket %u",
1766 ifp
->name
, ifp
->ifindex
, sock
);
1771 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1775 struct ipv6_mreq mreq
;
1777 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1778 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1779 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1781 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1784 zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
1785 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1787 if (IS_ZEBRA_DEBUG_EVENT
)
1789 "%s(%u): Leave All-Routers multicast group, socket %u",
1790 ifp
->name
, ifp
->ifindex
, sock
);
1796 void rtadv_init(struct zebra_ns
*zns
)
1800 void rtadv_terminate(struct zebra_ns
*zns
)
1804 void rtadv_cmd_init(void)
1808 #endif /* HAVE_RTADV */