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
= CMSG_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
= CMSG_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_debug("%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 ZEBRA_ERR_RA_PARAM_MISMATCH
,
488 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
489 ifp
->name
, ifp
->ifindex
, addr_str
);
492 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
493 && !zif
->rtadv
.AdvManagedFlag
) {
495 ZEBRA_ERR_RA_PARAM_MISMATCH
,
496 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
497 ifp
->name
, ifp
->ifindex
, addr_str
);
500 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
501 && !zif
->rtadv
.AdvOtherConfigFlag
) {
503 ZEBRA_ERR_RA_PARAM_MISMATCH
,
504 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
505 ifp
->name
, ifp
->ifindex
, addr_str
);
508 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
509 && (ntohl(radvert
->nd_ra_reachable
)
510 != zif
->rtadv
.AdvReachableTime
)) {
512 ZEBRA_ERR_RA_PARAM_MISMATCH
,
513 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
514 ifp
->name
, ifp
->ifindex
, addr_str
);
517 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
518 && (ntohl(radvert
->nd_ra_retransmit
)
519 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
521 ZEBRA_ERR_RA_PARAM_MISMATCH
,
522 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
523 ifp
->name
, ifp
->ifindex
, addr_str
);
526 /* Create entry for neighbor if not known. */
528 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
529 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
531 if (!nbr_connected_check(ifp
, &p
))
532 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
536 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
537 ifindex_t ifindex
, int hoplimit
,
538 struct sockaddr_in6
*from
,
539 struct zebra_ns
*zns
)
541 struct icmp6_hdr
*icmph
;
542 struct interface
*ifp
;
543 struct zebra_if
*zif
;
544 char addr_str
[INET6_ADDRSTRLEN
];
546 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
548 /* Interface search. */
549 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
551 flog_warn(ZEBRA_ERR_UNKNOWN_INTERFACE
,
552 "RA/RS received on unknown IF %u from %s", ifindex
,
557 if (IS_ZEBRA_DEBUG_PACKET
)
558 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
559 ifp
->ifindex
, len
, addr_str
);
561 if (if_is_loopback(ifp
)
562 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
565 /* Check interface configuration. */
567 if (!zif
->rtadv
.AdvSendAdvertisements
)
570 /* ICMP message length check. */
571 if (len
< sizeof(struct icmp6_hdr
)) {
572 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
573 ifp
->name
, ifp
->ifindex
, len
);
577 icmph
= (struct icmp6_hdr
*)buf
;
579 /* ICMP message type check. */
580 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
581 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
582 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
583 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
587 /* Hoplimit check. */
588 if (hoplimit
>= 0 && hoplimit
!= 255) {
589 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
590 ifp
->ifindex
, hoplimit
);
594 /* Check ICMP message type. */
595 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
596 rtadv_process_solicit(ifp
);
597 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
598 rtadv_process_advert(buf
, len
, ifp
, from
);
603 static int rtadv_read(struct thread
*thread
)
607 uint8_t buf
[RTADV_MSG_SIZE
];
608 struct sockaddr_in6 from
;
609 ifindex_t ifindex
= 0;
611 struct zebra_ns
*zns
= THREAD_ARG(thread
);
613 sock
= THREAD_FD(thread
);
614 zns
->rtadv
.ra_read
= NULL
;
616 /* Register myself. */
617 rtadv_event(zns
, RTADV_READ
, sock
);
619 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
623 flog_err_sys(LIB_ERR_SOCKET
,
624 "RA/RS recv failed, socket %u error %s", sock
,
625 safe_strerror(errno
));
629 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
634 static int rtadv_make_socket(ns_id_t ns_id
)
638 struct icmp6_filter filter
;
640 frr_elevate_privs(&zserv_privs
) {
642 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
650 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
655 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
660 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
665 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
670 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
676 ICMP6_FILTER_SETBLOCKALL(&filter
);
677 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
678 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
680 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
681 sizeof(struct icmp6_filter
));
683 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
691 static struct rtadv_prefix
*rtadv_prefix_new(void)
693 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
696 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
698 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
701 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
702 struct prefix_ipv6
*p
)
704 struct listnode
*node
;
705 struct rtadv_prefix
*rprefix
;
707 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
708 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
714 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
715 struct prefix_ipv6
*p
)
717 struct rtadv_prefix
*rprefix
;
719 rprefix
= rtadv_prefix_lookup(rplist
, p
);
723 rprefix
= rtadv_prefix_new();
724 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
725 listnode_add(rplist
, rprefix
);
730 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
732 struct rtadv_prefix
*rprefix
;
734 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
736 /* Set parameters. */
737 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
738 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
739 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
740 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
741 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
744 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
746 struct rtadv_prefix
*rprefix
;
748 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
749 if (rprefix
!= NULL
) {
750 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
751 rtadv_prefix_free(rprefix
);
757 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
758 ipv6_nd_suppress_ra_status status
)
760 struct zebra_if
*zif
;
761 struct zebra_vrf
*zvrf
;
762 struct zebra_ns
*zns
;
765 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
768 if (status
== RA_SUPPRESS
) {
769 /* RA is currently enabled */
770 if (zif
->rtadv
.AdvSendAdvertisements
) {
771 zif
->rtadv
.AdvSendAdvertisements
= 0;
772 zif
->rtadv
.AdvIntervalTimer
= 0;
773 zns
->rtadv
.adv_if_count
--;
775 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
777 if (zns
->rtadv
.adv_if_count
== 0)
778 rtadv_event(zns
, RTADV_STOP
, 0);
781 if (!zif
->rtadv
.AdvSendAdvertisements
) {
782 zif
->rtadv
.AdvSendAdvertisements
= 1;
783 zif
->rtadv
.AdvIntervalTimer
= 0;
784 zns
->rtadv
.adv_if_count
++;
786 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
787 /* Enable Fast RA only when RA interval is in
789 zif
->rtadv
.inFastRexmit
= 1;
790 zif
->rtadv
.NumFastReXmitsRemain
=
791 RTADV_NUM_FAST_REXMITS
;
794 if_join_all_router(zns
->rtadv
.sock
, ifp
);
796 if (zns
->rtadv
.adv_if_count
== 1)
797 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
803 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
804 * Note that while the client could request RA on an interface on which the
805 * operator has not enabled RA, RA won't be disabled upon client request
806 * if the operator has explicitly enabled RA. The enable request can also
807 * specify a RA interval (in seconds).
809 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
813 struct interface
*ifp
;
814 struct zebra_if
*zif
;
819 /* Get interface index and RA interval. */
820 STREAM_GETL(s
, ifindex
);
821 STREAM_GETL(s
, ra_interval
);
823 if (IS_ZEBRA_DEBUG_EVENT
)
824 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
825 zvrf_id(zvrf
), ifindex
,
826 enable
? "enable" : "disable",
827 zebra_route_string(client
->proto
), ra_interval
);
829 /* Locate interface and check VRF match. */
830 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
832 flog_warn(ZEBRA_ERR_UNKNOWN_INTERFACE
,
833 "%u: IF %u RA %s client %s - interface unknown",
834 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
835 zebra_route_string(client
->proto
));
838 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
840 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
841 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
842 zebra_route_string(client
->proto
), ifp
->vrf_id
);
848 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
849 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
851 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
852 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
853 VTY_RA_INTERVAL_CONFIGURED
))
854 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
856 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
857 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
858 VTY_RA_INTERVAL_CONFIGURED
))
859 zif
->rtadv
.MaxRtrAdvInterval
=
860 RTADV_MAX_RTR_ADV_INTERVAL
;
861 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
862 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
868 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
870 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
872 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
874 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
877 DEFUN (ipv6_nd_suppress_ra
,
878 ipv6_nd_suppress_ra_cmd
,
879 "ipv6 nd suppress-ra",
880 "Interface IPv6 config commands\n"
881 "Neighbor discovery\n"
882 "Suppress Router Advertisement\n")
884 VTY_DECLVAR_CONTEXT(interface
, ifp
);
885 struct zebra_if
*zif
= ifp
->info
;
887 if (if_is_loopback(ifp
)
888 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
890 "Cannot configure IPv6 Router Advertisements on this interface\n");
891 return CMD_WARNING_CONFIG_FAILED
;
894 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
895 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
897 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
901 DEFUN (no_ipv6_nd_suppress_ra
,
902 no_ipv6_nd_suppress_ra_cmd
,
903 "no ipv6 nd suppress-ra",
905 "Interface IPv6 config commands\n"
906 "Neighbor discovery\n"
907 "Suppress Router Advertisement\n")
909 VTY_DECLVAR_CONTEXT(interface
, ifp
);
910 struct zebra_if
*zif
= ifp
->info
;
912 if (if_is_loopback(ifp
)
913 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
915 "Cannot configure IPv6 Router Advertisements on this interface\n");
916 return CMD_WARNING_CONFIG_FAILED
;
919 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
920 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
924 DEFUN (ipv6_nd_ra_interval_msec
,
925 ipv6_nd_ra_interval_msec_cmd
,
926 "ipv6 nd ra-interval msec (70-1800000)",
927 "Interface IPv6 config commands\n"
928 "Neighbor discovery\n"
929 "Router Advertisement interval\n"
930 "Router Advertisement interval in milliseconds\n"
931 "Router Advertisement interval in milliseconds\n")
934 VTY_DECLVAR_CONTEXT(interface
, ifp
);
936 struct zebra_if
*zif
= ifp
->info
;
937 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
938 struct zebra_ns
*zns
;
941 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
942 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
943 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
945 "This ra-interval would conflict with configured ra-lifetime!\n");
946 return CMD_WARNING_CONFIG_FAILED
;
949 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
950 zns
->rtadv
.adv_msec_if_count
--;
953 zns
->rtadv
.adv_msec_if_count
++;
955 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
956 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
957 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
958 zif
->rtadv
.AdvIntervalTimer
= 0;
963 DEFUN (ipv6_nd_ra_interval
,
964 ipv6_nd_ra_interval_cmd
,
965 "ipv6 nd ra-interval (1-1800)",
966 "Interface IPv6 config commands\n"
967 "Neighbor discovery\n"
968 "Router Advertisement interval\n"
969 "Router Advertisement interval in seconds\n")
972 VTY_DECLVAR_CONTEXT(interface
, ifp
);
974 struct zebra_if
*zif
= ifp
->info
;
975 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
976 struct zebra_ns
*zns
;
979 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
980 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
981 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
983 "This ra-interval would conflict with configured ra-lifetime!\n");
984 return CMD_WARNING_CONFIG_FAILED
;
987 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
988 zns
->rtadv
.adv_msec_if_count
--;
990 /* convert to milliseconds */
991 interval
= interval
* 1000;
993 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
994 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
995 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
996 zif
->rtadv
.AdvIntervalTimer
= 0;
1001 DEFUN (no_ipv6_nd_ra_interval
,
1002 no_ipv6_nd_ra_interval_cmd
,
1003 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1005 "Interface IPv6 config commands\n"
1006 "Neighbor discovery\n"
1007 "Router Advertisement interval\n"
1008 "Router Advertisement interval in seconds\n"
1009 "Specify millisecond router advertisement interval\n"
1010 "Router Advertisement interval in milliseconds\n")
1012 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1013 struct zebra_if
*zif
= ifp
->info
;
1014 struct zebra_vrf
*zvrf
;
1015 struct zebra_ns
*zns
;
1017 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1020 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1021 zns
->rtadv
.adv_msec_if_count
--;
1023 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1025 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1026 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1028 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1030 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1031 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1036 DEFUN (ipv6_nd_ra_lifetime
,
1037 ipv6_nd_ra_lifetime_cmd
,
1038 "ipv6 nd ra-lifetime (0-9000)",
1039 "Interface IPv6 config commands\n"
1040 "Neighbor discovery\n"
1042 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1045 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1046 struct zebra_if
*zif
= ifp
->info
;
1049 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1051 /* The value to be placed in the Router Lifetime field
1052 * of Router Advertisements sent from the interface,
1053 * in seconds. MUST be either zero or between
1054 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1055 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1057 "This ra-lifetime would conflict with configured ra-interval\n");
1058 return CMD_WARNING_CONFIG_FAILED
;
1061 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1066 DEFUN (no_ipv6_nd_ra_lifetime
,
1067 no_ipv6_nd_ra_lifetime_cmd
,
1068 "no ipv6 nd ra-lifetime [(0-9000)]",
1070 "Interface IPv6 config commands\n"
1071 "Neighbor discovery\n"
1073 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1075 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1076 struct zebra_if
*zif
= ifp
->info
;
1078 zif
->rtadv
.AdvDefaultLifetime
= -1;
1083 DEFUN (ipv6_nd_reachable_time
,
1084 ipv6_nd_reachable_time_cmd
,
1085 "ipv6 nd reachable-time (1-3600000)",
1086 "Interface IPv6 config commands\n"
1087 "Neighbor discovery\n"
1089 "Reachable time in milliseconds\n")
1092 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1093 struct zebra_if
*zif
= ifp
->info
;
1094 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1098 DEFUN (no_ipv6_nd_reachable_time
,
1099 no_ipv6_nd_reachable_time_cmd
,
1100 "no ipv6 nd reachable-time [(1-3600000)]",
1102 "Interface IPv6 config commands\n"
1103 "Neighbor discovery\n"
1105 "Reachable time in milliseconds\n")
1107 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1108 struct zebra_if
*zif
= ifp
->info
;
1110 zif
->rtadv
.AdvReachableTime
= 0;
1115 DEFUN (ipv6_nd_homeagent_preference
,
1116 ipv6_nd_homeagent_preference_cmd
,
1117 "ipv6 nd home-agent-preference (0-65535)",
1118 "Interface IPv6 config commands\n"
1119 "Neighbor discovery\n"
1120 "Home Agent preference\n"
1121 "preference value (default is 0, least preferred)\n")
1124 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1125 struct zebra_if
*zif
= ifp
->info
;
1126 zif
->rtadv
.HomeAgentPreference
=
1127 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1131 DEFUN (no_ipv6_nd_homeagent_preference
,
1132 no_ipv6_nd_homeagent_preference_cmd
,
1133 "no ipv6 nd home-agent-preference [(0-65535)]",
1135 "Interface IPv6 config commands\n"
1136 "Neighbor discovery\n"
1137 "Home Agent preference\n"
1138 "preference value (default is 0, least preferred)\n")
1140 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1141 struct zebra_if
*zif
= ifp
->info
;
1143 zif
->rtadv
.HomeAgentPreference
= 0;
1148 DEFUN (ipv6_nd_homeagent_lifetime
,
1149 ipv6_nd_homeagent_lifetime_cmd
,
1150 "ipv6 nd home-agent-lifetime (0-65520)",
1151 "Interface IPv6 config commands\n"
1152 "Neighbor discovery\n"
1153 "Home Agent lifetime\n"
1154 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1157 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1158 struct zebra_if
*zif
= ifp
->info
;
1159 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1163 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1164 no_ipv6_nd_homeagent_lifetime_cmd
,
1165 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1167 "Interface IPv6 config commands\n"
1168 "Neighbor discovery\n"
1169 "Home Agent lifetime\n"
1170 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1172 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1173 struct zebra_if
*zif
= ifp
->info
;
1175 zif
->rtadv
.HomeAgentLifetime
= -1;
1180 DEFUN (ipv6_nd_managed_config_flag
,
1181 ipv6_nd_managed_config_flag_cmd
,
1182 "ipv6 nd managed-config-flag",
1183 "Interface IPv6 config commands\n"
1184 "Neighbor discovery\n"
1185 "Managed address configuration flag\n")
1187 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1188 struct zebra_if
*zif
= ifp
->info
;
1190 zif
->rtadv
.AdvManagedFlag
= 1;
1195 DEFUN (no_ipv6_nd_managed_config_flag
,
1196 no_ipv6_nd_managed_config_flag_cmd
,
1197 "no ipv6 nd managed-config-flag",
1199 "Interface IPv6 config commands\n"
1200 "Neighbor discovery\n"
1201 "Managed address configuration flag\n")
1203 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1204 struct zebra_if
*zif
= ifp
->info
;
1206 zif
->rtadv
.AdvManagedFlag
= 0;
1211 DEFUN (ipv6_nd_homeagent_config_flag
,
1212 ipv6_nd_homeagent_config_flag_cmd
,
1213 "ipv6 nd home-agent-config-flag",
1214 "Interface IPv6 config commands\n"
1215 "Neighbor discovery\n"
1216 "Home Agent configuration flag\n")
1218 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1219 struct zebra_if
*zif
= ifp
->info
;
1221 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1226 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1227 no_ipv6_nd_homeagent_config_flag_cmd
,
1228 "no ipv6 nd home-agent-config-flag",
1230 "Interface IPv6 config commands\n"
1231 "Neighbor discovery\n"
1232 "Home Agent configuration flag\n")
1234 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1235 struct zebra_if
*zif
= ifp
->info
;
1237 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1242 DEFUN (ipv6_nd_adv_interval_config_option
,
1243 ipv6_nd_adv_interval_config_option_cmd
,
1244 "ipv6 nd adv-interval-option",
1245 "Interface IPv6 config commands\n"
1246 "Neighbor discovery\n"
1247 "Advertisement Interval Option\n")
1249 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1250 struct zebra_if
*zif
= ifp
->info
;
1252 zif
->rtadv
.AdvIntervalOption
= 1;
1257 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1258 no_ipv6_nd_adv_interval_config_option_cmd
,
1259 "no ipv6 nd adv-interval-option",
1261 "Interface IPv6 config commands\n"
1262 "Neighbor discovery\n"
1263 "Advertisement Interval Option\n")
1265 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1266 struct zebra_if
*zif
= ifp
->info
;
1268 zif
->rtadv
.AdvIntervalOption
= 0;
1273 DEFUN (ipv6_nd_other_config_flag
,
1274 ipv6_nd_other_config_flag_cmd
,
1275 "ipv6 nd other-config-flag",
1276 "Interface IPv6 config commands\n"
1277 "Neighbor discovery\n"
1278 "Other statefull configuration flag\n")
1280 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1281 struct zebra_if
*zif
= ifp
->info
;
1283 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1288 DEFUN (no_ipv6_nd_other_config_flag
,
1289 no_ipv6_nd_other_config_flag_cmd
,
1290 "no ipv6 nd other-config-flag",
1292 "Interface IPv6 config commands\n"
1293 "Neighbor discovery\n"
1294 "Other statefull configuration flag\n")
1296 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1297 struct zebra_if
*zif
= ifp
->info
;
1299 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1304 DEFUN (ipv6_nd_prefix
,
1306 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1307 "Interface IPv6 config commands\n"
1308 "Neighbor discovery\n"
1309 "Prefix information\n"
1311 "Valid lifetime in seconds\n"
1312 "Infinite valid lifetime\n"
1313 "Preferred lifetime in seconds\n"
1314 "Infinite preferred lifetime\n"
1315 "Set Router Address flag\n"
1316 "Do not use prefix for onlink determination\n"
1317 "Do not use prefix for autoconfiguration\n"
1318 "Do not use prefix for autoconfiguration\n"
1319 "Do not use prefix for onlink determination\n")
1322 char *prefix
= argv
[3]->arg
;
1323 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1324 || strmatch(argv
[4]->text
, "infinite"));
1325 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1327 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1329 char *lifetime
= NULL
, *preflifetime
= NULL
;
1330 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1332 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1334 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1339 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1341 offlink
= (argc
> idx_routeropts
+ 1
1342 || strmatch(argv
[idx_routeropts
]->text
,
1344 noautoconf
= (argc
> idx_routeropts
+ 1
1345 || strmatch(argv
[idx_routeropts
]->text
,
1351 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1352 struct zebra_if
*zebra_if
= ifp
->info
;
1354 struct rtadv_prefix rp
;
1356 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1358 vty_out(vty
, "Malformed IPv6 prefix\n");
1359 return CMD_WARNING_CONFIG_FAILED
;
1361 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1362 rp
.AdvOnLinkFlag
= !offlink
;
1363 rp
.AdvAutonomousFlag
= !noautoconf
;
1364 rp
.AdvRouterAddressFlag
= routeraddr
;
1365 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1366 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1369 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1371 : strtoll(lifetime
, NULL
, 10);
1372 rp
.AdvPreferredLifetime
=
1373 strmatch(preflifetime
, "infinite")
1375 : strtoll(preflifetime
, NULL
, 10);
1376 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1377 vty_out(vty
, "Invalid preferred lifetime\n");
1378 return CMD_WARNING_CONFIG_FAILED
;
1382 rtadv_prefix_set(zebra_if
, &rp
);
1387 DEFUN (no_ipv6_nd_prefix
,
1388 no_ipv6_nd_prefix_cmd
,
1389 "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]>]",
1391 "Interface IPv6 config commands\n"
1392 "Neighbor discovery\n"
1393 "Prefix information\n"
1395 "Valid lifetime in seconds\n"
1396 "Infinite valid lifetime\n"
1397 "Preferred lifetime in seconds\n"
1398 "Infinite preferred lifetime\n"
1399 "Set Router Address flag\n"
1400 "Do not use prefix for onlink determination\n"
1401 "Do not use prefix for autoconfiguration\n"
1402 "Do not use prefix for autoconfiguration\n"
1403 "Do not use prefix for onlink determination\n")
1405 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1406 struct zebra_if
*zebra_if
= ifp
->info
;
1408 struct rtadv_prefix rp
;
1409 char *prefix
= argv
[4]->arg
;
1411 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1413 vty_out(vty
, "Malformed IPv6 prefix\n");
1414 return CMD_WARNING_CONFIG_FAILED
;
1416 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1418 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1420 vty_out(vty
, "Non-existant IPv6 prefix\n");
1421 return CMD_WARNING_CONFIG_FAILED
;
1427 DEFUN (ipv6_nd_router_preference
,
1428 ipv6_nd_router_preference_cmd
,
1429 "ipv6 nd router-preference <high|medium|low>",
1430 "Interface IPv6 config commands\n"
1431 "Neighbor discovery\n"
1432 "Default router preference\n"
1433 "High default router preference\n"
1434 "Medium default router preference (default)\n"
1435 "Low default router preference\n")
1437 int idx_high_medium_low
= 3;
1438 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1439 struct zebra_if
*zif
= ifp
->info
;
1442 while (0 != rtadv_pref_strs
[i
]) {
1443 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1446 zif
->rtadv
.DefaultPreference
= i
;
1452 return CMD_ERR_NO_MATCH
;
1455 DEFUN (no_ipv6_nd_router_preference
,
1456 no_ipv6_nd_router_preference_cmd
,
1457 "no ipv6 nd router-preference [<high|medium|low>]",
1459 "Interface IPv6 config commands\n"
1460 "Neighbor discovery\n"
1461 "Default router preference\n"
1462 "High default router preference\n"
1463 "Medium default router preference (default)\n"
1464 "Low default router preference\n")
1466 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1467 struct zebra_if
*zif
= ifp
->info
;
1469 zif
->rtadv
.DefaultPreference
=
1470 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1477 "ipv6 nd mtu (1-65535)",
1478 "Interface IPv6 config commands\n"
1479 "Neighbor discovery\n"
1484 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1485 struct zebra_if
*zif
= ifp
->info
;
1486 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1490 DEFUN (no_ipv6_nd_mtu
,
1492 "no ipv6 nd mtu [(1-65535)]",
1494 "Interface IPv6 config commands\n"
1495 "Neighbor discovery\n"
1499 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1500 struct zebra_if
*zif
= ifp
->info
;
1501 zif
->rtadv
.AdvLinkMTU
= 0;
1505 /* Dump interface ND information to vty. */
1506 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1508 struct zebra_if
*zif
;
1509 struct rtadvconf
*rtadv
;
1512 zif
= (struct zebra_if
*)ifp
->info
;
1513 rtadv
= &zif
->rtadv
;
1515 if (rtadv
->AdvSendAdvertisements
) {
1517 " ND advertised reachable time is %d milliseconds\n",
1518 rtadv
->AdvReachableTime
);
1520 " ND advertised retransmit interval is %d milliseconds\n",
1521 rtadv
->AdvRetransTimer
);
1522 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1523 zif
->ra_sent
, zif
->ra_rcvd
);
1524 interval
= rtadv
->MaxRtrAdvInterval
;
1525 if (interval
% 1000)
1527 " ND router advertisements are sent every "
1528 "%d milliseconds\n",
1532 " ND router advertisements are sent every "
1535 if (rtadv
->AdvDefaultLifetime
!= -1)
1537 " ND router advertisements live for %d seconds\n",
1538 rtadv
->AdvDefaultLifetime
);
1541 " ND router advertisements lifetime tracks ra-interval\n");
1543 " ND router advertisement default router preference is "
1545 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1546 if (rtadv
->AdvManagedFlag
)
1548 " Hosts use DHCP to obtain routable addresses.\n");
1551 " Hosts use stateless autoconfig for addresses.\n");
1552 if (rtadv
->AdvHomeAgentFlag
) {
1554 " ND router advertisements with Home Agent flag bit set.\n");
1555 if (rtadv
->HomeAgentLifetime
!= -1)
1557 " Home Agent lifetime is %u seconds\n",
1558 rtadv
->HomeAgentLifetime
);
1561 " Home Agent lifetime tracks ra-lifetime\n");
1562 vty_out(vty
, " Home Agent preference is %u\n",
1563 rtadv
->HomeAgentPreference
);
1565 if (rtadv
->AdvIntervalOption
)
1567 " ND router advertisements with Adv. Interval option.\n");
1573 /* Write configuration about router advertisement. */
1574 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1576 struct zebra_if
*zif
;
1577 struct listnode
*node
;
1578 struct rtadv_prefix
*rprefix
;
1579 char buf
[PREFIX_STRLEN
];
1584 if (!(if_is_loopback(ifp
)
1585 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1586 if (zif
->rtadv
.AdvSendAdvertisements
1587 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1588 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1591 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1592 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
1593 if (interval
% 1000)
1594 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
1596 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1597 vty_out(vty
, " ipv6 nd ra-interval %d\n",
1601 if (zif
->rtadv
.AdvIntervalOption
)
1602 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1604 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1605 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1606 zif
->rtadv
.AdvDefaultLifetime
);
1608 if (zif
->rtadv
.HomeAgentPreference
)
1609 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1610 zif
->rtadv
.HomeAgentPreference
);
1612 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1613 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1614 zif
->rtadv
.HomeAgentLifetime
);
1616 if (zif
->rtadv
.AdvHomeAgentFlag
)
1617 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1619 if (zif
->rtadv
.AdvReachableTime
)
1620 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1621 zif
->rtadv
.AdvReachableTime
);
1623 if (zif
->rtadv
.AdvManagedFlag
)
1624 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1626 if (zif
->rtadv
.AdvOtherConfigFlag
)
1627 vty_out(vty
, " ipv6 nd other-config-flag\n");
1629 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1630 vty_out(vty
, " ipv6 nd router-preference %s\n",
1631 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1633 if (zif
->rtadv
.AdvLinkMTU
)
1634 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1636 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1637 vty_out(vty
, " ipv6 nd prefix %s",
1638 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1639 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1640 || (rprefix
->AdvPreferredLifetime
1641 != RTADV_PREFERRED_LIFETIME
)) {
1642 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1643 vty_out(vty
, " infinite");
1645 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1646 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1647 vty_out(vty
, " infinite");
1650 rprefix
->AdvPreferredLifetime
);
1652 if (!rprefix
->AdvOnLinkFlag
)
1653 vty_out(vty
, " off-link");
1654 if (!rprefix
->AdvAutonomousFlag
)
1655 vty_out(vty
, " no-autoconfig");
1656 if (rprefix
->AdvRouterAddressFlag
)
1657 vty_out(vty
, " router-address");
1664 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1666 struct rtadv
*rtadv
= &zns
->rtadv
;
1670 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1672 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1676 if (rtadv
->ra_timer
) {
1677 thread_cancel(rtadv
->ra_timer
);
1678 rtadv
->ra_timer
= NULL
;
1680 if (rtadv
->ra_read
) {
1681 thread_cancel(rtadv
->ra_read
);
1682 rtadv
->ra_read
= NULL
;
1686 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1689 case RTADV_TIMER_MSEC
:
1690 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1694 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1703 void rtadv_init(struct zebra_ns
*zns
)
1705 zns
->rtadv
.sock
= rtadv_make_socket(zns
->ns_id
);
1708 void rtadv_terminate(struct zebra_ns
*zns
)
1710 rtadv_event(zns
, RTADV_STOP
, 0);
1711 if (zns
->rtadv
.sock
>= 0) {
1712 close(zns
->rtadv
.sock
);
1713 zns
->rtadv
.sock
= -1;
1716 zns
->rtadv
.adv_if_count
= 0;
1717 zns
->rtadv
.adv_msec_if_count
= 0;
1720 void rtadv_cmd_init(void)
1722 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1723 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1725 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1726 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1727 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1728 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1729 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1730 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1731 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1732 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1733 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1734 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1735 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1736 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1737 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1738 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1739 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1740 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1741 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1742 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1743 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1744 install_element(INTERFACE_NODE
,
1745 &ipv6_nd_adv_interval_config_option_cmd
);
1746 install_element(INTERFACE_NODE
,
1747 &no_ipv6_nd_adv_interval_config_option_cmd
);
1748 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1749 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1750 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1751 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1752 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1753 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1756 static int if_join_all_router(int sock
, struct interface
*ifp
)
1760 struct ipv6_mreq mreq
;
1762 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1763 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1764 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1766 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1769 flog_err_sys(LIB_ERR_SOCKET
,
1770 "%s(%u): Failed to join group, socket %u error %s",
1771 ifp
->name
, ifp
->ifindex
, sock
,
1772 safe_strerror(errno
));
1774 if (IS_ZEBRA_DEBUG_EVENT
)
1776 "%s(%u): Join All-Routers multicast group, socket %u",
1777 ifp
->name
, ifp
->ifindex
, sock
);
1782 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1786 struct ipv6_mreq mreq
;
1788 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1789 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1790 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1792 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1797 "%s(%u): Failed to leave group, socket %u error %s",
1798 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1800 if (IS_ZEBRA_DEBUG_EVENT
)
1802 "%s(%u): Leave All-Routers multicast group, socket %u",
1803 ifp
->name
, ifp
->ifindex
, sock
);
1809 void rtadv_init(struct zebra_ns
*zns
)
1813 void rtadv_terminate(struct zebra_ns
*zns
)
1817 void rtadv_cmd_init(void)
1821 #endif /* HAVE_RTADV */