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 if (zserv_privs
.change(ZPRIVS_RAISE
))
634 flog_err(LIB_ERR_PRIVILEGES
,
635 "rtadv_make_socket: could not raise privs, %s",
636 safe_strerror(errno
));
638 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
640 if (zserv_privs
.change(ZPRIVS_LOWER
))
641 flog_err(LIB_ERR_PRIVILEGES
,
642 "rtadv_make_socket: could not lower privs, %s",
643 safe_strerror(errno
));
649 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
654 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
659 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
664 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
669 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
675 ICMP6_FILTER_SETBLOCKALL(&filter
);
676 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
677 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
679 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
680 sizeof(struct icmp6_filter
));
682 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
690 static struct rtadv_prefix
*rtadv_prefix_new(void)
692 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
695 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
697 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
700 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
701 struct prefix_ipv6
*p
)
703 struct listnode
*node
;
704 struct rtadv_prefix
*rprefix
;
706 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
707 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
713 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
714 struct prefix_ipv6
*p
)
716 struct rtadv_prefix
*rprefix
;
718 rprefix
= rtadv_prefix_lookup(rplist
, p
);
722 rprefix
= rtadv_prefix_new();
723 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
724 listnode_add(rplist
, rprefix
);
729 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
731 struct rtadv_prefix
*rprefix
;
733 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
735 /* Set parameters. */
736 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
737 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
738 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
739 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
740 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
743 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
745 struct rtadv_prefix
*rprefix
;
747 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
748 if (rprefix
!= NULL
) {
749 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
750 rtadv_prefix_free(rprefix
);
756 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
757 ipv6_nd_suppress_ra_status status
)
759 struct zebra_if
*zif
;
760 struct zebra_vrf
*zvrf
;
761 struct zebra_ns
*zns
;
764 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
767 if (status
== RA_SUPPRESS
) {
768 /* RA is currently enabled */
769 if (zif
->rtadv
.AdvSendAdvertisements
) {
770 zif
->rtadv
.AdvSendAdvertisements
= 0;
771 zif
->rtadv
.AdvIntervalTimer
= 0;
772 zns
->rtadv
.adv_if_count
--;
774 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
776 if (zns
->rtadv
.adv_if_count
== 0)
777 rtadv_event(zns
, RTADV_STOP
, 0);
780 if (!zif
->rtadv
.AdvSendAdvertisements
) {
781 zif
->rtadv
.AdvSendAdvertisements
= 1;
782 zif
->rtadv
.AdvIntervalTimer
= 0;
783 zns
->rtadv
.adv_if_count
++;
785 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
786 /* Enable Fast RA only when RA interval is in
788 zif
->rtadv
.inFastRexmit
= 1;
789 zif
->rtadv
.NumFastReXmitsRemain
=
790 RTADV_NUM_FAST_REXMITS
;
793 if_join_all_router(zns
->rtadv
.sock
, ifp
);
795 if (zns
->rtadv
.adv_if_count
== 1)
796 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
802 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
803 * Note that while the client could request RA on an interface on which the
804 * operator has not enabled RA, RA won't be disabled upon client request
805 * if the operator has explicitly enabled RA. The enable request can also
806 * specify a RA interval (in seconds).
808 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
812 struct interface
*ifp
;
813 struct zebra_if
*zif
;
818 /* Get interface index and RA interval. */
819 STREAM_GETL(s
, ifindex
);
820 STREAM_GETL(s
, ra_interval
);
822 if (IS_ZEBRA_DEBUG_EVENT
)
823 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
824 zvrf_id(zvrf
), ifindex
,
825 enable
? "enable" : "disable",
826 zebra_route_string(client
->proto
), ra_interval
);
828 /* Locate interface and check VRF match. */
829 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
831 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
832 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
833 zebra_route_string(client
->proto
));
836 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
837 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
838 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
839 zebra_route_string(client
->proto
), ifp
->vrf_id
);
845 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
846 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
848 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
849 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
850 VTY_RA_INTERVAL_CONFIGURED
))
851 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
853 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
854 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
855 VTY_RA_INTERVAL_CONFIGURED
))
856 zif
->rtadv
.MaxRtrAdvInterval
=
857 RTADV_MAX_RTR_ADV_INTERVAL
;
858 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
859 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
865 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
867 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
869 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
871 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
874 DEFUN (ipv6_nd_suppress_ra
,
875 ipv6_nd_suppress_ra_cmd
,
876 "ipv6 nd suppress-ra",
877 "Interface IPv6 config commands\n"
878 "Neighbor discovery\n"
879 "Suppress Router Advertisement\n")
881 VTY_DECLVAR_CONTEXT(interface
, ifp
);
882 struct zebra_if
*zif
= ifp
->info
;
884 if (if_is_loopback(ifp
)
885 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
887 "Cannot configure IPv6 Router Advertisements on this interface\n");
888 return CMD_WARNING_CONFIG_FAILED
;
891 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
892 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
894 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
898 DEFUN (no_ipv6_nd_suppress_ra
,
899 no_ipv6_nd_suppress_ra_cmd
,
900 "no ipv6 nd suppress-ra",
902 "Interface IPv6 config commands\n"
903 "Neighbor discovery\n"
904 "Suppress Router Advertisement\n")
906 VTY_DECLVAR_CONTEXT(interface
, ifp
);
907 struct zebra_if
*zif
= ifp
->info
;
909 if (if_is_loopback(ifp
)
910 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
912 "Cannot configure IPv6 Router Advertisements on this interface\n");
913 return CMD_WARNING_CONFIG_FAILED
;
916 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
917 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
921 DEFUN (ipv6_nd_ra_interval_msec
,
922 ipv6_nd_ra_interval_msec_cmd
,
923 "ipv6 nd ra-interval msec (70-1800000)",
924 "Interface IPv6 config commands\n"
925 "Neighbor discovery\n"
926 "Router Advertisement interval\n"
927 "Router Advertisement interval in milliseconds\n"
928 "Router Advertisement interval in milliseconds\n")
931 VTY_DECLVAR_CONTEXT(interface
, ifp
);
933 struct zebra_if
*zif
= ifp
->info
;
934 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
935 struct zebra_ns
*zns
;
938 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
939 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
940 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
942 "This ra-interval would conflict with configured ra-lifetime!\n");
943 return CMD_WARNING_CONFIG_FAILED
;
946 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
947 zns
->rtadv
.adv_msec_if_count
--;
950 zns
->rtadv
.adv_msec_if_count
++;
952 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
953 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
954 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
955 zif
->rtadv
.AdvIntervalTimer
= 0;
960 DEFUN (ipv6_nd_ra_interval
,
961 ipv6_nd_ra_interval_cmd
,
962 "ipv6 nd ra-interval (1-1800)",
963 "Interface IPv6 config commands\n"
964 "Neighbor discovery\n"
965 "Router Advertisement interval\n"
966 "Router Advertisement interval in seconds\n")
969 VTY_DECLVAR_CONTEXT(interface
, ifp
);
971 struct zebra_if
*zif
= ifp
->info
;
972 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
973 struct zebra_ns
*zns
;
976 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
977 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
978 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
980 "This ra-interval would conflict with configured ra-lifetime!\n");
981 return CMD_WARNING_CONFIG_FAILED
;
984 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
985 zns
->rtadv
.adv_msec_if_count
--;
987 /* convert to milliseconds */
988 interval
= interval
* 1000;
990 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
991 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
992 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
993 zif
->rtadv
.AdvIntervalTimer
= 0;
998 DEFUN (no_ipv6_nd_ra_interval
,
999 no_ipv6_nd_ra_interval_cmd
,
1000 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1002 "Interface IPv6 config commands\n"
1003 "Neighbor discovery\n"
1004 "Router Advertisement interval\n"
1005 "Router Advertisement interval in seconds\n"
1006 "Specify millisecond router advertisement interval\n"
1007 "Router Advertisement interval in milliseconds\n")
1009 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1010 struct zebra_if
*zif
= ifp
->info
;
1011 struct zebra_vrf
*zvrf
;
1012 struct zebra_ns
*zns
;
1014 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1017 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1018 zns
->rtadv
.adv_msec_if_count
--;
1020 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1022 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1023 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1025 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1027 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1028 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1033 DEFUN (ipv6_nd_ra_lifetime
,
1034 ipv6_nd_ra_lifetime_cmd
,
1035 "ipv6 nd ra-lifetime (0-9000)",
1036 "Interface IPv6 config commands\n"
1037 "Neighbor discovery\n"
1039 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1042 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1043 struct zebra_if
*zif
= ifp
->info
;
1046 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1048 /* The value to be placed in the Router Lifetime field
1049 * of Router Advertisements sent from the interface,
1050 * in seconds. MUST be either zero or between
1051 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1052 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1054 "This ra-lifetime would conflict with configured ra-interval\n");
1055 return CMD_WARNING_CONFIG_FAILED
;
1058 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1063 DEFUN (no_ipv6_nd_ra_lifetime
,
1064 no_ipv6_nd_ra_lifetime_cmd
,
1065 "no ipv6 nd ra-lifetime [(0-9000)]",
1067 "Interface IPv6 config commands\n"
1068 "Neighbor discovery\n"
1070 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1072 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1073 struct zebra_if
*zif
= ifp
->info
;
1075 zif
->rtadv
.AdvDefaultLifetime
= -1;
1080 DEFUN (ipv6_nd_reachable_time
,
1081 ipv6_nd_reachable_time_cmd
,
1082 "ipv6 nd reachable-time (1-3600000)",
1083 "Interface IPv6 config commands\n"
1084 "Neighbor discovery\n"
1086 "Reachable time in milliseconds\n")
1089 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1090 struct zebra_if
*zif
= ifp
->info
;
1091 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1095 DEFUN (no_ipv6_nd_reachable_time
,
1096 no_ipv6_nd_reachable_time_cmd
,
1097 "no ipv6 nd reachable-time [(1-3600000)]",
1099 "Interface IPv6 config commands\n"
1100 "Neighbor discovery\n"
1102 "Reachable time in milliseconds\n")
1104 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1105 struct zebra_if
*zif
= ifp
->info
;
1107 zif
->rtadv
.AdvReachableTime
= 0;
1112 DEFUN (ipv6_nd_homeagent_preference
,
1113 ipv6_nd_homeagent_preference_cmd
,
1114 "ipv6 nd home-agent-preference (0-65535)",
1115 "Interface IPv6 config commands\n"
1116 "Neighbor discovery\n"
1117 "Home Agent preference\n"
1118 "preference value (default is 0, least preferred)\n")
1121 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1122 struct zebra_if
*zif
= ifp
->info
;
1123 zif
->rtadv
.HomeAgentPreference
=
1124 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1128 DEFUN (no_ipv6_nd_homeagent_preference
,
1129 no_ipv6_nd_homeagent_preference_cmd
,
1130 "no ipv6 nd home-agent-preference [(0-65535)]",
1132 "Interface IPv6 config commands\n"
1133 "Neighbor discovery\n"
1134 "Home Agent preference\n"
1135 "preference value (default is 0, least preferred)\n")
1137 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1138 struct zebra_if
*zif
= ifp
->info
;
1140 zif
->rtadv
.HomeAgentPreference
= 0;
1145 DEFUN (ipv6_nd_homeagent_lifetime
,
1146 ipv6_nd_homeagent_lifetime_cmd
,
1147 "ipv6 nd home-agent-lifetime (0-65520)",
1148 "Interface IPv6 config commands\n"
1149 "Neighbor discovery\n"
1150 "Home Agent lifetime\n"
1151 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1154 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1155 struct zebra_if
*zif
= ifp
->info
;
1156 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1160 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1161 no_ipv6_nd_homeagent_lifetime_cmd
,
1162 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1164 "Interface IPv6 config commands\n"
1165 "Neighbor discovery\n"
1166 "Home Agent lifetime\n"
1167 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1169 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1170 struct zebra_if
*zif
= ifp
->info
;
1172 zif
->rtadv
.HomeAgentLifetime
= -1;
1177 DEFUN (ipv6_nd_managed_config_flag
,
1178 ipv6_nd_managed_config_flag_cmd
,
1179 "ipv6 nd managed-config-flag",
1180 "Interface IPv6 config commands\n"
1181 "Neighbor discovery\n"
1182 "Managed address configuration flag\n")
1184 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1185 struct zebra_if
*zif
= ifp
->info
;
1187 zif
->rtadv
.AdvManagedFlag
= 1;
1192 DEFUN (no_ipv6_nd_managed_config_flag
,
1193 no_ipv6_nd_managed_config_flag_cmd
,
1194 "no ipv6 nd managed-config-flag",
1196 "Interface IPv6 config commands\n"
1197 "Neighbor discovery\n"
1198 "Managed address configuration flag\n")
1200 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1201 struct zebra_if
*zif
= ifp
->info
;
1203 zif
->rtadv
.AdvManagedFlag
= 0;
1208 DEFUN (ipv6_nd_homeagent_config_flag
,
1209 ipv6_nd_homeagent_config_flag_cmd
,
1210 "ipv6 nd home-agent-config-flag",
1211 "Interface IPv6 config commands\n"
1212 "Neighbor discovery\n"
1213 "Home Agent configuration flag\n")
1215 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1216 struct zebra_if
*zif
= ifp
->info
;
1218 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1223 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1224 no_ipv6_nd_homeagent_config_flag_cmd
,
1225 "no ipv6 nd home-agent-config-flag",
1227 "Interface IPv6 config commands\n"
1228 "Neighbor discovery\n"
1229 "Home Agent configuration flag\n")
1231 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1232 struct zebra_if
*zif
= ifp
->info
;
1234 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1239 DEFUN (ipv6_nd_adv_interval_config_option
,
1240 ipv6_nd_adv_interval_config_option_cmd
,
1241 "ipv6 nd adv-interval-option",
1242 "Interface IPv6 config commands\n"
1243 "Neighbor discovery\n"
1244 "Advertisement Interval Option\n")
1246 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1247 struct zebra_if
*zif
= ifp
->info
;
1249 zif
->rtadv
.AdvIntervalOption
= 1;
1254 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1255 no_ipv6_nd_adv_interval_config_option_cmd
,
1256 "no ipv6 nd adv-interval-option",
1258 "Interface IPv6 config commands\n"
1259 "Neighbor discovery\n"
1260 "Advertisement Interval Option\n")
1262 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1263 struct zebra_if
*zif
= ifp
->info
;
1265 zif
->rtadv
.AdvIntervalOption
= 0;
1270 DEFUN (ipv6_nd_other_config_flag
,
1271 ipv6_nd_other_config_flag_cmd
,
1272 "ipv6 nd other-config-flag",
1273 "Interface IPv6 config commands\n"
1274 "Neighbor discovery\n"
1275 "Other statefull configuration flag\n")
1277 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1278 struct zebra_if
*zif
= ifp
->info
;
1280 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1285 DEFUN (no_ipv6_nd_other_config_flag
,
1286 no_ipv6_nd_other_config_flag_cmd
,
1287 "no ipv6 nd other-config-flag",
1289 "Interface IPv6 config commands\n"
1290 "Neighbor discovery\n"
1291 "Other statefull configuration flag\n")
1293 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1294 struct zebra_if
*zif
= ifp
->info
;
1296 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1301 DEFUN (ipv6_nd_prefix
,
1303 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1304 "Interface IPv6 config commands\n"
1305 "Neighbor discovery\n"
1306 "Prefix information\n"
1308 "Valid lifetime in seconds\n"
1309 "Infinite valid lifetime\n"
1310 "Preferred lifetime in seconds\n"
1311 "Infinite preferred lifetime\n"
1312 "Set Router Address flag\n"
1313 "Do not use prefix for onlink determination\n"
1314 "Do not use prefix for autoconfiguration\n"
1315 "Do not use prefix for autoconfiguration\n"
1316 "Do not use prefix for onlink determination\n")
1319 char *prefix
= argv
[3]->arg
;
1320 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1321 || strmatch(argv
[4]->text
, "infinite"));
1322 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1324 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1326 char *lifetime
= NULL
, *preflifetime
= NULL
;
1327 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1329 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1331 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1336 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1338 offlink
= (argc
> idx_routeropts
+ 1
1339 || strmatch(argv
[idx_routeropts
]->text
,
1341 noautoconf
= (argc
> idx_routeropts
+ 1
1342 || strmatch(argv
[idx_routeropts
]->text
,
1348 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1349 struct zebra_if
*zebra_if
= ifp
->info
;
1351 struct rtadv_prefix rp
;
1353 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1355 vty_out(vty
, "Malformed IPv6 prefix\n");
1356 return CMD_WARNING_CONFIG_FAILED
;
1358 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1359 rp
.AdvOnLinkFlag
= !offlink
;
1360 rp
.AdvAutonomousFlag
= !noautoconf
;
1361 rp
.AdvRouterAddressFlag
= routeraddr
;
1362 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1363 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1366 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1368 : strtoll(lifetime
, NULL
, 10);
1369 rp
.AdvPreferredLifetime
=
1370 strmatch(preflifetime
, "infinite")
1372 : strtoll(preflifetime
, NULL
, 10);
1373 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1374 vty_out(vty
, "Invalid preferred lifetime\n");
1375 return CMD_WARNING_CONFIG_FAILED
;
1379 rtadv_prefix_set(zebra_if
, &rp
);
1384 DEFUN (no_ipv6_nd_prefix
,
1385 no_ipv6_nd_prefix_cmd
,
1386 "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]>]",
1388 "Interface IPv6 config commands\n"
1389 "Neighbor discovery\n"
1390 "Prefix information\n"
1392 "Valid lifetime in seconds\n"
1393 "Infinite valid lifetime\n"
1394 "Preferred lifetime in seconds\n"
1395 "Infinite preferred lifetime\n"
1396 "Set Router Address flag\n"
1397 "Do not use prefix for onlink determination\n"
1398 "Do not use prefix for autoconfiguration\n"
1399 "Do not use prefix for autoconfiguration\n"
1400 "Do not use prefix for onlink determination\n")
1402 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1403 struct zebra_if
*zebra_if
= ifp
->info
;
1405 struct rtadv_prefix rp
;
1406 char *prefix
= argv
[4]->arg
;
1408 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1410 vty_out(vty
, "Malformed IPv6 prefix\n");
1411 return CMD_WARNING_CONFIG_FAILED
;
1413 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1415 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1417 vty_out(vty
, "Non-existant IPv6 prefix\n");
1418 return CMD_WARNING_CONFIG_FAILED
;
1424 DEFUN (ipv6_nd_router_preference
,
1425 ipv6_nd_router_preference_cmd
,
1426 "ipv6 nd router-preference <high|medium|low>",
1427 "Interface IPv6 config commands\n"
1428 "Neighbor discovery\n"
1429 "Default router preference\n"
1430 "High default router preference\n"
1431 "Medium default router preference (default)\n"
1432 "Low default router preference\n")
1434 int idx_high_medium_low
= 3;
1435 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1436 struct zebra_if
*zif
= ifp
->info
;
1439 while (0 != rtadv_pref_strs
[i
]) {
1440 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1443 zif
->rtadv
.DefaultPreference
= i
;
1449 return CMD_ERR_NO_MATCH
;
1452 DEFUN (no_ipv6_nd_router_preference
,
1453 no_ipv6_nd_router_preference_cmd
,
1454 "no ipv6 nd router-preference [<high|medium|low>]",
1456 "Interface IPv6 config commands\n"
1457 "Neighbor discovery\n"
1458 "Default router preference\n"
1459 "High default router preference\n"
1460 "Medium default router preference (default)\n"
1461 "Low default router preference\n")
1463 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1464 struct zebra_if
*zif
= ifp
->info
;
1466 zif
->rtadv
.DefaultPreference
=
1467 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1474 "ipv6 nd mtu (1-65535)",
1475 "Interface IPv6 config commands\n"
1476 "Neighbor discovery\n"
1481 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1482 struct zebra_if
*zif
= ifp
->info
;
1483 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1487 DEFUN (no_ipv6_nd_mtu
,
1489 "no ipv6 nd mtu [(1-65535)]",
1491 "Interface IPv6 config commands\n"
1492 "Neighbor discovery\n"
1496 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1497 struct zebra_if
*zif
= ifp
->info
;
1498 zif
->rtadv
.AdvLinkMTU
= 0;
1502 /* Dump interface ND information to vty. */
1503 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1505 struct zebra_if
*zif
;
1506 struct rtadvconf
*rtadv
;
1509 zif
= (struct zebra_if
*)ifp
->info
;
1510 rtadv
= &zif
->rtadv
;
1512 if (rtadv
->AdvSendAdvertisements
) {
1514 " ND advertised reachable time is %d milliseconds\n",
1515 rtadv
->AdvReachableTime
);
1517 " ND advertised retransmit interval is %d milliseconds\n",
1518 rtadv
->AdvRetransTimer
);
1519 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1520 zif
->ra_sent
, zif
->ra_rcvd
);
1521 interval
= rtadv
->MaxRtrAdvInterval
;
1522 if (interval
% 1000)
1524 " ND router advertisements are sent every "
1525 "%d milliseconds\n",
1529 " ND router advertisements are sent every "
1532 if (rtadv
->AdvDefaultLifetime
!= -1)
1534 " ND router advertisements live for %d seconds\n",
1535 rtadv
->AdvDefaultLifetime
);
1538 " ND router advertisements lifetime tracks ra-interval\n");
1540 " ND router advertisement default router preference is "
1542 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1543 if (rtadv
->AdvManagedFlag
)
1545 " Hosts use DHCP to obtain routable addresses.\n");
1548 " Hosts use stateless autoconfig for addresses.\n");
1549 if (rtadv
->AdvHomeAgentFlag
) {
1551 " ND router advertisements with Home Agent flag bit set.\n");
1552 if (rtadv
->HomeAgentLifetime
!= -1)
1554 " Home Agent lifetime is %u seconds\n",
1555 rtadv
->HomeAgentLifetime
);
1558 " Home Agent lifetime tracks ra-lifetime\n");
1559 vty_out(vty
, " Home Agent preference is %u\n",
1560 rtadv
->HomeAgentPreference
);
1562 if (rtadv
->AdvIntervalOption
)
1564 " ND router advertisements with Adv. Interval option.\n");
1570 /* Write configuration about router advertisement. */
1571 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1573 struct zebra_if
*zif
;
1574 struct listnode
*node
;
1575 struct rtadv_prefix
*rprefix
;
1576 char buf
[PREFIX_STRLEN
];
1581 if (!(if_is_loopback(ifp
)
1582 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1583 if (zif
->rtadv
.AdvSendAdvertisements
1584 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1585 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1588 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1589 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
1590 if (interval
% 1000)
1591 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
1593 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1594 vty_out(vty
, " ipv6 nd ra-interval %d\n",
1598 if (zif
->rtadv
.AdvIntervalOption
)
1599 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1601 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1602 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1603 zif
->rtadv
.AdvDefaultLifetime
);
1605 if (zif
->rtadv
.HomeAgentPreference
)
1606 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1607 zif
->rtadv
.HomeAgentPreference
);
1609 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1610 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1611 zif
->rtadv
.HomeAgentLifetime
);
1613 if (zif
->rtadv
.AdvHomeAgentFlag
)
1614 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1616 if (zif
->rtadv
.AdvReachableTime
)
1617 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1618 zif
->rtadv
.AdvReachableTime
);
1620 if (zif
->rtadv
.AdvManagedFlag
)
1621 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1623 if (zif
->rtadv
.AdvOtherConfigFlag
)
1624 vty_out(vty
, " ipv6 nd other-config-flag\n");
1626 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1627 vty_out(vty
, " ipv6 nd router-preference %s\n",
1628 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1630 if (zif
->rtadv
.AdvLinkMTU
)
1631 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1633 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1634 vty_out(vty
, " ipv6 nd prefix %s",
1635 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1636 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1637 || (rprefix
->AdvPreferredLifetime
1638 != RTADV_PREFERRED_LIFETIME
)) {
1639 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1640 vty_out(vty
, " infinite");
1642 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1643 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1644 vty_out(vty
, " infinite");
1647 rprefix
->AdvPreferredLifetime
);
1649 if (!rprefix
->AdvOnLinkFlag
)
1650 vty_out(vty
, " off-link");
1651 if (!rprefix
->AdvAutonomousFlag
)
1652 vty_out(vty
, " no-autoconfig");
1653 if (rprefix
->AdvRouterAddressFlag
)
1654 vty_out(vty
, " router-address");
1661 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1663 struct rtadv
*rtadv
= &zns
->rtadv
;
1667 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1669 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1673 if (rtadv
->ra_timer
) {
1674 thread_cancel(rtadv
->ra_timer
);
1675 rtadv
->ra_timer
= NULL
;
1677 if (rtadv
->ra_read
) {
1678 thread_cancel(rtadv
->ra_read
);
1679 rtadv
->ra_read
= NULL
;
1683 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1686 case RTADV_TIMER_MSEC
:
1687 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1691 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1700 void rtadv_init(struct zebra_ns
*zns
)
1702 zns
->rtadv
.sock
= rtadv_make_socket(zns
->ns_id
);
1705 void rtadv_terminate(struct zebra_ns
*zns
)
1707 rtadv_event(zns
, RTADV_STOP
, 0);
1708 if (zns
->rtadv
.sock
>= 0) {
1709 close(zns
->rtadv
.sock
);
1710 zns
->rtadv
.sock
= -1;
1713 zns
->rtadv
.adv_if_count
= 0;
1714 zns
->rtadv
.adv_msec_if_count
= 0;
1717 void rtadv_cmd_init(void)
1719 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1720 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1722 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1723 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1724 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1725 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1726 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1727 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1728 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1729 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1730 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1731 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1732 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1733 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1734 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1735 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1736 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1737 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1738 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1739 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1740 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1741 install_element(INTERFACE_NODE
,
1742 &ipv6_nd_adv_interval_config_option_cmd
);
1743 install_element(INTERFACE_NODE
,
1744 &no_ipv6_nd_adv_interval_config_option_cmd
);
1745 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1746 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1747 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1748 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1749 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1750 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1753 static int if_join_all_router(int sock
, struct interface
*ifp
)
1757 struct ipv6_mreq mreq
;
1759 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1760 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1761 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1763 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1766 zlog_warn("%s(%u): Failed to join group, socket %u error %s",
1767 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1769 if (IS_ZEBRA_DEBUG_EVENT
)
1771 "%s(%u): Join All-Routers multicast group, socket %u",
1772 ifp
->name
, ifp
->ifindex
, sock
);
1777 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1781 struct ipv6_mreq mreq
;
1783 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1784 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1785 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1787 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1790 zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
1791 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1793 if (IS_ZEBRA_DEBUG_EVENT
)
1795 "%s(%u): Leave All-Routers multicast group, socket %u",
1796 ifp
->name
, ifp
->ifindex
, sock
);
1802 void rtadv_init(struct zebra_ns
*zns
)
1806 void rtadv_terminate(struct zebra_ns
*zns
)
1810 void rtadv_cmd_init(void)
1814 #endif /* HAVE_RTADV */