1 /* Router advertisement
2 * Copyright (C) 2016 Cumulus Networks
3 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
4 * Copyright (C) 1999 Kunihiro Ishiguro
6 * This file is part of GNU Zebra.
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "zebra_memory.h"
38 #include "lib_errors.h"
40 #include "zebra/interface.h"
41 #include "zebra/rtadv.h"
42 #include "zebra/debug.h"
43 #include "zebra/rib.h"
44 #include "zebra/zapi_msg.h"
45 #include "zebra/zebra_ns.h"
46 #include "zebra/zebra_vrf.h"
47 #include "zebra/zebra_errors.h"
49 extern struct zebra_privs_t zserv_privs
;
51 #if defined(HAVE_RTADV)
54 #include <netinet/icmp6.h>
57 /* If RFC2133 definition is used. */
58 #ifndef IPV6_JOIN_GROUP
59 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
61 #ifndef IPV6_LEAVE_GROUP
62 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
65 #define ALLNODE "ff02::1"
66 #define ALLROUTER "ff02::2"
68 /* Order is intentional. Matches RFC4191. This array is also used for
69 command matching, so only modify with care. */
70 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
80 static void rtadv_event(struct zebra_ns
*, enum rtadv_event
, int);
82 static int if_join_all_router(int, struct interface
*);
83 static int if_leave_all_router(int, struct interface
*);
85 static int rtadv_increment_received(struct zebra_ns
*zns
, ifindex_t
*ifindex
)
88 struct interface
*iface
;
91 iface
= if_lookup_by_index_per_ns(zns
, *ifindex
);
92 if (iface
&& iface
->info
) {
100 static int rtadv_recv_packet(struct zebra_ns
*zns
, int sock
, uint8_t *buf
,
101 int buflen
, struct sockaddr_in6
*from
,
102 ifindex_t
*ifindex
, int *hoplimit
)
107 struct cmsghdr
*cmsgptr
;
112 /* Fill in message and iovec. */
113 memset(&msg
, 0, sizeof(msg
));
114 msg
.msg_name
= (void *)from
;
115 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
118 msg
.msg_control
= (void *)adata
;
119 msg
.msg_controllen
= sizeof adata
;
121 iov
.iov_len
= buflen
;
123 /* If recvmsg fail return minus value. */
124 ret
= recvmsg(sock
, &msg
, 0);
128 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
129 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
130 /* I want interface index which this packet comes from. */
131 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
132 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
133 struct in6_pktinfo
*ptr
;
135 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
136 *ifindex
= ptr
->ipi6_ifindex
;
137 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
140 /* Incoming packet's hop limit. */
141 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
142 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
143 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
148 rtadv_increment_received(zns
, ifindex
);
152 #define RTADV_MSG_SIZE 4096
154 /* Send router advertisement packet. */
155 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
159 struct cmsghdr
*cmsgptr
;
160 struct in6_pktinfo
*pkt
;
161 struct sockaddr_in6 addr
;
162 static void *adata
= NULL
;
163 unsigned char buf
[RTADV_MSG_SIZE
];
164 struct nd_router_advert
*rtadv
;
167 struct zebra_if
*zif
;
168 struct rtadv_prefix
*rprefix
;
169 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
170 0, 0, 0, 0, 0, 0, 0, 1};
171 struct listnode
*node
;
172 uint16_t pkt_RouterLifetime
;
175 * Allocate control message bufffer. This is dynamic because
176 * CMSG_SPACE is not guaranteed not to call a function. Note that
177 * the size will be different on different architectures due to
178 * differing alignment rules.
181 /* XXX Free on shutdown. */
182 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
186 "rtadv_send_packet: can't malloc control data");
191 /* Logging of packet. */
192 if (IS_ZEBRA_DEBUG_PACKET
)
193 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
196 /* Fill in sockaddr_in6. */
197 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
198 addr
.sin6_family
= AF_INET6
;
200 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
201 #endif /* SIN6_LEN */
202 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
203 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
205 /* Fetch interface information. */
208 /* Make router advertisement message. */
209 rtadv
= (struct nd_router_advert
*)buf
;
211 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
212 rtadv
->nd_ra_code
= 0;
213 rtadv
->nd_ra_cksum
= 0;
215 rtadv
->nd_ra_curhoplimit
= 64;
217 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
218 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
220 : zif
->rtadv
.DefaultPreference
;
221 rtadv
->nd_ra_flags_reserved
<<= 3;
223 if (zif
->rtadv
.AdvManagedFlag
)
224 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
225 if (zif
->rtadv
.AdvOtherConfigFlag
)
226 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
227 if (zif
->rtadv
.AdvHomeAgentFlag
)
228 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
229 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
230 * AdvDefaultLifetime is by default based on the value of
231 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
232 * field of Router Advertisements. Given that this field is expressed
233 * in seconds, a small MaxRtrAdvInterval value can result in a zero
234 * value for this field. To prevent this, routers SHOULD keep
235 * AdvDefaultLifetime in at least one second, even if the use of
236 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
238 zif
->rtadv
.AdvDefaultLifetime
!= -1
239 ? zif
->rtadv
.AdvDefaultLifetime
240 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
241 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
242 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
243 rtadv
->nd_ra_retransmit
= htonl(0);
245 len
= sizeof(struct nd_router_advert
);
247 /* If both the Home Agent Preference and Home Agent Lifetime are set to
248 * their default values specified above, this option SHOULD NOT be
249 * included in the Router Advertisement messages sent by this home
250 * agent. -- RFC6275, 7.4 */
251 if (zif
->rtadv
.AdvHomeAgentFlag
252 && (zif
->rtadv
.HomeAgentPreference
253 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
254 struct nd_opt_homeagent_info
*ndopt_hai
=
255 (struct nd_opt_homeagent_info
*)(buf
+ len
);
256 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
257 ndopt_hai
->nd_opt_hai_len
= 1;
258 ndopt_hai
->nd_opt_hai_reserved
= 0;
259 ndopt_hai
->nd_opt_hai_preference
=
260 htons(zif
->rtadv
.HomeAgentPreference
);
261 /* 16-bit unsigned integer. The lifetime associated with the
263 * agent in units of seconds. The default value is the same as
265 * Router Lifetime, as specified in the main body of the Router
266 * Advertisement. The maximum value corresponds to 18.2 hours.
268 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
269 ndopt_hai
->nd_opt_hai_lifetime
=
270 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
271 ? zif
->rtadv
.HomeAgentLifetime
272 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
277 len
+= sizeof(struct nd_opt_homeagent_info
);
280 if (zif
->rtadv
.AdvIntervalOption
) {
281 struct nd_opt_adv_interval
*ndopt_adv
=
282 (struct nd_opt_adv_interval
*)(buf
+ len
);
283 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
284 ndopt_adv
->nd_opt_ai_len
= 1;
285 ndopt_adv
->nd_opt_ai_reserved
= 0;
286 ndopt_adv
->nd_opt_ai_interval
=
287 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
288 len
+= sizeof(struct nd_opt_adv_interval
);
291 /* Fill in prefix. */
292 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
293 struct nd_opt_prefix_info
*pinfo
;
295 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
297 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
298 pinfo
->nd_opt_pi_len
= 4;
299 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
301 pinfo
->nd_opt_pi_flags_reserved
= 0;
302 if (rprefix
->AdvOnLinkFlag
)
303 pinfo
->nd_opt_pi_flags_reserved
|=
304 ND_OPT_PI_FLAG_ONLINK
;
305 if (rprefix
->AdvAutonomousFlag
)
306 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
307 if (rprefix
->AdvRouterAddressFlag
)
308 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
310 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
311 pinfo
->nd_opt_pi_preferred_time
=
312 htonl(rprefix
->AdvPreferredLifetime
);
313 pinfo
->nd_opt_pi_reserved2
= 0;
315 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
316 &rprefix
->prefix
.prefix
);
320 uint8_t buf
[INET6_ADDRSTRLEN
];
322 zlog_debug("DEBUG %s",
323 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
324 buf
, INET6_ADDRSTRLEN
));
328 len
+= sizeof(struct nd_opt_prefix_info
);
331 /* Hardware address. */
332 if (ifp
->hw_addr_len
!= 0) {
333 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
335 /* Option length should be rounded up to next octet if
336 the link address does not end on an octet boundary. */
337 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
339 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
340 len
+= ifp
->hw_addr_len
;
342 /* Pad option to end on an octet boundary. */
343 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
344 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
348 if (zif
->rtadv
.AdvLinkMTU
) {
349 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
350 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
351 opt
->nd_opt_mtu_len
= 1;
352 opt
->nd_opt_mtu_reserved
= 0;
353 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
354 len
+= sizeof(struct nd_opt_mtu
);
357 msg
.msg_name
= (void *)&addr
;
358 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
361 msg
.msg_control
= (void *)adata
;
362 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
367 cmsgptr
= CMSG_FIRSTHDR(&msg
);
368 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
369 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
370 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
372 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
373 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
374 pkt
->ipi6_ifindex
= ifp
->ifindex
;
376 ret
= sendmsg(sock
, &msg
, 0);
378 flog_err_sys(EC_LIB_SOCKET
,
379 "%s(%u): Tx RA failed, socket %u error %d (%s)",
380 ifp
->name
, ifp
->ifindex
, sock
, errno
,
381 safe_strerror(errno
));
386 static int rtadv_timer(struct thread
*thread
)
388 struct zebra_ns
*zns
= THREAD_ARG(thread
);
390 struct interface
*ifp
;
391 struct zebra_if
*zif
;
394 zns
->rtadv
.ra_timer
= NULL
;
395 if (zns
->rtadv
.adv_msec_if_count
== 0) {
396 period
= 1000; /* 1 s */
397 rtadv_event(zns
, RTADV_TIMER
, 1 /* 1 s */);
399 period
= 10; /* 10 ms */
400 rtadv_event(zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
403 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
404 FOR_ALL_INTERFACES (vrf
, ifp
) {
405 if (if_is_loopback(ifp
)
406 || CHECK_FLAG(ifp
->status
,
407 ZEBRA_INTERFACE_VRF_LOOPBACK
)
408 || !if_is_operative(ifp
))
413 if (zif
->rtadv
.AdvSendAdvertisements
) {
414 if (zif
->rtadv
.inFastRexmit
) {
415 /* We assume we fast rexmit every sec so
418 if (--zif
->rtadv
.NumFastReXmitsRemain
420 zif
->rtadv
.inFastRexmit
= 0;
422 if (IS_ZEBRA_DEBUG_SEND
)
424 "Fast RA Rexmit on interface %s",
427 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
429 zif
->rtadv
.AdvIntervalTimer
-= period
;
430 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
432 MaxRtrAdvInterval each
433 time isn't what section
434 6.2.4 of RFC4861 tells to do.
436 zif
->rtadv
.AdvIntervalTimer
=
440 zns
->rtadv
.sock
, ifp
);
449 static void rtadv_process_solicit(struct interface
*ifp
)
451 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
452 struct zebra_ns
*zns
= zvrf
->zns
;
455 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
458 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
459 struct interface
*ifp
,
460 struct sockaddr_in6
*addr
)
462 struct nd_router_advert
*radvert
;
463 char addr_str
[INET6_ADDRSTRLEN
];
464 struct zebra_if
*zif
;
469 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
471 if (len
< sizeof(struct nd_router_advert
)) {
472 zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
473 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
476 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
478 "%s(%u): Rx RA with non-linklocal source address from %s",
479 ifp
->name
, ifp
->ifindex
, addr_str
);
483 radvert
= (struct nd_router_advert
*)msg
;
485 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
486 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
488 EC_ZEBRA_RA_PARAM_MISMATCH
,
489 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
490 ifp
->name
, ifp
->ifindex
, addr_str
);
493 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
494 && !zif
->rtadv
.AdvManagedFlag
) {
496 EC_ZEBRA_RA_PARAM_MISMATCH
,
497 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
498 ifp
->name
, ifp
->ifindex
, addr_str
);
501 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
502 && !zif
->rtadv
.AdvOtherConfigFlag
) {
504 EC_ZEBRA_RA_PARAM_MISMATCH
,
505 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
506 ifp
->name
, ifp
->ifindex
, addr_str
);
509 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
510 && (ntohl(radvert
->nd_ra_reachable
)
511 != zif
->rtadv
.AdvReachableTime
)) {
513 EC_ZEBRA_RA_PARAM_MISMATCH
,
514 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
515 ifp
->name
, ifp
->ifindex
, addr_str
);
518 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
519 && (ntohl(radvert
->nd_ra_retransmit
)
520 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
522 EC_ZEBRA_RA_PARAM_MISMATCH
,
523 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
524 ifp
->name
, ifp
->ifindex
, addr_str
);
527 /* Create entry for neighbor if not known. */
529 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
530 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
532 if (!nbr_connected_check(ifp
, &p
))
533 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
537 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
538 ifindex_t ifindex
, int hoplimit
,
539 struct sockaddr_in6
*from
,
540 struct zebra_ns
*zns
)
542 struct icmp6_hdr
*icmph
;
543 struct interface
*ifp
;
544 struct zebra_if
*zif
;
545 char addr_str
[INET6_ADDRSTRLEN
];
547 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
549 /* Interface search. */
550 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
552 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
553 "RA/RS received on unknown IF %u from %s", ifindex
,
558 if (IS_ZEBRA_DEBUG_PACKET
)
559 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
560 ifp
->ifindex
, len
, addr_str
);
562 if (if_is_loopback(ifp
)
563 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
566 /* Check interface configuration. */
568 if (!zif
->rtadv
.AdvSendAdvertisements
)
571 /* ICMP message length check. */
572 if (len
< sizeof(struct icmp6_hdr
)) {
573 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
574 ifp
->name
, ifp
->ifindex
, len
);
578 icmph
= (struct icmp6_hdr
*)buf
;
580 /* ICMP message type check. */
581 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
582 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
583 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
584 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
588 /* Hoplimit check. */
589 if (hoplimit
>= 0 && hoplimit
!= 255) {
590 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
591 ifp
->ifindex
, hoplimit
);
595 /* Check ICMP message type. */
596 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
597 rtadv_process_solicit(ifp
);
598 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
599 rtadv_process_advert(buf
, len
, ifp
, from
);
604 static int rtadv_read(struct thread
*thread
)
608 uint8_t buf
[RTADV_MSG_SIZE
];
609 struct sockaddr_in6 from
;
610 ifindex_t ifindex
= 0;
612 struct zebra_ns
*zns
= THREAD_ARG(thread
);
614 sock
= THREAD_FD(thread
);
615 zns
->rtadv
.ra_read
= NULL
;
617 /* Register myself. */
618 rtadv_event(zns
, RTADV_READ
, sock
);
620 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
624 flog_err_sys(EC_LIB_SOCKET
,
625 "RA/RS recv failed, socket %u error %s", sock
,
626 safe_strerror(errno
));
630 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
635 static int rtadv_make_socket(ns_id_t ns_id
)
639 struct icmp6_filter filter
;
641 frr_elevate_privs(&zserv_privs
) {
643 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
651 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
656 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
661 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
666 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
671 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
677 ICMP6_FILTER_SETBLOCKALL(&filter
);
678 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
679 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
681 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
682 sizeof(struct icmp6_filter
));
684 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
692 static struct rtadv_prefix
*rtadv_prefix_new(void)
694 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
697 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
699 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
702 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
703 struct prefix_ipv6
*p
)
705 struct listnode
*node
;
706 struct rtadv_prefix
*rprefix
;
708 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
709 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
715 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
716 struct prefix_ipv6
*p
)
718 struct rtadv_prefix
*rprefix
;
720 rprefix
= rtadv_prefix_lookup(rplist
, p
);
724 rprefix
= rtadv_prefix_new();
725 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
726 listnode_add(rplist
, rprefix
);
731 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
733 struct rtadv_prefix
*rprefix
;
735 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
737 /* Set parameters. */
738 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
739 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
740 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
741 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
742 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
745 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
747 struct rtadv_prefix
*rprefix
;
749 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
750 if (rprefix
!= NULL
) {
751 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
752 rtadv_prefix_free(rprefix
);
758 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
759 ipv6_nd_suppress_ra_status status
)
761 struct zebra_if
*zif
;
762 struct zebra_vrf
*zvrf
;
763 struct zebra_ns
*zns
;
766 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
769 if (status
== RA_SUPPRESS
) {
770 /* RA is currently enabled */
771 if (zif
->rtadv
.AdvSendAdvertisements
) {
772 zif
->rtadv
.AdvSendAdvertisements
= 0;
773 zif
->rtadv
.AdvIntervalTimer
= 0;
774 zns
->rtadv
.adv_if_count
--;
776 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
778 if (zns
->rtadv
.adv_if_count
== 0)
779 rtadv_event(zns
, RTADV_STOP
, 0);
782 if (!zif
->rtadv
.AdvSendAdvertisements
) {
783 zif
->rtadv
.AdvSendAdvertisements
= 1;
784 zif
->rtadv
.AdvIntervalTimer
= 0;
785 zns
->rtadv
.adv_if_count
++;
787 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
788 /* Enable Fast RA only when RA interval is in
790 zif
->rtadv
.inFastRexmit
= 1;
791 zif
->rtadv
.NumFastReXmitsRemain
=
792 RTADV_NUM_FAST_REXMITS
;
795 if_join_all_router(zns
->rtadv
.sock
, ifp
);
797 if (zns
->rtadv
.adv_if_count
== 1)
798 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
804 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
805 * Note that while the client could request RA on an interface on which the
806 * operator has not enabled RA, RA won't be disabled upon client request
807 * if the operator has explicitly enabled RA. The enable request can also
808 * specify a RA interval (in seconds).
810 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
814 struct interface
*ifp
;
815 struct zebra_if
*zif
;
820 /* Get interface index and RA interval. */
821 STREAM_GETL(s
, ifindex
);
822 STREAM_GETL(s
, ra_interval
);
824 if (IS_ZEBRA_DEBUG_EVENT
)
825 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
826 zvrf_id(zvrf
), ifindex
,
827 enable
? "enable" : "disable",
828 zebra_route_string(client
->proto
), ra_interval
);
830 /* Locate interface and check VRF match. */
831 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
833 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
834 "%u: IF %u RA %s client %s - interface unknown",
835 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
836 zebra_route_string(client
->proto
));
839 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
841 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
842 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
843 zebra_route_string(client
->proto
), ifp
->vrf_id
);
849 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
850 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
852 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
853 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
854 VTY_RA_INTERVAL_CONFIGURED
))
855 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
857 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
858 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
859 VTY_RA_INTERVAL_CONFIGURED
))
860 zif
->rtadv
.MaxRtrAdvInterval
=
861 RTADV_MAX_RTR_ADV_INTERVAL
;
862 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
863 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
869 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
871 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
873 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
875 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
878 DEFUN (ipv6_nd_suppress_ra
,
879 ipv6_nd_suppress_ra_cmd
,
880 "ipv6 nd suppress-ra",
881 "Interface IPv6 config commands\n"
882 "Neighbor discovery\n"
883 "Suppress Router Advertisement\n")
885 VTY_DECLVAR_CONTEXT(interface
, ifp
);
886 struct zebra_if
*zif
= ifp
->info
;
888 if (if_is_loopback(ifp
)
889 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
891 "Cannot configure IPv6 Router Advertisements on this interface\n");
892 return CMD_WARNING_CONFIG_FAILED
;
895 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
896 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
898 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
902 DEFUN (no_ipv6_nd_suppress_ra
,
903 no_ipv6_nd_suppress_ra_cmd
,
904 "no ipv6 nd suppress-ra",
906 "Interface IPv6 config commands\n"
907 "Neighbor discovery\n"
908 "Suppress Router Advertisement\n")
910 VTY_DECLVAR_CONTEXT(interface
, ifp
);
911 struct zebra_if
*zif
= ifp
->info
;
913 if (if_is_loopback(ifp
)
914 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
916 "Cannot configure IPv6 Router Advertisements on this interface\n");
917 return CMD_WARNING_CONFIG_FAILED
;
920 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
921 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
925 DEFUN (ipv6_nd_ra_interval_msec
,
926 ipv6_nd_ra_interval_msec_cmd
,
927 "ipv6 nd ra-interval msec (70-1800000)",
928 "Interface IPv6 config commands\n"
929 "Neighbor discovery\n"
930 "Router Advertisement interval\n"
931 "Router Advertisement interval in milliseconds\n"
932 "Router Advertisement interval in milliseconds\n")
935 VTY_DECLVAR_CONTEXT(interface
, ifp
);
937 struct zebra_if
*zif
= ifp
->info
;
938 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
939 struct zebra_ns
*zns
;
942 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
943 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
944 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
946 "This ra-interval would conflict with configured ra-lifetime!\n");
947 return CMD_WARNING_CONFIG_FAILED
;
950 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
951 zns
->rtadv
.adv_msec_if_count
--;
954 zns
->rtadv
.adv_msec_if_count
++;
956 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
957 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
958 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
959 zif
->rtadv
.AdvIntervalTimer
= 0;
964 DEFUN (ipv6_nd_ra_interval
,
965 ipv6_nd_ra_interval_cmd
,
966 "ipv6 nd ra-interval (1-1800)",
967 "Interface IPv6 config commands\n"
968 "Neighbor discovery\n"
969 "Router Advertisement interval\n"
970 "Router Advertisement interval in seconds\n")
973 VTY_DECLVAR_CONTEXT(interface
, ifp
);
975 struct zebra_if
*zif
= ifp
->info
;
976 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
977 struct zebra_ns
*zns
;
980 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
981 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
982 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
984 "This ra-interval would conflict with configured ra-lifetime!\n");
985 return CMD_WARNING_CONFIG_FAILED
;
988 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
989 zns
->rtadv
.adv_msec_if_count
--;
991 /* convert to milliseconds */
992 interval
= interval
* 1000;
994 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
995 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
996 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
997 zif
->rtadv
.AdvIntervalTimer
= 0;
1002 DEFUN (no_ipv6_nd_ra_interval
,
1003 no_ipv6_nd_ra_interval_cmd
,
1004 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1006 "Interface IPv6 config commands\n"
1007 "Neighbor discovery\n"
1008 "Router Advertisement interval\n"
1009 "Router Advertisement interval in seconds\n"
1010 "Specify millisecond router advertisement interval\n"
1011 "Router Advertisement interval in milliseconds\n")
1013 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1014 struct zebra_if
*zif
= ifp
->info
;
1015 struct zebra_vrf
*zvrf
;
1016 struct zebra_ns
*zns
;
1018 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1021 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1022 zns
->rtadv
.adv_msec_if_count
--;
1024 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1026 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1027 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1029 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1031 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1032 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1037 DEFUN (ipv6_nd_ra_lifetime
,
1038 ipv6_nd_ra_lifetime_cmd
,
1039 "ipv6 nd ra-lifetime (0-9000)",
1040 "Interface IPv6 config commands\n"
1041 "Neighbor discovery\n"
1043 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1046 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1047 struct zebra_if
*zif
= ifp
->info
;
1050 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1052 /* The value to be placed in the Router Lifetime field
1053 * of Router Advertisements sent from the interface,
1054 * in seconds. MUST be either zero or between
1055 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1056 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1058 "This ra-lifetime would conflict with configured ra-interval\n");
1059 return CMD_WARNING_CONFIG_FAILED
;
1062 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1067 DEFUN (no_ipv6_nd_ra_lifetime
,
1068 no_ipv6_nd_ra_lifetime_cmd
,
1069 "no ipv6 nd ra-lifetime [(0-9000)]",
1071 "Interface IPv6 config commands\n"
1072 "Neighbor discovery\n"
1074 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1076 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1077 struct zebra_if
*zif
= ifp
->info
;
1079 zif
->rtadv
.AdvDefaultLifetime
= -1;
1084 DEFUN (ipv6_nd_reachable_time
,
1085 ipv6_nd_reachable_time_cmd
,
1086 "ipv6 nd reachable-time (1-3600000)",
1087 "Interface IPv6 config commands\n"
1088 "Neighbor discovery\n"
1090 "Reachable time in milliseconds\n")
1093 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1094 struct zebra_if
*zif
= ifp
->info
;
1095 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1099 DEFUN (no_ipv6_nd_reachable_time
,
1100 no_ipv6_nd_reachable_time_cmd
,
1101 "no ipv6 nd reachable-time [(1-3600000)]",
1103 "Interface IPv6 config commands\n"
1104 "Neighbor discovery\n"
1106 "Reachable time in milliseconds\n")
1108 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1109 struct zebra_if
*zif
= ifp
->info
;
1111 zif
->rtadv
.AdvReachableTime
= 0;
1116 DEFUN (ipv6_nd_homeagent_preference
,
1117 ipv6_nd_homeagent_preference_cmd
,
1118 "ipv6 nd home-agent-preference (0-65535)",
1119 "Interface IPv6 config commands\n"
1120 "Neighbor discovery\n"
1121 "Home Agent preference\n"
1122 "preference value (default is 0, least preferred)\n")
1125 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1126 struct zebra_if
*zif
= ifp
->info
;
1127 zif
->rtadv
.HomeAgentPreference
=
1128 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1132 DEFUN (no_ipv6_nd_homeagent_preference
,
1133 no_ipv6_nd_homeagent_preference_cmd
,
1134 "no ipv6 nd home-agent-preference [(0-65535)]",
1136 "Interface IPv6 config commands\n"
1137 "Neighbor discovery\n"
1138 "Home Agent preference\n"
1139 "preference value (default is 0, least preferred)\n")
1141 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1142 struct zebra_if
*zif
= ifp
->info
;
1144 zif
->rtadv
.HomeAgentPreference
= 0;
1149 DEFUN (ipv6_nd_homeagent_lifetime
,
1150 ipv6_nd_homeagent_lifetime_cmd
,
1151 "ipv6 nd home-agent-lifetime (0-65520)",
1152 "Interface IPv6 config commands\n"
1153 "Neighbor discovery\n"
1154 "Home Agent lifetime\n"
1155 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1158 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1159 struct zebra_if
*zif
= ifp
->info
;
1160 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1164 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1165 no_ipv6_nd_homeagent_lifetime_cmd
,
1166 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1168 "Interface IPv6 config commands\n"
1169 "Neighbor discovery\n"
1170 "Home Agent lifetime\n"
1171 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1173 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1174 struct zebra_if
*zif
= ifp
->info
;
1176 zif
->rtadv
.HomeAgentLifetime
= -1;
1181 DEFUN (ipv6_nd_managed_config_flag
,
1182 ipv6_nd_managed_config_flag_cmd
,
1183 "ipv6 nd managed-config-flag",
1184 "Interface IPv6 config commands\n"
1185 "Neighbor discovery\n"
1186 "Managed address configuration flag\n")
1188 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1189 struct zebra_if
*zif
= ifp
->info
;
1191 zif
->rtadv
.AdvManagedFlag
= 1;
1196 DEFUN (no_ipv6_nd_managed_config_flag
,
1197 no_ipv6_nd_managed_config_flag_cmd
,
1198 "no ipv6 nd managed-config-flag",
1200 "Interface IPv6 config commands\n"
1201 "Neighbor discovery\n"
1202 "Managed address configuration flag\n")
1204 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1205 struct zebra_if
*zif
= ifp
->info
;
1207 zif
->rtadv
.AdvManagedFlag
= 0;
1212 DEFUN (ipv6_nd_homeagent_config_flag
,
1213 ipv6_nd_homeagent_config_flag_cmd
,
1214 "ipv6 nd home-agent-config-flag",
1215 "Interface IPv6 config commands\n"
1216 "Neighbor discovery\n"
1217 "Home Agent configuration flag\n")
1219 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1220 struct zebra_if
*zif
= ifp
->info
;
1222 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1227 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1228 no_ipv6_nd_homeagent_config_flag_cmd
,
1229 "no ipv6 nd home-agent-config-flag",
1231 "Interface IPv6 config commands\n"
1232 "Neighbor discovery\n"
1233 "Home Agent configuration flag\n")
1235 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1236 struct zebra_if
*zif
= ifp
->info
;
1238 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1243 DEFUN (ipv6_nd_adv_interval_config_option
,
1244 ipv6_nd_adv_interval_config_option_cmd
,
1245 "ipv6 nd adv-interval-option",
1246 "Interface IPv6 config commands\n"
1247 "Neighbor discovery\n"
1248 "Advertisement Interval Option\n")
1250 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1251 struct zebra_if
*zif
= ifp
->info
;
1253 zif
->rtadv
.AdvIntervalOption
= 1;
1258 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1259 no_ipv6_nd_adv_interval_config_option_cmd
,
1260 "no ipv6 nd adv-interval-option",
1262 "Interface IPv6 config commands\n"
1263 "Neighbor discovery\n"
1264 "Advertisement Interval Option\n")
1266 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1267 struct zebra_if
*zif
= ifp
->info
;
1269 zif
->rtadv
.AdvIntervalOption
= 0;
1274 DEFUN (ipv6_nd_other_config_flag
,
1275 ipv6_nd_other_config_flag_cmd
,
1276 "ipv6 nd other-config-flag",
1277 "Interface IPv6 config commands\n"
1278 "Neighbor discovery\n"
1279 "Other statefull configuration flag\n")
1281 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1282 struct zebra_if
*zif
= ifp
->info
;
1284 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1289 DEFUN (no_ipv6_nd_other_config_flag
,
1290 no_ipv6_nd_other_config_flag_cmd
,
1291 "no ipv6 nd other-config-flag",
1293 "Interface IPv6 config commands\n"
1294 "Neighbor discovery\n"
1295 "Other statefull configuration flag\n")
1297 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1298 struct zebra_if
*zif
= ifp
->info
;
1300 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1305 DEFUN (ipv6_nd_prefix
,
1307 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1308 "Interface IPv6 config commands\n"
1309 "Neighbor discovery\n"
1310 "Prefix information\n"
1312 "Valid lifetime in seconds\n"
1313 "Infinite valid lifetime\n"
1314 "Preferred lifetime in seconds\n"
1315 "Infinite preferred lifetime\n"
1316 "Set Router Address flag\n"
1317 "Do not use prefix for onlink determination\n"
1318 "Do not use prefix for autoconfiguration\n"
1319 "Do not use prefix for autoconfiguration\n"
1320 "Do not use prefix for onlink determination\n")
1323 char *prefix
= argv
[3]->arg
;
1324 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1325 || strmatch(argv
[4]->text
, "infinite"));
1326 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1328 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1330 char *lifetime
= NULL
, *preflifetime
= NULL
;
1331 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1333 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1335 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1340 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1342 offlink
= (argc
> idx_routeropts
+ 1
1343 || strmatch(argv
[idx_routeropts
]->text
,
1345 noautoconf
= (argc
> idx_routeropts
+ 1
1346 || strmatch(argv
[idx_routeropts
]->text
,
1352 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1353 struct zebra_if
*zebra_if
= ifp
->info
;
1355 struct rtadv_prefix rp
;
1357 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1359 vty_out(vty
, "Malformed IPv6 prefix\n");
1360 return CMD_WARNING_CONFIG_FAILED
;
1362 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1363 rp
.AdvOnLinkFlag
= !offlink
;
1364 rp
.AdvAutonomousFlag
= !noautoconf
;
1365 rp
.AdvRouterAddressFlag
= routeraddr
;
1366 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1367 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1370 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1372 : strtoll(lifetime
, NULL
, 10);
1373 rp
.AdvPreferredLifetime
=
1374 strmatch(preflifetime
, "infinite")
1376 : strtoll(preflifetime
, NULL
, 10);
1377 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1378 vty_out(vty
, "Invalid preferred lifetime\n");
1379 return CMD_WARNING_CONFIG_FAILED
;
1383 rtadv_prefix_set(zebra_if
, &rp
);
1388 DEFUN (no_ipv6_nd_prefix
,
1389 no_ipv6_nd_prefix_cmd
,
1390 "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]>]",
1392 "Interface IPv6 config commands\n"
1393 "Neighbor discovery\n"
1394 "Prefix information\n"
1396 "Valid lifetime in seconds\n"
1397 "Infinite valid lifetime\n"
1398 "Preferred lifetime in seconds\n"
1399 "Infinite preferred lifetime\n"
1400 "Set Router Address flag\n"
1401 "Do not use prefix for onlink determination\n"
1402 "Do not use prefix for autoconfiguration\n"
1403 "Do not use prefix for autoconfiguration\n"
1404 "Do not use prefix for onlink determination\n")
1406 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1407 struct zebra_if
*zebra_if
= ifp
->info
;
1409 struct rtadv_prefix rp
;
1410 char *prefix
= argv
[4]->arg
;
1412 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1414 vty_out(vty
, "Malformed IPv6 prefix\n");
1415 return CMD_WARNING_CONFIG_FAILED
;
1417 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1419 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1421 vty_out(vty
, "Non-existant IPv6 prefix\n");
1422 return CMD_WARNING_CONFIG_FAILED
;
1428 DEFUN (ipv6_nd_router_preference
,
1429 ipv6_nd_router_preference_cmd
,
1430 "ipv6 nd router-preference <high|medium|low>",
1431 "Interface IPv6 config commands\n"
1432 "Neighbor discovery\n"
1433 "Default router preference\n"
1434 "High default router preference\n"
1435 "Medium default router preference (default)\n"
1436 "Low default router preference\n")
1438 int idx_high_medium_low
= 3;
1439 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1440 struct zebra_if
*zif
= ifp
->info
;
1443 while (0 != rtadv_pref_strs
[i
]) {
1444 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1447 zif
->rtadv
.DefaultPreference
= i
;
1453 return CMD_ERR_NO_MATCH
;
1456 DEFUN (no_ipv6_nd_router_preference
,
1457 no_ipv6_nd_router_preference_cmd
,
1458 "no ipv6 nd router-preference [<high|medium|low>]",
1460 "Interface IPv6 config commands\n"
1461 "Neighbor discovery\n"
1462 "Default router preference\n"
1463 "High default router preference\n"
1464 "Medium default router preference (default)\n"
1465 "Low default router preference\n")
1467 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1468 struct zebra_if
*zif
= ifp
->info
;
1470 zif
->rtadv
.DefaultPreference
=
1471 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1478 "ipv6 nd mtu (1-65535)",
1479 "Interface IPv6 config commands\n"
1480 "Neighbor discovery\n"
1485 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1486 struct zebra_if
*zif
= ifp
->info
;
1487 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1491 DEFUN (no_ipv6_nd_mtu
,
1493 "no ipv6 nd mtu [(1-65535)]",
1495 "Interface IPv6 config commands\n"
1496 "Neighbor discovery\n"
1500 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1501 struct zebra_if
*zif
= ifp
->info
;
1502 zif
->rtadv
.AdvLinkMTU
= 0;
1506 /* Dump interface ND information to vty. */
1507 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1509 struct zebra_if
*zif
;
1510 struct rtadvconf
*rtadv
;
1513 zif
= (struct zebra_if
*)ifp
->info
;
1514 rtadv
= &zif
->rtadv
;
1516 if (rtadv
->AdvSendAdvertisements
) {
1518 " ND advertised reachable time is %d milliseconds\n",
1519 rtadv
->AdvReachableTime
);
1521 " ND advertised retransmit interval is %d milliseconds\n",
1522 rtadv
->AdvRetransTimer
);
1523 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1524 zif
->ra_sent
, zif
->ra_rcvd
);
1525 interval
= rtadv
->MaxRtrAdvInterval
;
1526 if (interval
% 1000)
1528 " ND router advertisements are sent every "
1529 "%d milliseconds\n",
1533 " ND router advertisements are sent every "
1536 if (rtadv
->AdvDefaultLifetime
!= -1)
1538 " ND router advertisements live for %d seconds\n",
1539 rtadv
->AdvDefaultLifetime
);
1542 " ND router advertisements lifetime tracks ra-interval\n");
1544 " ND router advertisement default router preference is "
1546 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1547 if (rtadv
->AdvManagedFlag
)
1549 " Hosts use DHCP to obtain routable addresses.\n");
1552 " Hosts use stateless autoconfig for addresses.\n");
1553 if (rtadv
->AdvHomeAgentFlag
) {
1555 " ND router advertisements with Home Agent flag bit set.\n");
1556 if (rtadv
->HomeAgentLifetime
!= -1)
1558 " Home Agent lifetime is %u seconds\n",
1559 rtadv
->HomeAgentLifetime
);
1562 " Home Agent lifetime tracks ra-lifetime\n");
1563 vty_out(vty
, " Home Agent preference is %u\n",
1564 rtadv
->HomeAgentPreference
);
1566 if (rtadv
->AdvIntervalOption
)
1568 " ND router advertisements with Adv. Interval option.\n");
1574 /* Write configuration about router advertisement. */
1575 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1577 struct zebra_if
*zif
;
1578 struct listnode
*node
;
1579 struct rtadv_prefix
*rprefix
;
1580 char buf
[PREFIX_STRLEN
];
1585 if (!(if_is_loopback(ifp
)
1586 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1587 if (zif
->rtadv
.AdvSendAdvertisements
1588 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1589 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1592 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1593 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
1594 if (interval
% 1000)
1595 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
1597 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1598 vty_out(vty
, " ipv6 nd ra-interval %d\n",
1602 if (zif
->rtadv
.AdvIntervalOption
)
1603 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1605 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1606 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1607 zif
->rtadv
.AdvDefaultLifetime
);
1609 if (zif
->rtadv
.HomeAgentPreference
)
1610 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1611 zif
->rtadv
.HomeAgentPreference
);
1613 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1614 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1615 zif
->rtadv
.HomeAgentLifetime
);
1617 if (zif
->rtadv
.AdvHomeAgentFlag
)
1618 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1620 if (zif
->rtadv
.AdvReachableTime
)
1621 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1622 zif
->rtadv
.AdvReachableTime
);
1624 if (zif
->rtadv
.AdvManagedFlag
)
1625 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1627 if (zif
->rtadv
.AdvOtherConfigFlag
)
1628 vty_out(vty
, " ipv6 nd other-config-flag\n");
1630 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1631 vty_out(vty
, " ipv6 nd router-preference %s\n",
1632 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1634 if (zif
->rtadv
.AdvLinkMTU
)
1635 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1637 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1638 vty_out(vty
, " ipv6 nd prefix %s",
1639 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1640 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1641 || (rprefix
->AdvPreferredLifetime
1642 != RTADV_PREFERRED_LIFETIME
)) {
1643 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1644 vty_out(vty
, " infinite");
1646 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1647 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1648 vty_out(vty
, " infinite");
1651 rprefix
->AdvPreferredLifetime
);
1653 if (!rprefix
->AdvOnLinkFlag
)
1654 vty_out(vty
, " off-link");
1655 if (!rprefix
->AdvAutonomousFlag
)
1656 vty_out(vty
, " no-autoconfig");
1657 if (rprefix
->AdvRouterAddressFlag
)
1658 vty_out(vty
, " router-address");
1665 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1667 struct rtadv
*rtadv
= &zns
->rtadv
;
1671 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1673 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1677 if (rtadv
->ra_timer
) {
1678 thread_cancel(rtadv
->ra_timer
);
1679 rtadv
->ra_timer
= NULL
;
1681 if (rtadv
->ra_read
) {
1682 thread_cancel(rtadv
->ra_read
);
1683 rtadv
->ra_read
= NULL
;
1687 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1690 case RTADV_TIMER_MSEC
:
1691 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1695 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1704 void rtadv_init(struct zebra_ns
*zns
)
1706 zns
->rtadv
.sock
= rtadv_make_socket(zns
->ns_id
);
1709 void rtadv_terminate(struct zebra_ns
*zns
)
1711 rtadv_event(zns
, RTADV_STOP
, 0);
1712 if (zns
->rtadv
.sock
>= 0) {
1713 close(zns
->rtadv
.sock
);
1714 zns
->rtadv
.sock
= -1;
1717 zns
->rtadv
.adv_if_count
= 0;
1718 zns
->rtadv
.adv_msec_if_count
= 0;
1721 void rtadv_cmd_init(void)
1723 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1724 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1726 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1727 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1728 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1729 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1730 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1731 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1732 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1733 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1734 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1735 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1736 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1737 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1738 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1739 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1740 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1741 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1742 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1743 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1744 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1745 install_element(INTERFACE_NODE
,
1746 &ipv6_nd_adv_interval_config_option_cmd
);
1747 install_element(INTERFACE_NODE
,
1748 &no_ipv6_nd_adv_interval_config_option_cmd
);
1749 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1750 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1751 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1752 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1753 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1754 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1757 static int if_join_all_router(int sock
, struct interface
*ifp
)
1761 struct ipv6_mreq mreq
;
1763 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1764 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1765 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1767 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1770 flog_err_sys(EC_LIB_SOCKET
,
1771 "%s(%u): Failed to join group, socket %u error %s",
1772 ifp
->name
, ifp
->ifindex
, sock
,
1773 safe_strerror(errno
));
1775 if (IS_ZEBRA_DEBUG_EVENT
)
1777 "%s(%u): Join All-Routers multicast group, socket %u",
1778 ifp
->name
, ifp
->ifindex
, sock
);
1783 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1787 struct ipv6_mreq mreq
;
1789 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1790 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1791 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1793 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1798 "%s(%u): Failed to leave group, socket %u error %s",
1799 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1801 if (IS_ZEBRA_DEBUG_EVENT
)
1803 "%s(%u): Leave All-Routers multicast group, socket %u",
1804 ifp
->name
, ifp
->ifindex
, sock
);
1810 void rtadv_init(struct zebra_ns
*zns
)
1814 void rtadv_terminate(struct zebra_ns
*zns
)
1818 void rtadv_cmd_init(void)
1822 #endif /* HAVE_RTADV */