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
= malloc(CMSG_SPACE(sizeof(struct in6_pktinfo
)));
183 "rtadv_send_packet: can't malloc control data");
186 /* Logging of packet. */
187 if (IS_ZEBRA_DEBUG_PACKET
)
188 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
191 /* Fill in sockaddr_in6. */
192 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
193 addr
.sin6_family
= AF_INET6
;
195 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
196 #endif /* SIN6_LEN */
197 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
198 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
200 /* Fetch interface information. */
203 /* Make router advertisement message. */
204 rtadv
= (struct nd_router_advert
*)buf
;
206 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
207 rtadv
->nd_ra_code
= 0;
208 rtadv
->nd_ra_cksum
= 0;
210 rtadv
->nd_ra_curhoplimit
= 64;
212 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
213 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
215 : zif
->rtadv
.DefaultPreference
;
216 rtadv
->nd_ra_flags_reserved
<<= 3;
218 if (zif
->rtadv
.AdvManagedFlag
)
219 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
220 if (zif
->rtadv
.AdvOtherConfigFlag
)
221 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
222 if (zif
->rtadv
.AdvHomeAgentFlag
)
223 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
224 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
225 * AdvDefaultLifetime is by default based on the value of
226 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
227 * field of Router Advertisements. Given that this field is expressed
228 * in seconds, a small MaxRtrAdvInterval value can result in a zero
229 * value for this field. To prevent this, routers SHOULD keep
230 * AdvDefaultLifetime in at least one second, even if the use of
231 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
233 zif
->rtadv
.AdvDefaultLifetime
!= -1
234 ? zif
->rtadv
.AdvDefaultLifetime
235 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
236 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
237 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
238 rtadv
->nd_ra_retransmit
= htonl(0);
240 len
= sizeof(struct nd_router_advert
);
242 /* If both the Home Agent Preference and Home Agent Lifetime are set to
243 * their default values specified above, this option SHOULD NOT be
244 * included in the Router Advertisement messages sent by this home
245 * agent. -- RFC6275, 7.4 */
246 if (zif
->rtadv
.AdvHomeAgentFlag
247 && (zif
->rtadv
.HomeAgentPreference
248 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
249 struct nd_opt_homeagent_info
*ndopt_hai
=
250 (struct nd_opt_homeagent_info
*)(buf
+ len
);
251 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
252 ndopt_hai
->nd_opt_hai_len
= 1;
253 ndopt_hai
->nd_opt_hai_reserved
= 0;
254 ndopt_hai
->nd_opt_hai_preference
=
255 htons(zif
->rtadv
.HomeAgentPreference
);
256 /* 16-bit unsigned integer. The lifetime associated with the
258 * agent in units of seconds. The default value is the same as
260 * Router Lifetime, as specified in the main body of the Router
261 * Advertisement. The maximum value corresponds to 18.2 hours.
263 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
264 ndopt_hai
->nd_opt_hai_lifetime
=
265 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
266 ? zif
->rtadv
.HomeAgentLifetime
267 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
272 len
+= sizeof(struct nd_opt_homeagent_info
);
275 if (zif
->rtadv
.AdvIntervalOption
) {
276 struct nd_opt_adv_interval
*ndopt_adv
=
277 (struct nd_opt_adv_interval
*)(buf
+ len
);
278 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
279 ndopt_adv
->nd_opt_ai_len
= 1;
280 ndopt_adv
->nd_opt_ai_reserved
= 0;
281 ndopt_adv
->nd_opt_ai_interval
=
282 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
283 len
+= sizeof(struct nd_opt_adv_interval
);
286 /* Fill in prefix. */
287 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
288 struct nd_opt_prefix_info
*pinfo
;
290 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
292 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
293 pinfo
->nd_opt_pi_len
= 4;
294 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
296 pinfo
->nd_opt_pi_flags_reserved
= 0;
297 if (rprefix
->AdvOnLinkFlag
)
298 pinfo
->nd_opt_pi_flags_reserved
|=
299 ND_OPT_PI_FLAG_ONLINK
;
300 if (rprefix
->AdvAutonomousFlag
)
301 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
302 if (rprefix
->AdvRouterAddressFlag
)
303 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
305 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
306 pinfo
->nd_opt_pi_preferred_time
=
307 htonl(rprefix
->AdvPreferredLifetime
);
308 pinfo
->nd_opt_pi_reserved2
= 0;
310 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
311 &rprefix
->prefix
.prefix
);
315 u_char buf
[INET6_ADDRSTRLEN
];
317 zlog_debug("DEBUG %s",
318 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
319 buf
, INET6_ADDRSTRLEN
));
323 len
+= sizeof(struct nd_opt_prefix_info
);
326 /* Hardware address. */
327 if (ifp
->hw_addr_len
!= 0) {
328 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
330 /* Option length should be rounded up to next octet if
331 the link address does not end on an octet boundary. */
332 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
334 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
335 len
+= ifp
->hw_addr_len
;
337 /* Pad option to end on an octet boundary. */
338 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
339 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
343 if (zif
->rtadv
.AdvLinkMTU
) {
344 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
345 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
346 opt
->nd_opt_mtu_len
= 1;
347 opt
->nd_opt_mtu_reserved
= 0;
348 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
349 len
+= sizeof(struct nd_opt_mtu
);
352 msg
.msg_name
= (void *)&addr
;
353 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
356 msg
.msg_control
= (void *)adata
;
357 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
362 cmsgptr
= ZCMSG_FIRSTHDR(&msg
);
363 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
364 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
365 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
367 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
368 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
369 pkt
->ipi6_ifindex
= ifp
->ifindex
;
371 ret
= sendmsg(sock
, &msg
, 0);
373 zlog_err("%s(%u): Tx RA failed, socket %u error %d (%s)",
374 ifp
->name
, ifp
->ifindex
, sock
, errno
,
375 safe_strerror(errno
));
380 static int rtadv_timer(struct thread
*thread
)
382 struct zebra_ns
*zns
= THREAD_ARG(thread
);
384 struct listnode
*node
, *nnode
;
385 struct interface
*ifp
;
386 struct zebra_if
*zif
;
389 zns
->rtadv
.ra_timer
= NULL
;
390 if (zns
->rtadv
.adv_msec_if_count
== 0) {
391 period
= 1000; /* 1 s */
392 rtadv_event(zns
, RTADV_TIMER
, 1 /* 1 s */);
394 period
= 10; /* 10 ms */
395 rtadv_event(zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
398 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
399 for (ALL_LIST_ELEMENTS(vrf
->iflist
, node
, nnode
, ifp
)) {
400 if (if_is_loopback(ifp
)
401 || CHECK_FLAG(ifp
->status
,
402 ZEBRA_INTERFACE_VRF_LOOPBACK
)
403 || !if_is_operative(ifp
))
408 if (zif
->rtadv
.AdvSendAdvertisements
) {
409 if (zif
->rtadv
.inFastRexmit
) {
410 /* We assume we fast rexmit every sec so
413 if (--zif
->rtadv
.NumFastReXmitsRemain
415 zif
->rtadv
.inFastRexmit
= 0;
417 if (IS_ZEBRA_DEBUG_SEND
)
419 "Fast RA Rexmit on interface %s",
422 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
424 zif
->rtadv
.AdvIntervalTimer
-= period
;
425 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
427 MaxRtrAdvInterval each
428 time isn't what section
429 6.2.4 of RFC4861 tells to do.
431 zif
->rtadv
.AdvIntervalTimer
=
435 zns
->rtadv
.sock
, ifp
);
444 static void rtadv_process_solicit(struct interface
*ifp
)
446 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
447 struct zebra_ns
*zns
= zvrf
->zns
;
450 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
453 static void rtadv_process_advert(u_char
*msg
, unsigned int len
,
454 struct interface
*ifp
,
455 struct sockaddr_in6
*addr
)
457 struct nd_router_advert
*radvert
;
458 char addr_str
[INET6_ADDRSTRLEN
];
459 struct zebra_if
*zif
;
464 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
466 if (len
< sizeof(struct nd_router_advert
)) {
467 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
468 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
471 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
473 "%s(%u): Rx RA with non-linklocal source address from %s",
474 ifp
->name
, ifp
->ifindex
, addr_str
);
478 radvert
= (struct nd_router_advert
*)msg
;
480 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
481 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
483 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
484 ifp
->name
, ifp
->ifindex
, addr_str
);
487 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
488 && !zif
->rtadv
.AdvManagedFlag
) {
490 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
491 ifp
->name
, ifp
->ifindex
, addr_str
);
494 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
495 && !zif
->rtadv
.AdvOtherConfigFlag
) {
497 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
498 ifp
->name
, ifp
->ifindex
, addr_str
);
501 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
502 && (ntohl(radvert
->nd_ra_reachable
)
503 != zif
->rtadv
.AdvReachableTime
)) {
505 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
506 ifp
->name
, ifp
->ifindex
, addr_str
);
509 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
510 && (ntohl(radvert
->nd_ra_retransmit
)
511 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
513 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
514 ifp
->name
, ifp
->ifindex
, addr_str
);
517 /* Create entry for neighbor if not known. */
519 IPV6_ADDR_COPY(&p
.u
.prefix
, &addr
->sin6_addr
);
520 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
522 if (!nbr_connected_check(ifp
, &p
))
523 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
527 static void rtadv_process_packet(u_char
*buf
, unsigned int len
,
528 ifindex_t ifindex
, int hoplimit
,
529 struct sockaddr_in6
*from
,
530 struct zebra_ns
*zns
)
532 struct icmp6_hdr
*icmph
;
533 struct interface
*ifp
;
534 struct zebra_if
*zif
;
535 char addr_str
[INET6_ADDRSTRLEN
];
537 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
539 /* Interface search. */
540 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
542 zlog_warn("RA/RS received on unknown IF %u from %s", ifindex
,
547 if (IS_ZEBRA_DEBUG_PACKET
)
548 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
549 ifp
->ifindex
, len
, addr_str
);
551 if (if_is_loopback(ifp
)
552 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
555 /* Check interface configuration. */
557 if (!zif
->rtadv
.AdvSendAdvertisements
)
560 /* ICMP message length check. */
561 if (len
< sizeof(struct icmp6_hdr
)) {
562 zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
563 ifp
->name
, ifp
->ifindex
, len
);
567 icmph
= (struct icmp6_hdr
*)buf
;
569 /* ICMP message type check. */
570 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
571 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
572 zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
573 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
577 /* Hoplimit check. */
578 if (hoplimit
>= 0 && hoplimit
!= 255) {
579 zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
580 ifp
->ifindex
, hoplimit
);
584 /* Check ICMP message type. */
585 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
586 rtadv_process_solicit(ifp
);
587 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
588 rtadv_process_advert(buf
, len
, ifp
, from
);
593 static int rtadv_read(struct thread
*thread
)
597 u_char buf
[RTADV_MSG_SIZE
];
598 struct sockaddr_in6 from
;
599 ifindex_t ifindex
= 0;
601 struct zebra_ns
*zns
= THREAD_ARG(thread
);
603 sock
= THREAD_FD(thread
);
604 zns
->rtadv
.ra_read
= NULL
;
606 /* Register myself. */
607 rtadv_event(zns
, RTADV_READ
, sock
);
609 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
613 zlog_warn("RA/RS recv failed, socket %u error %s", sock
,
614 safe_strerror(errno
));
618 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
623 static int rtadv_make_socket(void)
627 struct icmp6_filter filter
;
629 if (zserv_privs
.change(ZPRIVS_RAISE
))
630 zlog_err("rtadv_make_socket: could not raise privs, %s",
631 safe_strerror(errno
));
633 sock
= socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
635 if (zserv_privs
.change(ZPRIVS_LOWER
))
636 zlog_err("rtadv_make_socket: could not lower privs, %s",
637 safe_strerror(errno
));
643 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
648 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
653 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
658 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
663 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
669 ICMP6_FILTER_SETBLOCKALL(&filter
);
670 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
671 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
673 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
674 sizeof(struct icmp6_filter
));
676 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
683 static struct rtadv_prefix
*rtadv_prefix_new(void)
685 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
688 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
690 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
693 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
694 struct prefix_ipv6
*p
)
696 struct listnode
*node
;
697 struct rtadv_prefix
*rprefix
;
699 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
700 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
706 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
707 struct prefix_ipv6
*p
)
709 struct rtadv_prefix
*rprefix
;
711 rprefix
= rtadv_prefix_lookup(rplist
, p
);
715 rprefix
= rtadv_prefix_new();
716 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
717 listnode_add(rplist
, rprefix
);
722 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
724 struct rtadv_prefix
*rprefix
;
726 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
728 /* Set parameters. */
729 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
730 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
731 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
732 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
733 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
736 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
738 struct rtadv_prefix
*rprefix
;
740 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
741 if (rprefix
!= NULL
) {
742 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
743 rtadv_prefix_free(rprefix
);
749 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
750 ipv6_nd_suppress_ra_status status
)
752 struct zebra_if
*zif
;
753 struct zebra_vrf
*zvrf
;
754 struct zebra_ns
*zns
;
757 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
760 if (status
== RA_SUPPRESS
) {
761 /* RA is currently enabled */
762 if (zif
->rtadv
.AdvSendAdvertisements
) {
763 zif
->rtadv
.AdvSendAdvertisements
= 0;
764 zif
->rtadv
.AdvIntervalTimer
= 0;
765 zns
->rtadv
.adv_if_count
--;
767 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
769 if (zns
->rtadv
.adv_if_count
== 0)
770 rtadv_event(zns
, RTADV_STOP
, 0);
773 if (!zif
->rtadv
.AdvSendAdvertisements
) {
774 zif
->rtadv
.AdvSendAdvertisements
= 1;
775 zif
->rtadv
.AdvIntervalTimer
= 0;
776 zns
->rtadv
.adv_if_count
++;
778 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
779 /* Enable Fast RA only when RA interval is in
781 zif
->rtadv
.inFastRexmit
= 1;
782 zif
->rtadv
.NumFastReXmitsRemain
=
783 RTADV_NUM_FAST_REXMITS
;
786 if_join_all_router(zns
->rtadv
.sock
, ifp
);
788 if (zns
->rtadv
.adv_if_count
== 1)
789 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
795 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
796 * Note that while the client could request RA on an interface on which the
797 * operator has not enabled RA, RA won't be disabled upon client request
798 * if the operator has explicitly enabled RA. The enable request can also
799 * specify a RA interval (in seconds).
801 void zebra_interface_radv_set(struct zserv
*client
, int sock
, u_short length
,
802 struct zebra_vrf
*zvrf
, int enable
)
805 unsigned int ifindex
;
806 struct interface
*ifp
;
807 struct zebra_if
*zif
;
812 /* Get interface index and RA interval. */
813 ifindex
= stream_getl(s
);
814 ra_interval
= stream_getl(s
);
816 if (IS_ZEBRA_DEBUG_EVENT
)
817 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
818 zvrf_id(zvrf
), ifindex
,
819 enable
? "enable" : "disable",
820 zebra_route_string(client
->proto
), ra_interval
);
822 /* Locate interface and check VRF match. */
823 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
825 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
826 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
827 zebra_route_string(client
->proto
));
830 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
831 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
832 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
833 zebra_route_string(client
->proto
), ifp
->vrf_id
);
839 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
841 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
)
842 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
844 if (!zif
->rtadv
.configured
) {
845 zif
->rtadv
.MaxRtrAdvInterval
=
846 RTADV_MAX_RTR_ADV_INTERVAL
;
847 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
852 DEFUN (ipv6_nd_suppress_ra
,
853 ipv6_nd_suppress_ra_cmd
,
854 "ipv6 nd suppress-ra",
855 "Interface IPv6 config commands\n"
856 "Neighbor discovery\n"
857 "Suppress Router Advertisement\n")
859 VTY_DECLVAR_CONTEXT(interface
, ifp
);
860 struct zebra_if
*zif
= ifp
->info
;
862 if (if_is_loopback(ifp
)
863 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
865 "Cannot configure IPv6 Router Advertisements on this interface\n");
866 return CMD_WARNING_CONFIG_FAILED
;
869 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
870 zif
->rtadv
.configured
= 0;
874 DEFUN (no_ipv6_nd_suppress_ra
,
875 no_ipv6_nd_suppress_ra_cmd
,
876 "no ipv6 nd suppress-ra",
878 "Interface IPv6 config commands\n"
879 "Neighbor discovery\n"
880 "Suppress Router Advertisement\n")
882 VTY_DECLVAR_CONTEXT(interface
, ifp
);
883 struct zebra_if
*zif
= ifp
->info
;
885 if (if_is_loopback(ifp
)
886 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
888 "Cannot configure IPv6 Router Advertisements on this interface\n");
889 return CMD_WARNING_CONFIG_FAILED
;
892 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
893 zif
->rtadv
.configured
= 1;
897 DEFUN (ipv6_nd_ra_interval_msec
,
898 ipv6_nd_ra_interval_msec_cmd
,
899 "ipv6 nd ra-interval msec (70-1800000)",
900 "Interface IPv6 config commands\n"
901 "Neighbor discovery\n"
902 "Router Advertisement interval\n"
903 "Router Advertisement interval in milliseconds\n"
904 "Router Advertisement interval in milliseconds\n")
907 VTY_DECLVAR_CONTEXT(interface
, ifp
);
909 struct zebra_if
*zif
= ifp
->info
;
910 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
911 struct zebra_ns
*zns
;
914 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
915 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
916 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
918 "This ra-interval would conflict with configured ra-lifetime!\n");
919 return CMD_WARNING_CONFIG_FAILED
;
922 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
923 zns
->rtadv
.adv_msec_if_count
--;
926 zns
->rtadv
.adv_msec_if_count
++;
928 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
929 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
930 zif
->rtadv
.AdvIntervalTimer
= 0;
935 DEFUN (ipv6_nd_ra_interval
,
936 ipv6_nd_ra_interval_cmd
,
937 "ipv6 nd ra-interval (1-1800)",
938 "Interface IPv6 config commands\n"
939 "Neighbor discovery\n"
940 "Router Advertisement interval\n"
941 "Router Advertisement interval in seconds\n")
944 VTY_DECLVAR_CONTEXT(interface
, ifp
);
946 struct zebra_if
*zif
= ifp
->info
;
947 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
948 struct zebra_ns
*zns
;
951 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
952 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
953 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
955 "This ra-interval would conflict with configured ra-lifetime!\n");
956 return CMD_WARNING_CONFIG_FAILED
;
959 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
960 zns
->rtadv
.adv_msec_if_count
--;
962 /* convert to milliseconds */
963 interval
= interval
* 1000;
965 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
966 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
967 zif
->rtadv
.AdvIntervalTimer
= 0;
972 DEFUN (no_ipv6_nd_ra_interval
,
973 no_ipv6_nd_ra_interval_cmd
,
974 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
976 "Interface IPv6 config commands\n"
977 "Neighbor discovery\n"
978 "Router Advertisement interval\n"
979 "Router Advertisement interval in seconds\n"
980 "Specify millisecond router advertisement interval\n"
981 "Router Advertisement interval in milliseconds\n")
983 VTY_DECLVAR_CONTEXT(interface
, ifp
);
984 struct zebra_if
*zif
= ifp
->info
;
985 struct zebra_vrf
*zvrf
;
986 struct zebra_ns
*zns
;
988 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
991 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
992 zns
->rtadv
.adv_msec_if_count
--;
994 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
995 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
996 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1001 DEFUN (ipv6_nd_ra_lifetime
,
1002 ipv6_nd_ra_lifetime_cmd
,
1003 "ipv6 nd ra-lifetime (0-9000)",
1004 "Interface IPv6 config commands\n"
1005 "Neighbor discovery\n"
1007 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1010 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1011 struct zebra_if
*zif
= ifp
->info
;
1014 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1016 /* The value to be placed in the Router Lifetime field
1017 * of Router Advertisements sent from the interface,
1018 * in seconds. MUST be either zero or between
1019 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1020 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1022 "This ra-lifetime would conflict with configured ra-interval\n");
1023 return CMD_WARNING_CONFIG_FAILED
;
1026 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1031 DEFUN (no_ipv6_nd_ra_lifetime
,
1032 no_ipv6_nd_ra_lifetime_cmd
,
1033 "no ipv6 nd ra-lifetime [(0-9000)]",
1035 "Interface IPv6 config commands\n"
1036 "Neighbor discovery\n"
1038 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1040 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1041 struct zebra_if
*zif
= ifp
->info
;
1043 zif
->rtadv
.AdvDefaultLifetime
= -1;
1048 DEFUN (ipv6_nd_reachable_time
,
1049 ipv6_nd_reachable_time_cmd
,
1050 "ipv6 nd reachable-time (1-3600000)",
1051 "Interface IPv6 config commands\n"
1052 "Neighbor discovery\n"
1054 "Reachable time in milliseconds\n")
1057 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1058 struct zebra_if
*zif
= ifp
->info
;
1059 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1063 DEFUN (no_ipv6_nd_reachable_time
,
1064 no_ipv6_nd_reachable_time_cmd
,
1065 "no ipv6 nd reachable-time [(1-3600000)]",
1067 "Interface IPv6 config commands\n"
1068 "Neighbor discovery\n"
1070 "Reachable time in milliseconds\n")
1072 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1073 struct zebra_if
*zif
= ifp
->info
;
1075 zif
->rtadv
.AdvReachableTime
= 0;
1080 DEFUN (ipv6_nd_homeagent_preference
,
1081 ipv6_nd_homeagent_preference_cmd
,
1082 "ipv6 nd home-agent-preference (0-65535)",
1083 "Interface IPv6 config commands\n"
1084 "Neighbor discovery\n"
1085 "Home Agent preference\n"
1086 "preference value (default is 0, least preferred)\n")
1089 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1090 struct zebra_if
*zif
= ifp
->info
;
1091 zif
->rtadv
.HomeAgentPreference
=
1092 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1096 DEFUN (no_ipv6_nd_homeagent_preference
,
1097 no_ipv6_nd_homeagent_preference_cmd
,
1098 "no ipv6 nd home-agent-preference [(0-65535)]",
1100 "Interface IPv6 config commands\n"
1101 "Neighbor discovery\n"
1102 "Home Agent preference\n"
1103 "preference value (default is 0, least preferred)\n")
1105 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1106 struct zebra_if
*zif
= ifp
->info
;
1108 zif
->rtadv
.HomeAgentPreference
= 0;
1113 DEFUN (ipv6_nd_homeagent_lifetime
,
1114 ipv6_nd_homeagent_lifetime_cmd
,
1115 "ipv6 nd home-agent-lifetime (0-65520)",
1116 "Interface IPv6 config commands\n"
1117 "Neighbor discovery\n"
1118 "Home Agent lifetime\n"
1119 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1122 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1123 struct zebra_if
*zif
= ifp
->info
;
1124 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1128 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1129 no_ipv6_nd_homeagent_lifetime_cmd
,
1130 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1132 "Interface IPv6 config commands\n"
1133 "Neighbor discovery\n"
1134 "Home Agent lifetime\n"
1135 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1137 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1138 struct zebra_if
*zif
= ifp
->info
;
1140 zif
->rtadv
.HomeAgentLifetime
= -1;
1145 DEFUN (ipv6_nd_managed_config_flag
,
1146 ipv6_nd_managed_config_flag_cmd
,
1147 "ipv6 nd managed-config-flag",
1148 "Interface IPv6 config commands\n"
1149 "Neighbor discovery\n"
1150 "Managed address configuration flag\n")
1152 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1153 struct zebra_if
*zif
= ifp
->info
;
1155 zif
->rtadv
.AdvManagedFlag
= 1;
1160 DEFUN (no_ipv6_nd_managed_config_flag
,
1161 no_ipv6_nd_managed_config_flag_cmd
,
1162 "no ipv6 nd managed-config-flag",
1164 "Interface IPv6 config commands\n"
1165 "Neighbor discovery\n"
1166 "Managed address configuration flag\n")
1168 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1169 struct zebra_if
*zif
= ifp
->info
;
1171 zif
->rtadv
.AdvManagedFlag
= 0;
1176 DEFUN (ipv6_nd_homeagent_config_flag
,
1177 ipv6_nd_homeagent_config_flag_cmd
,
1178 "ipv6 nd home-agent-config-flag",
1179 "Interface IPv6 config commands\n"
1180 "Neighbor discovery\n"
1181 "Home Agent configuration flag\n")
1183 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1184 struct zebra_if
*zif
= ifp
->info
;
1186 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1191 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1192 no_ipv6_nd_homeagent_config_flag_cmd
,
1193 "no ipv6 nd home-agent-config-flag",
1195 "Interface IPv6 config commands\n"
1196 "Neighbor discovery\n"
1197 "Home Agent configuration flag\n")
1199 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1200 struct zebra_if
*zif
= ifp
->info
;
1202 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1207 DEFUN (ipv6_nd_adv_interval_config_option
,
1208 ipv6_nd_adv_interval_config_option_cmd
,
1209 "ipv6 nd adv-interval-option",
1210 "Interface IPv6 config commands\n"
1211 "Neighbor discovery\n"
1212 "Advertisement Interval Option\n")
1214 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1215 struct zebra_if
*zif
= ifp
->info
;
1217 zif
->rtadv
.AdvIntervalOption
= 1;
1222 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1223 no_ipv6_nd_adv_interval_config_option_cmd
,
1224 "no ipv6 nd adv-interval-option",
1226 "Interface IPv6 config commands\n"
1227 "Neighbor discovery\n"
1228 "Advertisement Interval Option\n")
1230 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1231 struct zebra_if
*zif
= ifp
->info
;
1233 zif
->rtadv
.AdvIntervalOption
= 0;
1238 DEFUN (ipv6_nd_other_config_flag
,
1239 ipv6_nd_other_config_flag_cmd
,
1240 "ipv6 nd other-config-flag",
1241 "Interface IPv6 config commands\n"
1242 "Neighbor discovery\n"
1243 "Other statefull configuration flag\n")
1245 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1246 struct zebra_if
*zif
= ifp
->info
;
1248 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1253 DEFUN (no_ipv6_nd_other_config_flag
,
1254 no_ipv6_nd_other_config_flag_cmd
,
1255 "no ipv6 nd other-config-flag",
1257 "Interface IPv6 config commands\n"
1258 "Neighbor discovery\n"
1259 "Other statefull configuration flag\n")
1261 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1262 struct zebra_if
*zif
= ifp
->info
;
1264 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1269 DEFUN (ipv6_nd_prefix
,
1271 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1272 "Interface IPv6 config commands\n"
1273 "Neighbor discovery\n"
1274 "Prefix information\n"
1276 "Valid lifetime in seconds\n"
1277 "Infinite valid lifetime\n"
1278 "Preferred lifetime in seconds\n"
1279 "Infinite preferred lifetime\n"
1280 "Set Router Address flag\n"
1281 "Do not use prefix for onlink determination\n"
1282 "Do not use prefix for autoconfiguration\n"
1283 "Do not use prefix for autoconfiguration\n"
1284 "Do not use prefix for onlink determination\n")
1287 char *prefix
= argv
[3]->arg
;
1288 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1289 || strmatch(argv
[4]->text
, "infinite"));
1290 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1292 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1294 char *lifetime
= NULL
, *preflifetime
= NULL
;
1295 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1297 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1299 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1304 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1306 offlink
= (argc
> idx_routeropts
+ 1
1307 || strmatch(argv
[idx_routeropts
]->text
,
1309 noautoconf
= (argc
> idx_routeropts
+ 1
1310 || strmatch(argv
[idx_routeropts
]->text
,
1316 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1317 struct zebra_if
*zebra_if
= ifp
->info
;
1319 struct rtadv_prefix rp
;
1321 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1323 vty_out(vty
, "Malformed IPv6 prefix\n");
1324 return CMD_WARNING_CONFIG_FAILED
;
1326 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1327 rp
.AdvOnLinkFlag
= !offlink
;
1328 rp
.AdvAutonomousFlag
= !noautoconf
;
1329 rp
.AdvRouterAddressFlag
= routeraddr
;
1330 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1331 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1334 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1336 : strtoll(lifetime
, NULL
, 10);
1337 rp
.AdvPreferredLifetime
=
1338 strmatch(preflifetime
, "infinite")
1340 : strtoll(preflifetime
, NULL
, 10);
1341 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1342 vty_out(vty
, "Invalid preferred lifetime\n");
1343 return CMD_WARNING_CONFIG_FAILED
;
1347 rtadv_prefix_set(zebra_if
, &rp
);
1352 DEFUN (no_ipv6_nd_prefix
,
1353 no_ipv6_nd_prefix_cmd
,
1354 "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]>]",
1356 "Interface IPv6 config commands\n"
1357 "Neighbor discovery\n"
1358 "Prefix information\n"
1360 "Valid lifetime in seconds\n"
1361 "Infinite valid lifetime\n"
1362 "Preferred lifetime in seconds\n"
1363 "Infinite preferred lifetime\n"
1364 "Set Router Address flag\n"
1365 "Do not use prefix for onlink determination\n"
1366 "Do not use prefix for autoconfiguration\n"
1367 "Do not use prefix for autoconfiguration\n"
1368 "Do not use prefix for onlink determination\n")
1370 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1371 struct zebra_if
*zebra_if
= ifp
->info
;
1373 struct rtadv_prefix rp
;
1374 char *prefix
= argv
[4]->arg
;
1376 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1378 vty_out(vty
, "Malformed IPv6 prefix\n");
1379 return CMD_WARNING_CONFIG_FAILED
;
1381 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1383 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1385 vty_out(vty
, "Non-existant IPv6 prefix\n");
1386 return CMD_WARNING_CONFIG_FAILED
;
1392 DEFUN (ipv6_nd_router_preference
,
1393 ipv6_nd_router_preference_cmd
,
1394 "ipv6 nd router-preference <high|medium|low>",
1395 "Interface IPv6 config commands\n"
1396 "Neighbor discovery\n"
1397 "Default router preference\n"
1398 "High default router preference\n"
1399 "Medium default router preference (default)\n"
1400 "Low default router preference\n")
1402 int idx_high_medium_low
= 3;
1403 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1404 struct zebra_if
*zif
= ifp
->info
;
1407 while (0 != rtadv_pref_strs
[i
]) {
1408 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1411 zif
->rtadv
.DefaultPreference
= i
;
1417 return CMD_ERR_NO_MATCH
;
1420 DEFUN (no_ipv6_nd_router_preference
,
1421 no_ipv6_nd_router_preference_cmd
,
1422 "no ipv6 nd router-preference [<high|medium|low>]",
1424 "Interface IPv6 config commands\n"
1425 "Neighbor discovery\n"
1426 "Default router preference\n"
1427 "High default router preference\n"
1428 "Medium default router preference (default)\n"
1429 "Low default router preference\n")
1431 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1432 struct zebra_if
*zif
= ifp
->info
;
1434 zif
->rtadv
.DefaultPreference
=
1435 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1442 "ipv6 nd mtu (1-65535)",
1443 "Interface IPv6 config commands\n"
1444 "Neighbor discovery\n"
1449 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1450 struct zebra_if
*zif
= ifp
->info
;
1451 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1455 DEFUN (no_ipv6_nd_mtu
,
1457 "no ipv6 nd mtu [(1-65535)]",
1459 "Interface IPv6 config commands\n"
1460 "Neighbor discovery\n"
1464 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1465 struct zebra_if
*zif
= ifp
->info
;
1466 zif
->rtadv
.AdvLinkMTU
= 0;
1470 /* Dump interface ND information to vty. */
1471 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1473 struct zebra_if
*zif
;
1474 struct rtadvconf
*rtadv
;
1477 zif
= (struct zebra_if
*)ifp
->info
;
1478 rtadv
= &zif
->rtadv
;
1480 if (rtadv
->AdvSendAdvertisements
) {
1482 " ND advertised reachable time is %d milliseconds\n",
1483 rtadv
->AdvReachableTime
);
1485 " ND advertised retransmit interval is %d milliseconds\n",
1486 rtadv
->AdvRetransTimer
);
1487 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1488 zif
->ra_sent
, zif
->ra_rcvd
);
1489 interval
= rtadv
->MaxRtrAdvInterval
;
1490 if (interval
% 1000)
1492 " ND router advertisements are sent every "
1493 "%d milliseconds\n",
1497 " ND router advertisements are sent every "
1500 if (rtadv
->AdvDefaultLifetime
!= -1)
1502 " ND router advertisements live for %d seconds\n",
1503 rtadv
->AdvDefaultLifetime
);
1506 " ND router advertisements lifetime tracks ra-interval\n");
1508 " ND router advertisement default router preference is "
1510 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1511 if (rtadv
->AdvManagedFlag
)
1513 " Hosts use DHCP to obtain routable addresses.\n");
1516 " Hosts use stateless autoconfig for addresses.\n");
1517 if (rtadv
->AdvHomeAgentFlag
) {
1519 " ND router advertisements with Home Agent flag bit set.\n");
1520 if (rtadv
->HomeAgentLifetime
!= -1)
1522 " Home Agent lifetime is %u seconds\n",
1523 rtadv
->HomeAgentLifetime
);
1526 " Home Agent lifetime tracks ra-lifetime\n");
1527 vty_out(vty
, " Home Agent preference is %u\n",
1528 rtadv
->HomeAgentPreference
);
1530 if (rtadv
->AdvIntervalOption
)
1532 " ND router advertisements with Adv. Interval option.\n");
1538 /* Write configuration about router advertisement. */
1539 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1541 struct zebra_if
*zif
;
1542 struct listnode
*node
;
1543 struct rtadv_prefix
*rprefix
;
1544 char buf
[PREFIX_STRLEN
];
1549 if (!(if_is_loopback(ifp
)
1550 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1551 if (zif
->rtadv
.AdvSendAdvertisements
)
1552 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1555 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1556 if (interval
% 1000)
1557 vty_out(vty
, " ipv6 nd ra-interval msec %d\n", interval
);
1558 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1559 vty_out(vty
, " ipv6 nd ra-interval %d\n", interval
/ 1000);
1561 if (zif
->rtadv
.AdvIntervalOption
)
1562 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1564 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1565 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1566 zif
->rtadv
.AdvDefaultLifetime
);
1568 if (zif
->rtadv
.HomeAgentPreference
)
1569 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1570 zif
->rtadv
.HomeAgentPreference
);
1572 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1573 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1574 zif
->rtadv
.HomeAgentLifetime
);
1576 if (zif
->rtadv
.AdvHomeAgentFlag
)
1577 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1579 if (zif
->rtadv
.AdvReachableTime
)
1580 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1581 zif
->rtadv
.AdvReachableTime
);
1583 if (zif
->rtadv
.AdvManagedFlag
)
1584 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1586 if (zif
->rtadv
.AdvOtherConfigFlag
)
1587 vty_out(vty
, " ipv6 nd other-config-flag\n");
1589 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1590 vty_out(vty
, " ipv6 nd router-preference %s\n",
1591 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1593 if (zif
->rtadv
.AdvLinkMTU
)
1594 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1596 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1597 vty_out(vty
, " ipv6 nd prefix %s",
1598 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1599 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1600 || (rprefix
->AdvPreferredLifetime
1601 != RTADV_PREFERRED_LIFETIME
)) {
1602 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1603 vty_out(vty
, " infinite");
1605 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1606 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1607 vty_out(vty
, " infinite");
1610 rprefix
->AdvPreferredLifetime
);
1612 if (!rprefix
->AdvOnLinkFlag
)
1613 vty_out(vty
, " off-link");
1614 if (!rprefix
->AdvAutonomousFlag
)
1615 vty_out(vty
, " no-autoconfig");
1616 if (rprefix
->AdvRouterAddressFlag
)
1617 vty_out(vty
, " router-address");
1624 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1626 struct rtadv
*rtadv
= &zns
->rtadv
;
1630 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1632 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1636 if (rtadv
->ra_timer
) {
1637 thread_cancel(rtadv
->ra_timer
);
1638 rtadv
->ra_timer
= NULL
;
1640 if (rtadv
->ra_read
) {
1641 thread_cancel(rtadv
->ra_read
);
1642 rtadv
->ra_read
= NULL
;
1646 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1649 case RTADV_TIMER_MSEC
:
1650 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1654 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1663 void rtadv_init(struct zebra_ns
*zns
)
1665 zns
->rtadv
.sock
= rtadv_make_socket();
1668 void rtadv_terminate(struct zebra_ns
*zns
)
1670 rtadv_event(zns
, RTADV_STOP
, 0);
1671 if (zns
->rtadv
.sock
>= 0) {
1672 close(zns
->rtadv
.sock
);
1673 zns
->rtadv
.sock
= -1;
1676 zns
->rtadv
.adv_if_count
= 0;
1677 zns
->rtadv
.adv_msec_if_count
= 0;
1680 void rtadv_cmd_init(void)
1682 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1683 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1685 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1686 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1687 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1688 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1689 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1690 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1691 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1692 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1693 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1694 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1695 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1696 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1697 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1698 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1699 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1700 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1701 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1702 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1703 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1704 install_element(INTERFACE_NODE
,
1705 &ipv6_nd_adv_interval_config_option_cmd
);
1706 install_element(INTERFACE_NODE
,
1707 &no_ipv6_nd_adv_interval_config_option_cmd
);
1708 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1709 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1710 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1711 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1712 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1713 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1716 static int if_join_all_router(int sock
, struct interface
*ifp
)
1720 struct ipv6_mreq mreq
;
1722 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1723 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1724 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1726 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1729 zlog_warn("%s(%u): Failed to join group, socket %u error %s",
1730 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1732 if (IS_ZEBRA_DEBUG_EVENT
)
1734 "%s(%u): Join All-Routers multicast group, socket %u",
1735 ifp
->name
, ifp
->ifindex
, sock
);
1740 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1744 struct ipv6_mreq mreq
;
1746 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1747 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1748 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1750 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1753 zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
1754 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1756 if (IS_ZEBRA_DEBUG_EVENT
)
1758 "%s(%u): Leave All-Routers multicast group, socket %u",
1759 ifp
->name
, ifp
->ifindex
, sock
);
1765 void rtadv_init(struct zebra_ns
*zns
)
1769 void rtadv_terminate(struct zebra_ns
*zns
)
1773 void rtadv_cmd_init(void)
1777 #endif /* HAVE_RTADV */