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 "zebra/interface.h"
39 #include "zebra/rtadv.h"
40 #include "zebra/debug.h"
41 #include "zebra/rib.h"
42 #include "zebra/zserv.h"
43 #include "zebra/zebra_ns.h"
44 #include "zebra/zebra_vrf.h"
46 extern struct zebra_privs_t zserv_privs
;
48 #if defined(HAVE_RTADV)
51 #include <netinet/icmp6.h>
54 /* If RFC2133 definition is used. */
55 #ifndef IPV6_JOIN_GROUP
56 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
58 #ifndef IPV6_LEAVE_GROUP
59 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
62 #define ALLNODE "ff02::1"
63 #define ALLROUTER "ff02::2"
65 /* Order is intentional. Matches RFC4191. This array is also used for
66 command matching, so only modify with care. */
67 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
77 static void rtadv_event(struct zebra_ns
*, enum rtadv_event
, int);
79 static int if_join_all_router(int, struct interface
*);
80 static int if_leave_all_router(int, struct interface
*);
82 static int rtadv_increment_received(struct zebra_ns
*zns
, ifindex_t
*ifindex
)
85 struct interface
*iface
;
88 iface
= if_lookup_by_index_per_ns(zns
, *ifindex
);
89 if (iface
&& iface
->info
) {
97 static int rtadv_recv_packet(struct zebra_ns
*zns
, int sock
, u_char
*buf
,
98 int buflen
, struct sockaddr_in6
*from
,
99 ifindex_t
*ifindex
, int *hoplimit
)
104 struct cmsghdr
*cmsgptr
;
109 /* Fill in message and iovec. */
110 memset(&msg
, 0, sizeof(msg
));
111 msg
.msg_name
= (void *)from
;
112 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
115 msg
.msg_control
= (void *)adata
;
116 msg
.msg_controllen
= sizeof adata
;
118 iov
.iov_len
= buflen
;
120 /* If recvmsg fail return minus value. */
121 ret
= recvmsg(sock
, &msg
, 0);
125 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
126 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
127 /* I want interface index which this packet comes from. */
128 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
129 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
130 struct in6_pktinfo
*ptr
;
132 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
133 *ifindex
= ptr
->ipi6_ifindex
;
134 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
137 /* Incoming packet's hop limit. */
138 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
139 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
140 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
145 rtadv_increment_received(zns
, ifindex
);
149 #define RTADV_MSG_SIZE 4096
151 /* Send router advertisement packet. */
152 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
156 struct cmsghdr
*cmsgptr
;
157 struct in6_pktinfo
*pkt
;
158 struct sockaddr_in6 addr
;
159 static void *adata
= NULL
;
160 unsigned char buf
[RTADV_MSG_SIZE
];
161 struct nd_router_advert
*rtadv
;
164 struct zebra_if
*zif
;
165 struct rtadv_prefix
*rprefix
;
166 u_char all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
167 0, 0, 0, 0, 0, 0, 0, 1};
168 struct listnode
*node
;
169 u_int16_t pkt_RouterLifetime
;
172 * Allocate control message bufffer. This is dynamic because
173 * CMSG_SPACE is not guaranteed not to call a function. Note that
174 * the size will be different on different architectures due to
175 * differing alignment rules.
178 /* XXX Free on shutdown. */
179 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
183 "rtadv_send_packet: can't malloc control data");
188 /* Logging of packet. */
189 if (IS_ZEBRA_DEBUG_PACKET
)
190 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
193 /* Fill in sockaddr_in6. */
194 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
195 addr
.sin6_family
= AF_INET6
;
197 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
198 #endif /* SIN6_LEN */
199 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
200 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
202 /* Fetch interface information. */
205 /* Make router advertisement message. */
206 rtadv
= (struct nd_router_advert
*)buf
;
208 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
209 rtadv
->nd_ra_code
= 0;
210 rtadv
->nd_ra_cksum
= 0;
212 rtadv
->nd_ra_curhoplimit
= 64;
214 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
215 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
217 : zif
->rtadv
.DefaultPreference
;
218 rtadv
->nd_ra_flags_reserved
<<= 3;
220 if (zif
->rtadv
.AdvManagedFlag
)
221 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
222 if (zif
->rtadv
.AdvOtherConfigFlag
)
223 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
224 if (zif
->rtadv
.AdvHomeAgentFlag
)
225 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
226 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
227 * AdvDefaultLifetime is by default based on the value of
228 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
229 * field of Router Advertisements. Given that this field is expressed
230 * in seconds, a small MaxRtrAdvInterval value can result in a zero
231 * value for this field. To prevent this, routers SHOULD keep
232 * AdvDefaultLifetime in at least one second, even if the use of
233 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
235 zif
->rtadv
.AdvDefaultLifetime
!= -1
236 ? zif
->rtadv
.AdvDefaultLifetime
237 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
238 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
239 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
240 rtadv
->nd_ra_retransmit
= htonl(0);
242 len
= sizeof(struct nd_router_advert
);
244 /* If both the Home Agent Preference and Home Agent Lifetime are set to
245 * their default values specified above, this option SHOULD NOT be
246 * included in the Router Advertisement messages sent by this home
247 * agent. -- RFC6275, 7.4 */
248 if (zif
->rtadv
.AdvHomeAgentFlag
249 && (zif
->rtadv
.HomeAgentPreference
250 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
251 struct nd_opt_homeagent_info
*ndopt_hai
=
252 (struct nd_opt_homeagent_info
*)(buf
+ len
);
253 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
254 ndopt_hai
->nd_opt_hai_len
= 1;
255 ndopt_hai
->nd_opt_hai_reserved
= 0;
256 ndopt_hai
->nd_opt_hai_preference
=
257 htons(zif
->rtadv
.HomeAgentPreference
);
258 /* 16-bit unsigned integer. The lifetime associated with the
260 * agent in units of seconds. The default value is the same as
262 * Router Lifetime, as specified in the main body of the Router
263 * Advertisement. The maximum value corresponds to 18.2 hours.
265 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
266 ndopt_hai
->nd_opt_hai_lifetime
=
267 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
268 ? zif
->rtadv
.HomeAgentLifetime
269 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
274 len
+= sizeof(struct nd_opt_homeagent_info
);
277 if (zif
->rtadv
.AdvIntervalOption
) {
278 struct nd_opt_adv_interval
*ndopt_adv
=
279 (struct nd_opt_adv_interval
*)(buf
+ len
);
280 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
281 ndopt_adv
->nd_opt_ai_len
= 1;
282 ndopt_adv
->nd_opt_ai_reserved
= 0;
283 ndopt_adv
->nd_opt_ai_interval
=
284 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
285 len
+= sizeof(struct nd_opt_adv_interval
);
288 /* Fill in prefix. */
289 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
290 struct nd_opt_prefix_info
*pinfo
;
292 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
294 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
295 pinfo
->nd_opt_pi_len
= 4;
296 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
298 pinfo
->nd_opt_pi_flags_reserved
= 0;
299 if (rprefix
->AdvOnLinkFlag
)
300 pinfo
->nd_opt_pi_flags_reserved
|=
301 ND_OPT_PI_FLAG_ONLINK
;
302 if (rprefix
->AdvAutonomousFlag
)
303 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
304 if (rprefix
->AdvRouterAddressFlag
)
305 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
307 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
308 pinfo
->nd_opt_pi_preferred_time
=
309 htonl(rprefix
->AdvPreferredLifetime
);
310 pinfo
->nd_opt_pi_reserved2
= 0;
312 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
313 &rprefix
->prefix
.prefix
);
317 u_char buf
[INET6_ADDRSTRLEN
];
319 zlog_debug("DEBUG %s",
320 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
321 buf
, INET6_ADDRSTRLEN
));
325 len
+= sizeof(struct nd_opt_prefix_info
);
328 /* Hardware address. */
329 if (ifp
->hw_addr_len
!= 0) {
330 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
332 /* Option length should be rounded up to next octet if
333 the link address does not end on an octet boundary. */
334 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
336 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
337 len
+= ifp
->hw_addr_len
;
339 /* Pad option to end on an octet boundary. */
340 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
341 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
345 if (zif
->rtadv
.AdvLinkMTU
) {
346 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
347 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
348 opt
->nd_opt_mtu_len
= 1;
349 opt
->nd_opt_mtu_reserved
= 0;
350 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
351 len
+= sizeof(struct nd_opt_mtu
);
354 msg
.msg_name
= (void *)&addr
;
355 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
358 msg
.msg_control
= (void *)adata
;
359 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
364 cmsgptr
= ZCMSG_FIRSTHDR(&msg
);
365 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
366 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
367 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
369 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
370 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
371 pkt
->ipi6_ifindex
= ifp
->ifindex
;
373 ret
= sendmsg(sock
, &msg
, 0);
375 zlog_err("%s(%u): Tx RA failed, socket %u error %d (%s)",
376 ifp
->name
, ifp
->ifindex
, sock
, errno
,
377 safe_strerror(errno
));
382 static int rtadv_timer(struct thread
*thread
)
384 struct zebra_ns
*zns
= THREAD_ARG(thread
);
386 struct interface
*ifp
;
387 struct zebra_if
*zif
;
390 zns
->rtadv
.ra_timer
= NULL
;
391 if (zns
->rtadv
.adv_msec_if_count
== 0) {
392 period
= 1000; /* 1 s */
393 rtadv_event(zns
, RTADV_TIMER
, 1 /* 1 s */);
395 period
= 10; /* 10 ms */
396 rtadv_event(zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
399 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
400 RB_FOREACH (ifp
, if_name_head
, &vrf
->ifaces_by_name
) {
401 if (if_is_loopback(ifp
)
402 || CHECK_FLAG(ifp
->status
,
403 ZEBRA_INTERFACE_VRF_LOOPBACK
)
404 || !if_is_operative(ifp
))
409 if (zif
->rtadv
.AdvSendAdvertisements
) {
410 if (zif
->rtadv
.inFastRexmit
) {
411 /* We assume we fast rexmit every sec so
414 if (--zif
->rtadv
.NumFastReXmitsRemain
416 zif
->rtadv
.inFastRexmit
= 0;
418 if (IS_ZEBRA_DEBUG_SEND
)
420 "Fast RA Rexmit on interface %s",
423 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
425 zif
->rtadv
.AdvIntervalTimer
-= period
;
426 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
428 MaxRtrAdvInterval each
429 time isn't what section
430 6.2.4 of RFC4861 tells to do.
432 zif
->rtadv
.AdvIntervalTimer
=
436 zns
->rtadv
.sock
, ifp
);
445 static void rtadv_process_solicit(struct interface
*ifp
)
447 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
448 struct zebra_ns
*zns
= zvrf
->zns
;
451 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
454 static void rtadv_process_advert(u_char
*msg
, unsigned int len
,
455 struct interface
*ifp
,
456 struct sockaddr_in6
*addr
)
458 struct nd_router_advert
*radvert
;
459 char addr_str
[INET6_ADDRSTRLEN
];
460 struct zebra_if
*zif
;
465 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
467 if (len
< sizeof(struct nd_router_advert
)) {
468 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
469 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
472 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
474 "%s(%u): Rx RA with non-linklocal source address from %s",
475 ifp
->name
, ifp
->ifindex
, addr_str
);
479 radvert
= (struct nd_router_advert
*)msg
;
481 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
482 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
484 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
485 ifp
->name
, ifp
->ifindex
, addr_str
);
488 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
489 && !zif
->rtadv
.AdvManagedFlag
) {
491 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
492 ifp
->name
, ifp
->ifindex
, addr_str
);
495 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
496 && !zif
->rtadv
.AdvOtherConfigFlag
) {
498 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
499 ifp
->name
, ifp
->ifindex
, addr_str
);
502 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
503 && (ntohl(radvert
->nd_ra_reachable
)
504 != zif
->rtadv
.AdvReachableTime
)) {
506 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
507 ifp
->name
, ifp
->ifindex
, addr_str
);
510 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
511 && (ntohl(radvert
->nd_ra_retransmit
)
512 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
514 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
515 ifp
->name
, ifp
->ifindex
, addr_str
);
518 /* Create entry for neighbor if not known. */
520 IPV6_ADDR_COPY(&p
.u
.prefix
, &addr
->sin6_addr
);
521 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
523 if (!nbr_connected_check(ifp
, &p
))
524 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
528 static void rtadv_process_packet(u_char
*buf
, unsigned int len
,
529 ifindex_t ifindex
, int hoplimit
,
530 struct sockaddr_in6
*from
,
531 struct zebra_ns
*zns
)
533 struct icmp6_hdr
*icmph
;
534 struct interface
*ifp
;
535 struct zebra_if
*zif
;
536 char addr_str
[INET6_ADDRSTRLEN
];
538 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
540 /* Interface search. */
541 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
543 zlog_warn("RA/RS received on unknown IF %u from %s", ifindex
,
548 if (IS_ZEBRA_DEBUG_PACKET
)
549 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
550 ifp
->ifindex
, len
, addr_str
);
552 if (if_is_loopback(ifp
)
553 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
556 /* Check interface configuration. */
558 if (!zif
->rtadv
.AdvSendAdvertisements
)
561 /* ICMP message length check. */
562 if (len
< sizeof(struct icmp6_hdr
)) {
563 zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
564 ifp
->name
, ifp
->ifindex
, len
);
568 icmph
= (struct icmp6_hdr
*)buf
;
570 /* ICMP message type check. */
571 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
572 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
573 zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
574 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
578 /* Hoplimit check. */
579 if (hoplimit
>= 0 && hoplimit
!= 255) {
580 zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
581 ifp
->ifindex
, hoplimit
);
585 /* Check ICMP message type. */
586 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
587 rtadv_process_solicit(ifp
);
588 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
589 rtadv_process_advert(buf
, len
, ifp
, from
);
594 static int rtadv_read(struct thread
*thread
)
598 u_char buf
[RTADV_MSG_SIZE
];
599 struct sockaddr_in6 from
;
600 ifindex_t ifindex
= 0;
602 struct zebra_ns
*zns
= THREAD_ARG(thread
);
604 sock
= THREAD_FD(thread
);
605 zns
->rtadv
.ra_read
= NULL
;
607 /* Register myself. */
608 rtadv_event(zns
, RTADV_READ
, sock
);
610 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
614 zlog_warn("RA/RS recv failed, socket %u error %s", sock
,
615 safe_strerror(errno
));
619 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
624 static int rtadv_make_socket(void)
628 struct icmp6_filter filter
;
630 if (zserv_privs
.change(ZPRIVS_RAISE
))
631 zlog_err("rtadv_make_socket: could not raise privs, %s",
632 safe_strerror(errno
));
634 sock
= socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
636 if (zserv_privs
.change(ZPRIVS_LOWER
))
637 zlog_err("rtadv_make_socket: could not lower privs, %s",
638 safe_strerror(errno
));
644 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
649 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
654 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
659 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
664 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
670 ICMP6_FILTER_SETBLOCKALL(&filter
);
671 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
672 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
674 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
675 sizeof(struct icmp6_filter
));
677 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
684 static struct rtadv_prefix
*rtadv_prefix_new(void)
686 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
689 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
691 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
694 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
695 struct prefix_ipv6
*p
)
697 struct listnode
*node
;
698 struct rtadv_prefix
*rprefix
;
700 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
701 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
707 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
708 struct prefix_ipv6
*p
)
710 struct rtadv_prefix
*rprefix
;
712 rprefix
= rtadv_prefix_lookup(rplist
, p
);
716 rprefix
= rtadv_prefix_new();
717 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
718 listnode_add(rplist
, rprefix
);
723 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
725 struct rtadv_prefix
*rprefix
;
727 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
729 /* Set parameters. */
730 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
731 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
732 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
733 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
734 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
737 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
739 struct rtadv_prefix
*rprefix
;
741 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
742 if (rprefix
!= NULL
) {
743 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
744 rtadv_prefix_free(rprefix
);
750 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
751 ipv6_nd_suppress_ra_status status
)
753 struct zebra_if
*zif
;
754 struct zebra_vrf
*zvrf
;
755 struct zebra_ns
*zns
;
758 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
761 if (status
== RA_SUPPRESS
) {
762 /* RA is currently enabled */
763 if (zif
->rtadv
.AdvSendAdvertisements
) {
764 zif
->rtadv
.AdvSendAdvertisements
= 0;
765 zif
->rtadv
.AdvIntervalTimer
= 0;
766 zns
->rtadv
.adv_if_count
--;
768 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
770 if (zns
->rtadv
.adv_if_count
== 0)
771 rtadv_event(zns
, RTADV_STOP
, 0);
774 if (!zif
->rtadv
.AdvSendAdvertisements
) {
775 zif
->rtadv
.AdvSendAdvertisements
= 1;
776 zif
->rtadv
.AdvIntervalTimer
= 0;
777 zns
->rtadv
.adv_if_count
++;
779 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
780 /* Enable Fast RA only when RA interval is in
782 zif
->rtadv
.inFastRexmit
= 1;
783 zif
->rtadv
.NumFastReXmitsRemain
=
784 RTADV_NUM_FAST_REXMITS
;
787 if_join_all_router(zns
->rtadv
.sock
, ifp
);
789 if (zns
->rtadv
.adv_if_count
== 1)
790 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
796 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
797 * Note that while the client could request RA on an interface on which the
798 * operator has not enabled RA, RA won't be disabled upon client request
799 * if the operator has explicitly enabled RA. The enable request can also
800 * specify a RA interval (in seconds).
802 void zebra_interface_radv_set(struct zserv
*client
, int sock
, u_short length
,
803 struct zebra_vrf
*zvrf
, int enable
)
806 unsigned int ifindex
;
807 struct interface
*ifp
;
808 struct zebra_if
*zif
;
813 /* Get interface index and RA interval. */
814 ifindex
= stream_getl(s
);
815 ra_interval
= stream_getl(s
);
817 if (IS_ZEBRA_DEBUG_EVENT
)
818 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
819 zvrf_id(zvrf
), ifindex
,
820 enable
? "enable" : "disable",
821 zebra_route_string(client
->proto
), ra_interval
);
823 /* Locate interface and check VRF match. */
824 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
826 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
827 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
828 zebra_route_string(client
->proto
));
831 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
832 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
833 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
834 zebra_route_string(client
->proto
), ifp
->vrf_id
);
840 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
842 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
)
843 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
845 if (!zif
->rtadv
.configured
) {
846 zif
->rtadv
.MaxRtrAdvInterval
=
847 RTADV_MAX_RTR_ADV_INTERVAL
;
848 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
853 DEFUN (ipv6_nd_suppress_ra
,
854 ipv6_nd_suppress_ra_cmd
,
855 "ipv6 nd suppress-ra",
856 "Interface IPv6 config commands\n"
857 "Neighbor discovery\n"
858 "Suppress Router Advertisement\n")
860 VTY_DECLVAR_CONTEXT(interface
, ifp
);
861 struct zebra_if
*zif
= ifp
->info
;
863 if (if_is_loopback(ifp
)
864 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
866 "Cannot configure IPv6 Router Advertisements on this interface\n");
867 return CMD_WARNING_CONFIG_FAILED
;
870 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
871 zif
->rtadv
.configured
= 0;
875 DEFUN (no_ipv6_nd_suppress_ra
,
876 no_ipv6_nd_suppress_ra_cmd
,
877 "no ipv6 nd suppress-ra",
879 "Interface IPv6 config commands\n"
880 "Neighbor discovery\n"
881 "Suppress Router Advertisement\n")
883 VTY_DECLVAR_CONTEXT(interface
, ifp
);
884 struct zebra_if
*zif
= ifp
->info
;
886 if (if_is_loopback(ifp
)
887 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
889 "Cannot configure IPv6 Router Advertisements on this interface\n");
890 return CMD_WARNING_CONFIG_FAILED
;
893 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
894 zif
->rtadv
.configured
= 1;
898 DEFUN (ipv6_nd_ra_interval_msec
,
899 ipv6_nd_ra_interval_msec_cmd
,
900 "ipv6 nd ra-interval msec (70-1800000)",
901 "Interface IPv6 config commands\n"
902 "Neighbor discovery\n"
903 "Router Advertisement interval\n"
904 "Router Advertisement interval in milliseconds\n"
905 "Router Advertisement interval in milliseconds\n")
908 VTY_DECLVAR_CONTEXT(interface
, ifp
);
910 struct zebra_if
*zif
= ifp
->info
;
911 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
912 struct zebra_ns
*zns
;
915 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
916 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
917 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
919 "This ra-interval would conflict with configured ra-lifetime!\n");
920 return CMD_WARNING_CONFIG_FAILED
;
923 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
924 zns
->rtadv
.adv_msec_if_count
--;
927 zns
->rtadv
.adv_msec_if_count
++;
929 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
930 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
931 zif
->rtadv
.AdvIntervalTimer
= 0;
936 DEFUN (ipv6_nd_ra_interval
,
937 ipv6_nd_ra_interval_cmd
,
938 "ipv6 nd ra-interval (1-1800)",
939 "Interface IPv6 config commands\n"
940 "Neighbor discovery\n"
941 "Router Advertisement interval\n"
942 "Router Advertisement interval in seconds\n")
945 VTY_DECLVAR_CONTEXT(interface
, ifp
);
947 struct zebra_if
*zif
= ifp
->info
;
948 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
949 struct zebra_ns
*zns
;
952 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
953 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
954 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
956 "This ra-interval would conflict with configured ra-lifetime!\n");
957 return CMD_WARNING_CONFIG_FAILED
;
960 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
961 zns
->rtadv
.adv_msec_if_count
--;
963 /* convert to milliseconds */
964 interval
= interval
* 1000;
966 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
967 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
968 zif
->rtadv
.AdvIntervalTimer
= 0;
973 DEFUN (no_ipv6_nd_ra_interval
,
974 no_ipv6_nd_ra_interval_cmd
,
975 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
977 "Interface IPv6 config commands\n"
978 "Neighbor discovery\n"
979 "Router Advertisement interval\n"
980 "Router Advertisement interval in seconds\n"
981 "Specify millisecond router advertisement interval\n"
982 "Router Advertisement interval in milliseconds\n")
984 VTY_DECLVAR_CONTEXT(interface
, ifp
);
985 struct zebra_if
*zif
= ifp
->info
;
986 struct zebra_vrf
*zvrf
;
987 struct zebra_ns
*zns
;
989 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
992 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
993 zns
->rtadv
.adv_msec_if_count
--;
995 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
996 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
997 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1002 DEFUN (ipv6_nd_ra_lifetime
,
1003 ipv6_nd_ra_lifetime_cmd
,
1004 "ipv6 nd ra-lifetime (0-9000)",
1005 "Interface IPv6 config commands\n"
1006 "Neighbor discovery\n"
1008 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1011 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1012 struct zebra_if
*zif
= ifp
->info
;
1015 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1017 /* The value to be placed in the Router Lifetime field
1018 * of Router Advertisements sent from the interface,
1019 * in seconds. MUST be either zero or between
1020 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1021 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1023 "This ra-lifetime would conflict with configured ra-interval\n");
1024 return CMD_WARNING_CONFIG_FAILED
;
1027 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1032 DEFUN (no_ipv6_nd_ra_lifetime
,
1033 no_ipv6_nd_ra_lifetime_cmd
,
1034 "no ipv6 nd ra-lifetime [(0-9000)]",
1036 "Interface IPv6 config commands\n"
1037 "Neighbor discovery\n"
1039 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1041 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1042 struct zebra_if
*zif
= ifp
->info
;
1044 zif
->rtadv
.AdvDefaultLifetime
= -1;
1049 DEFUN (ipv6_nd_reachable_time
,
1050 ipv6_nd_reachable_time_cmd
,
1051 "ipv6 nd reachable-time (1-3600000)",
1052 "Interface IPv6 config commands\n"
1053 "Neighbor discovery\n"
1055 "Reachable time in milliseconds\n")
1058 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1059 struct zebra_if
*zif
= ifp
->info
;
1060 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1064 DEFUN (no_ipv6_nd_reachable_time
,
1065 no_ipv6_nd_reachable_time_cmd
,
1066 "no ipv6 nd reachable-time [(1-3600000)]",
1068 "Interface IPv6 config commands\n"
1069 "Neighbor discovery\n"
1071 "Reachable time in milliseconds\n")
1073 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1074 struct zebra_if
*zif
= ifp
->info
;
1076 zif
->rtadv
.AdvReachableTime
= 0;
1081 DEFUN (ipv6_nd_homeagent_preference
,
1082 ipv6_nd_homeagent_preference_cmd
,
1083 "ipv6 nd home-agent-preference (0-65535)",
1084 "Interface IPv6 config commands\n"
1085 "Neighbor discovery\n"
1086 "Home Agent preference\n"
1087 "preference value (default is 0, least preferred)\n")
1090 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1091 struct zebra_if
*zif
= ifp
->info
;
1092 zif
->rtadv
.HomeAgentPreference
=
1093 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1097 DEFUN (no_ipv6_nd_homeagent_preference
,
1098 no_ipv6_nd_homeagent_preference_cmd
,
1099 "no ipv6 nd home-agent-preference [(0-65535)]",
1101 "Interface IPv6 config commands\n"
1102 "Neighbor discovery\n"
1103 "Home Agent preference\n"
1104 "preference value (default is 0, least preferred)\n")
1106 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1107 struct zebra_if
*zif
= ifp
->info
;
1109 zif
->rtadv
.HomeAgentPreference
= 0;
1114 DEFUN (ipv6_nd_homeagent_lifetime
,
1115 ipv6_nd_homeagent_lifetime_cmd
,
1116 "ipv6 nd home-agent-lifetime (0-65520)",
1117 "Interface IPv6 config commands\n"
1118 "Neighbor discovery\n"
1119 "Home Agent lifetime\n"
1120 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1123 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1124 struct zebra_if
*zif
= ifp
->info
;
1125 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1129 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1130 no_ipv6_nd_homeagent_lifetime_cmd
,
1131 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1133 "Interface IPv6 config commands\n"
1134 "Neighbor discovery\n"
1135 "Home Agent lifetime\n"
1136 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1138 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1139 struct zebra_if
*zif
= ifp
->info
;
1141 zif
->rtadv
.HomeAgentLifetime
= -1;
1146 DEFUN (ipv6_nd_managed_config_flag
,
1147 ipv6_nd_managed_config_flag_cmd
,
1148 "ipv6 nd managed-config-flag",
1149 "Interface IPv6 config commands\n"
1150 "Neighbor discovery\n"
1151 "Managed address configuration flag\n")
1153 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1154 struct zebra_if
*zif
= ifp
->info
;
1156 zif
->rtadv
.AdvManagedFlag
= 1;
1161 DEFUN (no_ipv6_nd_managed_config_flag
,
1162 no_ipv6_nd_managed_config_flag_cmd
,
1163 "no ipv6 nd managed-config-flag",
1165 "Interface IPv6 config commands\n"
1166 "Neighbor discovery\n"
1167 "Managed address configuration flag\n")
1169 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1170 struct zebra_if
*zif
= ifp
->info
;
1172 zif
->rtadv
.AdvManagedFlag
= 0;
1177 DEFUN (ipv6_nd_homeagent_config_flag
,
1178 ipv6_nd_homeagent_config_flag_cmd
,
1179 "ipv6 nd home-agent-config-flag",
1180 "Interface IPv6 config commands\n"
1181 "Neighbor discovery\n"
1182 "Home Agent configuration flag\n")
1184 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1185 struct zebra_if
*zif
= ifp
->info
;
1187 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1192 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1193 no_ipv6_nd_homeagent_config_flag_cmd
,
1194 "no ipv6 nd home-agent-config-flag",
1196 "Interface IPv6 config commands\n"
1197 "Neighbor discovery\n"
1198 "Home Agent configuration flag\n")
1200 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1201 struct zebra_if
*zif
= ifp
->info
;
1203 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1208 DEFUN (ipv6_nd_adv_interval_config_option
,
1209 ipv6_nd_adv_interval_config_option_cmd
,
1210 "ipv6 nd adv-interval-option",
1211 "Interface IPv6 config commands\n"
1212 "Neighbor discovery\n"
1213 "Advertisement Interval Option\n")
1215 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1216 struct zebra_if
*zif
= ifp
->info
;
1218 zif
->rtadv
.AdvIntervalOption
= 1;
1223 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1224 no_ipv6_nd_adv_interval_config_option_cmd
,
1225 "no ipv6 nd adv-interval-option",
1227 "Interface IPv6 config commands\n"
1228 "Neighbor discovery\n"
1229 "Advertisement Interval Option\n")
1231 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1232 struct zebra_if
*zif
= ifp
->info
;
1234 zif
->rtadv
.AdvIntervalOption
= 0;
1239 DEFUN (ipv6_nd_other_config_flag
,
1240 ipv6_nd_other_config_flag_cmd
,
1241 "ipv6 nd other-config-flag",
1242 "Interface IPv6 config commands\n"
1243 "Neighbor discovery\n"
1244 "Other statefull configuration flag\n")
1246 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1247 struct zebra_if
*zif
= ifp
->info
;
1249 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1254 DEFUN (no_ipv6_nd_other_config_flag
,
1255 no_ipv6_nd_other_config_flag_cmd
,
1256 "no ipv6 nd other-config-flag",
1258 "Interface IPv6 config commands\n"
1259 "Neighbor discovery\n"
1260 "Other statefull configuration flag\n")
1262 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1263 struct zebra_if
*zif
= ifp
->info
;
1265 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1270 DEFUN (ipv6_nd_prefix
,
1272 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1273 "Interface IPv6 config commands\n"
1274 "Neighbor discovery\n"
1275 "Prefix information\n"
1277 "Valid lifetime in seconds\n"
1278 "Infinite valid lifetime\n"
1279 "Preferred lifetime in seconds\n"
1280 "Infinite preferred lifetime\n"
1281 "Set Router Address flag\n"
1282 "Do not use prefix for onlink determination\n"
1283 "Do not use prefix for autoconfiguration\n"
1284 "Do not use prefix for autoconfiguration\n"
1285 "Do not use prefix for onlink determination\n")
1288 char *prefix
= argv
[3]->arg
;
1289 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1290 || strmatch(argv
[4]->text
, "infinite"));
1291 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1293 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1295 char *lifetime
= NULL
, *preflifetime
= NULL
;
1296 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1298 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1300 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1305 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1307 offlink
= (argc
> idx_routeropts
+ 1
1308 || strmatch(argv
[idx_routeropts
]->text
,
1310 noautoconf
= (argc
> idx_routeropts
+ 1
1311 || strmatch(argv
[idx_routeropts
]->text
,
1317 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1318 struct zebra_if
*zebra_if
= ifp
->info
;
1320 struct rtadv_prefix rp
;
1322 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1324 vty_out(vty
, "Malformed IPv6 prefix\n");
1325 return CMD_WARNING_CONFIG_FAILED
;
1327 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1328 rp
.AdvOnLinkFlag
= !offlink
;
1329 rp
.AdvAutonomousFlag
= !noautoconf
;
1330 rp
.AdvRouterAddressFlag
= routeraddr
;
1331 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1332 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1335 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1337 : strtoll(lifetime
, NULL
, 10);
1338 rp
.AdvPreferredLifetime
=
1339 strmatch(preflifetime
, "infinite")
1341 : strtoll(preflifetime
, NULL
, 10);
1342 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1343 vty_out(vty
, "Invalid preferred lifetime\n");
1344 return CMD_WARNING_CONFIG_FAILED
;
1348 rtadv_prefix_set(zebra_if
, &rp
);
1353 DEFUN (no_ipv6_nd_prefix
,
1354 no_ipv6_nd_prefix_cmd
,
1355 "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]>]",
1357 "Interface IPv6 config commands\n"
1358 "Neighbor discovery\n"
1359 "Prefix information\n"
1361 "Valid lifetime in seconds\n"
1362 "Infinite valid lifetime\n"
1363 "Preferred lifetime in seconds\n"
1364 "Infinite preferred lifetime\n"
1365 "Set Router Address flag\n"
1366 "Do not use prefix for onlink determination\n"
1367 "Do not use prefix for autoconfiguration\n"
1368 "Do not use prefix for autoconfiguration\n"
1369 "Do not use prefix for onlink determination\n")
1371 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1372 struct zebra_if
*zebra_if
= ifp
->info
;
1374 struct rtadv_prefix rp
;
1375 char *prefix
= argv
[4]->arg
;
1377 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1379 vty_out(vty
, "Malformed IPv6 prefix\n");
1380 return CMD_WARNING_CONFIG_FAILED
;
1382 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1384 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1386 vty_out(vty
, "Non-existant IPv6 prefix\n");
1387 return CMD_WARNING_CONFIG_FAILED
;
1393 DEFUN (ipv6_nd_router_preference
,
1394 ipv6_nd_router_preference_cmd
,
1395 "ipv6 nd router-preference <high|medium|low>",
1396 "Interface IPv6 config commands\n"
1397 "Neighbor discovery\n"
1398 "Default router preference\n"
1399 "High default router preference\n"
1400 "Medium default router preference (default)\n"
1401 "Low default router preference\n")
1403 int idx_high_medium_low
= 3;
1404 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1405 struct zebra_if
*zif
= ifp
->info
;
1408 while (0 != rtadv_pref_strs
[i
]) {
1409 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1412 zif
->rtadv
.DefaultPreference
= i
;
1418 return CMD_ERR_NO_MATCH
;
1421 DEFUN (no_ipv6_nd_router_preference
,
1422 no_ipv6_nd_router_preference_cmd
,
1423 "no ipv6 nd router-preference [<high|medium|low>]",
1425 "Interface IPv6 config commands\n"
1426 "Neighbor discovery\n"
1427 "Default router preference\n"
1428 "High default router preference\n"
1429 "Medium default router preference (default)\n"
1430 "Low default router preference\n")
1432 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1433 struct zebra_if
*zif
= ifp
->info
;
1435 zif
->rtadv
.DefaultPreference
=
1436 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1443 "ipv6 nd mtu (1-65535)",
1444 "Interface IPv6 config commands\n"
1445 "Neighbor discovery\n"
1450 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1451 struct zebra_if
*zif
= ifp
->info
;
1452 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1456 DEFUN (no_ipv6_nd_mtu
,
1458 "no ipv6 nd mtu [(1-65535)]",
1460 "Interface IPv6 config commands\n"
1461 "Neighbor discovery\n"
1465 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1466 struct zebra_if
*zif
= ifp
->info
;
1467 zif
->rtadv
.AdvLinkMTU
= 0;
1471 /* Dump interface ND information to vty. */
1472 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1474 struct zebra_if
*zif
;
1475 struct rtadvconf
*rtadv
;
1478 zif
= (struct zebra_if
*)ifp
->info
;
1479 rtadv
= &zif
->rtadv
;
1481 if (rtadv
->AdvSendAdvertisements
) {
1483 " ND advertised reachable time is %d milliseconds\n",
1484 rtadv
->AdvReachableTime
);
1486 " ND advertised retransmit interval is %d milliseconds\n",
1487 rtadv
->AdvRetransTimer
);
1488 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1489 zif
->ra_sent
, zif
->ra_rcvd
);
1490 interval
= rtadv
->MaxRtrAdvInterval
;
1491 if (interval
% 1000)
1493 " ND router advertisements are sent every "
1494 "%d milliseconds\n",
1498 " ND router advertisements are sent every "
1501 if (rtadv
->AdvDefaultLifetime
!= -1)
1503 " ND router advertisements live for %d seconds\n",
1504 rtadv
->AdvDefaultLifetime
);
1507 " ND router advertisements lifetime tracks ra-interval\n");
1509 " ND router advertisement default router preference is "
1511 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1512 if (rtadv
->AdvManagedFlag
)
1514 " Hosts use DHCP to obtain routable addresses.\n");
1517 " Hosts use stateless autoconfig for addresses.\n");
1518 if (rtadv
->AdvHomeAgentFlag
) {
1520 " ND router advertisements with Home Agent flag bit set.\n");
1521 if (rtadv
->HomeAgentLifetime
!= -1)
1523 " Home Agent lifetime is %u seconds\n",
1524 rtadv
->HomeAgentLifetime
);
1527 " Home Agent lifetime tracks ra-lifetime\n");
1528 vty_out(vty
, " Home Agent preference is %u\n",
1529 rtadv
->HomeAgentPreference
);
1531 if (rtadv
->AdvIntervalOption
)
1533 " ND router advertisements with Adv. Interval option.\n");
1539 /* Write configuration about router advertisement. */
1540 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1542 struct zebra_if
*zif
;
1543 struct listnode
*node
;
1544 struct rtadv_prefix
*rprefix
;
1545 char buf
[PREFIX_STRLEN
];
1550 if (!(if_is_loopback(ifp
)
1551 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1552 if (zif
->rtadv
.AdvSendAdvertisements
)
1553 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1556 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1557 if (interval
% 1000)
1558 vty_out(vty
, " ipv6 nd ra-interval msec %d\n", interval
);
1559 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1560 vty_out(vty
, " ipv6 nd ra-interval %d\n", interval
/ 1000);
1562 if (zif
->rtadv
.AdvIntervalOption
)
1563 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1565 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1566 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1567 zif
->rtadv
.AdvDefaultLifetime
);
1569 if (zif
->rtadv
.HomeAgentPreference
)
1570 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1571 zif
->rtadv
.HomeAgentPreference
);
1573 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1574 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1575 zif
->rtadv
.HomeAgentLifetime
);
1577 if (zif
->rtadv
.AdvHomeAgentFlag
)
1578 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1580 if (zif
->rtadv
.AdvReachableTime
)
1581 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1582 zif
->rtadv
.AdvReachableTime
);
1584 if (zif
->rtadv
.AdvManagedFlag
)
1585 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1587 if (zif
->rtadv
.AdvOtherConfigFlag
)
1588 vty_out(vty
, " ipv6 nd other-config-flag\n");
1590 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1591 vty_out(vty
, " ipv6 nd router-preference %s\n",
1592 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1594 if (zif
->rtadv
.AdvLinkMTU
)
1595 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1597 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1598 vty_out(vty
, " ipv6 nd prefix %s",
1599 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1600 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1601 || (rprefix
->AdvPreferredLifetime
1602 != RTADV_PREFERRED_LIFETIME
)) {
1603 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1604 vty_out(vty
, " infinite");
1606 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1607 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1608 vty_out(vty
, " infinite");
1611 rprefix
->AdvPreferredLifetime
);
1613 if (!rprefix
->AdvOnLinkFlag
)
1614 vty_out(vty
, " off-link");
1615 if (!rprefix
->AdvAutonomousFlag
)
1616 vty_out(vty
, " no-autoconfig");
1617 if (rprefix
->AdvRouterAddressFlag
)
1618 vty_out(vty
, " router-address");
1625 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1627 struct rtadv
*rtadv
= &zns
->rtadv
;
1631 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1633 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1637 if (rtadv
->ra_timer
) {
1638 thread_cancel(rtadv
->ra_timer
);
1639 rtadv
->ra_timer
= NULL
;
1641 if (rtadv
->ra_read
) {
1642 thread_cancel(rtadv
->ra_read
);
1643 rtadv
->ra_read
= NULL
;
1647 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1650 case RTADV_TIMER_MSEC
:
1651 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1655 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1664 void rtadv_init(struct zebra_ns
*zns
)
1666 zns
->rtadv
.sock
= rtadv_make_socket();
1669 void rtadv_terminate(struct zebra_ns
*zns
)
1671 rtadv_event(zns
, RTADV_STOP
, 0);
1672 if (zns
->rtadv
.sock
>= 0) {
1673 close(zns
->rtadv
.sock
);
1674 zns
->rtadv
.sock
= -1;
1677 zns
->rtadv
.adv_if_count
= 0;
1678 zns
->rtadv
.adv_msec_if_count
= 0;
1681 void rtadv_cmd_init(void)
1683 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1684 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1686 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1687 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1688 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1689 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1690 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1691 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1692 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1693 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1694 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1695 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1696 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1697 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1698 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1699 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1700 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1701 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1702 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1703 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1704 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1705 install_element(INTERFACE_NODE
,
1706 &ipv6_nd_adv_interval_config_option_cmd
);
1707 install_element(INTERFACE_NODE
,
1708 &no_ipv6_nd_adv_interval_config_option_cmd
);
1709 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1710 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1711 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1712 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1713 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1714 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1717 static int if_join_all_router(int sock
, struct interface
*ifp
)
1721 struct ipv6_mreq mreq
;
1723 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1724 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1725 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1727 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1730 zlog_warn("%s(%u): Failed to join group, socket %u error %s",
1731 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1733 if (IS_ZEBRA_DEBUG_EVENT
)
1735 "%s(%u): Join All-Routers multicast group, socket %u",
1736 ifp
->name
, ifp
->ifindex
, sock
);
1741 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1745 struct ipv6_mreq mreq
;
1747 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1748 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1749 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1751 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1754 zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
1755 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1757 if (IS_ZEBRA_DEBUG_EVENT
)
1759 "%s(%u): Leave All-Routers multicast group, socket %u",
1760 ifp
->name
, ifp
->ifindex
, sock
);
1766 void rtadv_init(struct zebra_ns
*zns
)
1770 void rtadv_terminate(struct zebra_ns
*zns
)
1774 void rtadv_cmd_init(void)
1778 #endif /* HAVE_RTADV */