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
, ZEBRA_INTERFACE_VRF_LOOPBACK
)
402 || !if_is_operative(ifp
))
407 if (zif
->rtadv
.AdvSendAdvertisements
) {
408 if (zif
->rtadv
.inFastRexmit
) {
409 /* We assume we fast rexmit every sec so no
411 if (--zif
->rtadv
.NumFastReXmitsRemain
<= 0)
412 zif
->rtadv
.inFastRexmit
= 0;
414 if (IS_ZEBRA_DEBUG_SEND
)
416 "Fast RA Rexmit on interface %s",
419 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
421 zif
->rtadv
.AdvIntervalTimer
-= period
;
422 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
423 /* FIXME: using MaxRtrAdvInterval each
424 time isn't what section
425 6.2.4 of RFC4861 tells to do. */
426 zif
->rtadv
.AdvIntervalTimer
=
427 zif
->rtadv
.MaxRtrAdvInterval
;
428 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
437 static void rtadv_process_solicit(struct interface
*ifp
)
439 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
440 struct zebra_ns
*zns
= zvrf
->zns
;
443 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
446 static void rtadv_process_advert(u_char
*msg
, unsigned int len
,
447 struct interface
*ifp
,
448 struct sockaddr_in6
*addr
)
450 struct nd_router_advert
*radvert
;
451 char addr_str
[INET6_ADDRSTRLEN
];
452 struct zebra_if
*zif
;
457 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
459 if (len
< sizeof(struct nd_router_advert
)) {
460 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
461 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
464 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
466 "%s(%u): Rx RA with non-linklocal source address from %s",
467 ifp
->name
, ifp
->ifindex
, addr_str
);
471 radvert
= (struct nd_router_advert
*)msg
;
473 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
474 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
476 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
477 ifp
->name
, ifp
->ifindex
, addr_str
);
480 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
481 && !zif
->rtadv
.AdvManagedFlag
) {
483 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
484 ifp
->name
, ifp
->ifindex
, addr_str
);
487 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
488 && !zif
->rtadv
.AdvOtherConfigFlag
) {
490 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
491 ifp
->name
, ifp
->ifindex
, addr_str
);
494 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
495 && (ntohl(radvert
->nd_ra_reachable
)
496 != zif
->rtadv
.AdvReachableTime
)) {
498 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
499 ifp
->name
, ifp
->ifindex
, addr_str
);
502 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
503 && (ntohl(radvert
->nd_ra_retransmit
)
504 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
506 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
507 ifp
->name
, ifp
->ifindex
, addr_str
);
510 /* Create entry for neighbor if not known. */
512 IPV6_ADDR_COPY(&p
.u
.prefix
, &addr
->sin6_addr
);
513 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
515 if (!nbr_connected_check(ifp
, &p
))
516 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
520 static void rtadv_process_packet(u_char
*buf
, unsigned int len
,
521 ifindex_t ifindex
, int hoplimit
,
522 struct sockaddr_in6
*from
,
523 struct zebra_ns
*zns
)
525 struct icmp6_hdr
*icmph
;
526 struct interface
*ifp
;
527 struct zebra_if
*zif
;
528 char addr_str
[INET6_ADDRSTRLEN
];
530 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
532 /* Interface search. */
533 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
535 zlog_warn("RA/RS received on unknown IF %u from %s", ifindex
,
540 if (IS_ZEBRA_DEBUG_PACKET
)
541 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
542 ifp
->ifindex
, len
, addr_str
);
544 if (if_is_loopback(ifp
)
545 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
548 /* Check interface configuration. */
550 if (!zif
->rtadv
.AdvSendAdvertisements
)
553 /* ICMP message length check. */
554 if (len
< sizeof(struct icmp6_hdr
)) {
555 zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
556 ifp
->name
, ifp
->ifindex
, len
);
560 icmph
= (struct icmp6_hdr
*)buf
;
562 /* ICMP message type check. */
563 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
564 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
565 zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
566 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
570 /* Hoplimit check. */
571 if (hoplimit
>= 0 && hoplimit
!= 255) {
572 zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
573 ifp
->ifindex
, hoplimit
);
577 /* Check ICMP message type. */
578 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
579 rtadv_process_solicit(ifp
);
580 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
581 rtadv_process_advert(buf
, len
, ifp
, from
);
586 static int rtadv_read(struct thread
*thread
)
590 u_char buf
[RTADV_MSG_SIZE
];
591 struct sockaddr_in6 from
;
592 ifindex_t ifindex
= 0;
594 struct zebra_ns
*zns
= THREAD_ARG(thread
);
596 sock
= THREAD_FD(thread
);
597 zns
->rtadv
.ra_read
= NULL
;
599 /* Register myself. */
600 rtadv_event(zns
, RTADV_READ
, sock
);
602 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
606 zlog_warn("RA/RS recv failed, socket %u error %s", sock
,
607 safe_strerror(errno
));
611 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
616 static int rtadv_make_socket(void)
620 struct icmp6_filter filter
;
622 if (zserv_privs
.change(ZPRIVS_RAISE
))
623 zlog_err("rtadv_make_socket: could not raise privs, %s",
624 safe_strerror(errno
));
626 sock
= socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
628 if (zserv_privs
.change(ZPRIVS_LOWER
))
629 zlog_err("rtadv_make_socket: could not lower privs, %s",
630 safe_strerror(errno
));
636 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
641 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
646 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
651 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
656 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
662 ICMP6_FILTER_SETBLOCKALL(&filter
);
663 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
664 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
666 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
667 sizeof(struct icmp6_filter
));
669 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
676 static struct rtadv_prefix
*rtadv_prefix_new(void)
678 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
681 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
683 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
686 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
687 struct prefix_ipv6
*p
)
689 struct listnode
*node
;
690 struct rtadv_prefix
*rprefix
;
692 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
693 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
699 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
700 struct prefix_ipv6
*p
)
702 struct rtadv_prefix
*rprefix
;
704 rprefix
= rtadv_prefix_lookup(rplist
, p
);
708 rprefix
= rtadv_prefix_new();
709 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
710 listnode_add(rplist
, rprefix
);
715 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
717 struct rtadv_prefix
*rprefix
;
719 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
721 /* Set parameters. */
722 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
723 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
724 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
725 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
726 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
729 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
731 struct rtadv_prefix
*rprefix
;
733 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
734 if (rprefix
!= NULL
) {
735 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
736 rtadv_prefix_free(rprefix
);
742 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
743 ipv6_nd_suppress_ra_status status
)
745 struct zebra_if
*zif
;
746 struct zebra_vrf
*zvrf
;
747 struct zebra_ns
*zns
;
750 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
753 if (status
== RA_SUPPRESS
) {
754 /* RA is currently enabled */
755 if (zif
->rtadv
.AdvSendAdvertisements
) {
756 zif
->rtadv
.AdvSendAdvertisements
= 0;
757 zif
->rtadv
.AdvIntervalTimer
= 0;
758 zns
->rtadv
.adv_if_count
--;
760 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
762 if (zns
->rtadv
.adv_if_count
== 0)
763 rtadv_event(zns
, RTADV_STOP
, 0);
766 if (!zif
->rtadv
.AdvSendAdvertisements
) {
767 zif
->rtadv
.AdvSendAdvertisements
= 1;
768 zif
->rtadv
.AdvIntervalTimer
= 0;
769 zns
->rtadv
.adv_if_count
++;
771 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
772 /* Enable Fast RA only when RA interval is in
774 zif
->rtadv
.inFastRexmit
= 1;
775 zif
->rtadv
.NumFastReXmitsRemain
=
776 RTADV_NUM_FAST_REXMITS
;
779 if_join_all_router(zns
->rtadv
.sock
, ifp
);
781 if (zns
->rtadv
.adv_if_count
== 1)
782 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
788 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
789 * Note that while the client could request RA on an interface on which the
790 * operator has not enabled RA, RA won't be disabled upon client request
791 * if the operator has explicitly enabled RA. The enable request can also
792 * specify a RA interval (in seconds).
794 void zebra_interface_radv_set(struct zserv
*client
, int sock
, u_short length
,
795 struct zebra_vrf
*zvrf
, int enable
)
798 unsigned int ifindex
;
799 struct interface
*ifp
;
800 struct zebra_if
*zif
;
805 /* Get interface index and RA interval. */
806 ifindex
= stream_getl(s
);
807 ra_interval
= stream_getl(s
);
809 if (IS_ZEBRA_DEBUG_EVENT
)
810 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
811 zvrf_id(zvrf
), ifindex
,
812 enable
? "enable" : "disable",
813 zebra_route_string(client
->proto
), ra_interval
);
815 /* Locate interface and check VRF match. */
816 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
818 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
819 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
820 zebra_route_string(client
->proto
));
823 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
824 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
825 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
826 zebra_route_string(client
->proto
), ifp
->vrf_id
);
832 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
834 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
)
835 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
837 if (!zif
->rtadv
.configured
) {
838 zif
->rtadv
.MaxRtrAdvInterval
=
839 RTADV_MAX_RTR_ADV_INTERVAL
;
840 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
845 DEFUN (ipv6_nd_suppress_ra
,
846 ipv6_nd_suppress_ra_cmd
,
847 "ipv6 nd suppress-ra",
848 "Interface IPv6 config commands\n"
849 "Neighbor discovery\n"
850 "Suppress Router Advertisement\n")
852 VTY_DECLVAR_CONTEXT(interface
, ifp
);
853 struct zebra_if
*zif
= ifp
->info
;
855 if (if_is_loopback(ifp
)
856 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
858 "Cannot configure IPv6 Router Advertisements on this interface\n");
859 return CMD_WARNING_CONFIG_FAILED
;
862 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
863 zif
->rtadv
.configured
= 0;
867 DEFUN (no_ipv6_nd_suppress_ra
,
868 no_ipv6_nd_suppress_ra_cmd
,
869 "no ipv6 nd suppress-ra",
871 "Interface IPv6 config commands\n"
872 "Neighbor discovery\n"
873 "Suppress Router Advertisement\n")
875 VTY_DECLVAR_CONTEXT(interface
, ifp
);
876 struct zebra_if
*zif
= ifp
->info
;
878 if (if_is_loopback(ifp
)
879 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
881 "Cannot configure IPv6 Router Advertisements on this interface\n");
882 return CMD_WARNING_CONFIG_FAILED
;
885 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
886 zif
->rtadv
.configured
= 1;
890 DEFUN (ipv6_nd_ra_interval_msec
,
891 ipv6_nd_ra_interval_msec_cmd
,
892 "ipv6 nd ra-interval msec (70-1800000)",
893 "Interface IPv6 config commands\n"
894 "Neighbor discovery\n"
895 "Router Advertisement interval\n"
896 "Router Advertisement interval in milliseconds\n"
897 "Router Advertisement interval in milliseconds\n")
900 VTY_DECLVAR_CONTEXT(interface
, ifp
);
902 struct zebra_if
*zif
= ifp
->info
;
903 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
904 struct zebra_ns
*zns
;
907 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
908 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
909 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
911 "This ra-interval would conflict with configured ra-lifetime!\n");
912 return CMD_WARNING_CONFIG_FAILED
;
915 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
916 zns
->rtadv
.adv_msec_if_count
--;
919 zns
->rtadv
.adv_msec_if_count
++;
921 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
922 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
923 zif
->rtadv
.AdvIntervalTimer
= 0;
928 DEFUN (ipv6_nd_ra_interval
,
929 ipv6_nd_ra_interval_cmd
,
930 "ipv6 nd ra-interval (1-1800)",
931 "Interface IPv6 config commands\n"
932 "Neighbor discovery\n"
933 "Router Advertisement interval\n"
934 "Router Advertisement interval in seconds\n")
937 VTY_DECLVAR_CONTEXT(interface
, ifp
);
939 struct zebra_if
*zif
= ifp
->info
;
940 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
941 struct zebra_ns
*zns
;
944 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
945 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
946 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
948 "This ra-interval would conflict with configured ra-lifetime!\n");
949 return CMD_WARNING_CONFIG_FAILED
;
952 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
953 zns
->rtadv
.adv_msec_if_count
--;
955 /* convert to milliseconds */
956 interval
= interval
* 1000;
958 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
959 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
960 zif
->rtadv
.AdvIntervalTimer
= 0;
965 DEFUN (no_ipv6_nd_ra_interval
,
966 no_ipv6_nd_ra_interval_cmd
,
967 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
969 "Interface IPv6 config commands\n"
970 "Neighbor discovery\n"
971 "Router Advertisement interval\n"
972 "Router Advertisement interval in seconds\n"
973 "Specify millisecond router advertisement interval\n"
974 "Router Advertisement interval in milliseconds\n")
976 VTY_DECLVAR_CONTEXT(interface
, ifp
);
977 struct zebra_if
*zif
= ifp
->info
;
978 struct zebra_vrf
*zvrf
;
979 struct zebra_ns
*zns
;
981 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
984 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
985 zns
->rtadv
.adv_msec_if_count
--;
987 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
988 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
989 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
994 DEFUN (ipv6_nd_ra_lifetime
,
995 ipv6_nd_ra_lifetime_cmd
,
996 "ipv6 nd ra-lifetime (0-9000)",
997 "Interface IPv6 config commands\n"
998 "Neighbor discovery\n"
1000 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1003 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1004 struct zebra_if
*zif
= ifp
->info
;
1007 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1009 /* The value to be placed in the Router Lifetime field
1010 * of Router Advertisements sent from the interface,
1011 * in seconds. MUST be either zero or between
1012 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1013 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1015 "This ra-lifetime would conflict with configured ra-interval\n");
1016 return CMD_WARNING_CONFIG_FAILED
;
1019 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1024 DEFUN (no_ipv6_nd_ra_lifetime
,
1025 no_ipv6_nd_ra_lifetime_cmd
,
1026 "no ipv6 nd ra-lifetime [(0-9000)]",
1028 "Interface IPv6 config commands\n"
1029 "Neighbor discovery\n"
1031 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1033 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1034 struct zebra_if
*zif
= ifp
->info
;
1036 zif
->rtadv
.AdvDefaultLifetime
= -1;
1041 DEFUN (ipv6_nd_reachable_time
,
1042 ipv6_nd_reachable_time_cmd
,
1043 "ipv6 nd reachable-time (1-3600000)",
1044 "Interface IPv6 config commands\n"
1045 "Neighbor discovery\n"
1047 "Reachable time in milliseconds\n")
1050 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1051 struct zebra_if
*zif
= ifp
->info
;
1052 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1056 DEFUN (no_ipv6_nd_reachable_time
,
1057 no_ipv6_nd_reachable_time_cmd
,
1058 "no ipv6 nd reachable-time [(1-3600000)]",
1060 "Interface IPv6 config commands\n"
1061 "Neighbor discovery\n"
1063 "Reachable time in milliseconds\n")
1065 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1066 struct zebra_if
*zif
= ifp
->info
;
1068 zif
->rtadv
.AdvReachableTime
= 0;
1073 DEFUN (ipv6_nd_homeagent_preference
,
1074 ipv6_nd_homeagent_preference_cmd
,
1075 "ipv6 nd home-agent-preference (0-65535)",
1076 "Interface IPv6 config commands\n"
1077 "Neighbor discovery\n"
1078 "Home Agent preference\n"
1079 "preference value (default is 0, least preferred)\n")
1082 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1083 struct zebra_if
*zif
= ifp
->info
;
1084 zif
->rtadv
.HomeAgentPreference
=
1085 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1089 DEFUN (no_ipv6_nd_homeagent_preference
,
1090 no_ipv6_nd_homeagent_preference_cmd
,
1091 "no ipv6 nd home-agent-preference [(0-65535)]",
1093 "Interface IPv6 config commands\n"
1094 "Neighbor discovery\n"
1095 "Home Agent preference\n"
1096 "preference value (default is 0, least preferred)\n")
1098 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1099 struct zebra_if
*zif
= ifp
->info
;
1101 zif
->rtadv
.HomeAgentPreference
= 0;
1106 DEFUN (ipv6_nd_homeagent_lifetime
,
1107 ipv6_nd_homeagent_lifetime_cmd
,
1108 "ipv6 nd home-agent-lifetime (0-65520)",
1109 "Interface IPv6 config commands\n"
1110 "Neighbor discovery\n"
1111 "Home Agent lifetime\n"
1112 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1115 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1116 struct zebra_if
*zif
= ifp
->info
;
1117 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1121 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1122 no_ipv6_nd_homeagent_lifetime_cmd
,
1123 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1125 "Interface IPv6 config commands\n"
1126 "Neighbor discovery\n"
1127 "Home Agent lifetime\n"
1128 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1130 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1131 struct zebra_if
*zif
= ifp
->info
;
1133 zif
->rtadv
.HomeAgentLifetime
= -1;
1138 DEFUN (ipv6_nd_managed_config_flag
,
1139 ipv6_nd_managed_config_flag_cmd
,
1140 "ipv6 nd managed-config-flag",
1141 "Interface IPv6 config commands\n"
1142 "Neighbor discovery\n"
1143 "Managed address configuration flag\n")
1145 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1146 struct zebra_if
*zif
= ifp
->info
;
1148 zif
->rtadv
.AdvManagedFlag
= 1;
1153 DEFUN (no_ipv6_nd_managed_config_flag
,
1154 no_ipv6_nd_managed_config_flag_cmd
,
1155 "no ipv6 nd managed-config-flag",
1157 "Interface IPv6 config commands\n"
1158 "Neighbor discovery\n"
1159 "Managed address configuration flag\n")
1161 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1162 struct zebra_if
*zif
= ifp
->info
;
1164 zif
->rtadv
.AdvManagedFlag
= 0;
1169 DEFUN (ipv6_nd_homeagent_config_flag
,
1170 ipv6_nd_homeagent_config_flag_cmd
,
1171 "ipv6 nd home-agent-config-flag",
1172 "Interface IPv6 config commands\n"
1173 "Neighbor discovery\n"
1174 "Home Agent configuration flag\n")
1176 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1177 struct zebra_if
*zif
= ifp
->info
;
1179 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1184 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1185 no_ipv6_nd_homeagent_config_flag_cmd
,
1186 "no ipv6 nd home-agent-config-flag",
1188 "Interface IPv6 config commands\n"
1189 "Neighbor discovery\n"
1190 "Home Agent configuration flag\n")
1192 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1193 struct zebra_if
*zif
= ifp
->info
;
1195 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1200 DEFUN (ipv6_nd_adv_interval_config_option
,
1201 ipv6_nd_adv_interval_config_option_cmd
,
1202 "ipv6 nd adv-interval-option",
1203 "Interface IPv6 config commands\n"
1204 "Neighbor discovery\n"
1205 "Advertisement Interval Option\n")
1207 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1208 struct zebra_if
*zif
= ifp
->info
;
1210 zif
->rtadv
.AdvIntervalOption
= 1;
1215 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1216 no_ipv6_nd_adv_interval_config_option_cmd
,
1217 "no ipv6 nd adv-interval-option",
1219 "Interface IPv6 config commands\n"
1220 "Neighbor discovery\n"
1221 "Advertisement Interval Option\n")
1223 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1224 struct zebra_if
*zif
= ifp
->info
;
1226 zif
->rtadv
.AdvIntervalOption
= 0;
1231 DEFUN (ipv6_nd_other_config_flag
,
1232 ipv6_nd_other_config_flag_cmd
,
1233 "ipv6 nd other-config-flag",
1234 "Interface IPv6 config commands\n"
1235 "Neighbor discovery\n"
1236 "Other statefull configuration flag\n")
1238 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1239 struct zebra_if
*zif
= ifp
->info
;
1241 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1246 DEFUN (no_ipv6_nd_other_config_flag
,
1247 no_ipv6_nd_other_config_flag_cmd
,
1248 "no ipv6 nd other-config-flag",
1250 "Interface IPv6 config commands\n"
1251 "Neighbor discovery\n"
1252 "Other statefull configuration flag\n")
1254 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1255 struct zebra_if
*zif
= ifp
->info
;
1257 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1262 DEFUN (ipv6_nd_prefix
,
1264 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1265 "Interface IPv6 config commands\n"
1266 "Neighbor discovery\n"
1267 "Prefix information\n"
1269 "Valid lifetime in seconds\n"
1270 "Infinite valid lifetime\n"
1271 "Preferred lifetime in seconds\n"
1272 "Infinite preferred lifetime\n"
1273 "Set Router Address flag\n"
1274 "Do not use prefix for onlink determination\n"
1275 "Do not use prefix for autoconfiguration\n"
1276 "Do not use prefix for autoconfiguration\n"
1277 "Do not use prefix for onlink determination\n")
1280 char *prefix
= argv
[3]->arg
;
1281 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1282 || strmatch(argv
[4]->text
, "infinite"));
1283 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1285 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1287 char *lifetime
= NULL
, *preflifetime
= NULL
;
1288 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1290 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1292 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1297 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1299 offlink
= (argc
> idx_routeropts
+ 1
1300 || strmatch(argv
[idx_routeropts
]->text
,
1302 noautoconf
= (argc
> idx_routeropts
+ 1
1303 || strmatch(argv
[idx_routeropts
]->text
,
1309 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1310 struct zebra_if
*zebra_if
= ifp
->info
;
1312 struct rtadv_prefix rp
;
1314 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1316 vty_out(vty
, "Malformed IPv6 prefix\n");
1317 return CMD_WARNING_CONFIG_FAILED
;
1319 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1320 rp
.AdvOnLinkFlag
= !offlink
;
1321 rp
.AdvAutonomousFlag
= !noautoconf
;
1322 rp
.AdvRouterAddressFlag
= routeraddr
;
1323 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1324 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1327 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1329 : strtoll(lifetime
, NULL
, 10);
1330 rp
.AdvPreferredLifetime
=
1331 strmatch(preflifetime
, "infinite")
1333 : strtoll(preflifetime
, NULL
, 10);
1334 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1335 vty_out(vty
, "Invalid preferred lifetime\n");
1336 return CMD_WARNING_CONFIG_FAILED
;
1340 rtadv_prefix_set(zebra_if
, &rp
);
1345 DEFUN (no_ipv6_nd_prefix
,
1346 no_ipv6_nd_prefix_cmd
,
1347 "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]>]",
1349 "Interface IPv6 config commands\n"
1350 "Neighbor discovery\n"
1351 "Prefix information\n"
1353 "Valid lifetime in seconds\n"
1354 "Infinite valid lifetime\n"
1355 "Preferred lifetime in seconds\n"
1356 "Infinite preferred lifetime\n"
1357 "Set Router Address flag\n"
1358 "Do not use prefix for onlink determination\n"
1359 "Do not use prefix for autoconfiguration\n"
1360 "Do not use prefix for autoconfiguration\n"
1361 "Do not use prefix for onlink determination\n")
1363 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1364 struct zebra_if
*zebra_if
= ifp
->info
;
1366 struct rtadv_prefix rp
;
1367 char *prefix
= argv
[4]->arg
;
1369 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1371 vty_out(vty
, "Malformed IPv6 prefix\n");
1372 return CMD_WARNING_CONFIG_FAILED
;
1374 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1376 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1378 vty_out(vty
, "Non-existant IPv6 prefix\n");
1379 return CMD_WARNING_CONFIG_FAILED
;
1385 DEFUN (ipv6_nd_router_preference
,
1386 ipv6_nd_router_preference_cmd
,
1387 "ipv6 nd router-preference <high|medium|low>",
1388 "Interface IPv6 config commands\n"
1389 "Neighbor discovery\n"
1390 "Default router preference\n"
1391 "High default router preference\n"
1392 "Medium default router preference (default)\n"
1393 "Low default router preference\n")
1395 int idx_high_medium_low
= 3;
1396 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1397 struct zebra_if
*zif
= ifp
->info
;
1400 while (0 != rtadv_pref_strs
[i
]) {
1401 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1404 zif
->rtadv
.DefaultPreference
= i
;
1410 return CMD_ERR_NO_MATCH
;
1413 DEFUN (no_ipv6_nd_router_preference
,
1414 no_ipv6_nd_router_preference_cmd
,
1415 "no ipv6 nd router-preference [<high|medium|low>]",
1417 "Interface IPv6 config commands\n"
1418 "Neighbor discovery\n"
1419 "Default router preference\n"
1420 "High default router preference\n"
1421 "Medium default router preference (default)\n"
1422 "Low default router preference\n")
1424 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1425 struct zebra_if
*zif
= ifp
->info
;
1427 zif
->rtadv
.DefaultPreference
=
1428 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1435 "ipv6 nd mtu (1-65535)",
1436 "Interface IPv6 config commands\n"
1437 "Neighbor discovery\n"
1442 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1443 struct zebra_if
*zif
= ifp
->info
;
1444 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1448 DEFUN (no_ipv6_nd_mtu
,
1450 "no ipv6 nd mtu [(1-65535)]",
1452 "Interface IPv6 config commands\n"
1453 "Neighbor discovery\n"
1457 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1458 struct zebra_if
*zif
= ifp
->info
;
1459 zif
->rtadv
.AdvLinkMTU
= 0;
1463 /* Dump interface ND information to vty. */
1464 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1466 struct zebra_if
*zif
;
1467 struct rtadvconf
*rtadv
;
1470 zif
= (struct zebra_if
*)ifp
->info
;
1471 rtadv
= &zif
->rtadv
;
1473 if (rtadv
->AdvSendAdvertisements
) {
1475 " ND advertised reachable time is %d milliseconds\n",
1476 rtadv
->AdvReachableTime
);
1478 " ND advertised retransmit interval is %d milliseconds\n",
1479 rtadv
->AdvRetransTimer
);
1480 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1481 zif
->ra_sent
, zif
->ra_rcvd
);
1482 interval
= rtadv
->MaxRtrAdvInterval
;
1483 if (interval
% 1000)
1485 " ND router advertisements are sent every "
1486 "%d milliseconds\n",
1490 " ND router advertisements are sent every "
1493 if (rtadv
->AdvDefaultLifetime
!= -1)
1495 " ND router advertisements live for %d seconds\n",
1496 rtadv
->AdvDefaultLifetime
);
1499 " ND router advertisements lifetime tracks ra-interval\n");
1501 " ND router advertisement default router preference is "
1503 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1504 if (rtadv
->AdvManagedFlag
)
1506 " Hosts use DHCP to obtain routable addresses.\n");
1509 " Hosts use stateless autoconfig for addresses.\n");
1510 if (rtadv
->AdvHomeAgentFlag
) {
1512 " ND router advertisements with Home Agent flag bit set.\n");
1513 if (rtadv
->HomeAgentLifetime
!= -1)
1515 " Home Agent lifetime is %u seconds\n",
1516 rtadv
->HomeAgentLifetime
);
1519 " Home Agent lifetime tracks ra-lifetime\n");
1520 vty_out(vty
, " Home Agent preference is %u\n",
1521 rtadv
->HomeAgentPreference
);
1523 if (rtadv
->AdvIntervalOption
)
1525 " ND router advertisements with Adv. Interval option.\n");
1531 /* Write configuration about router advertisement. */
1532 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1534 struct zebra_if
*zif
;
1535 struct listnode
*node
;
1536 struct rtadv_prefix
*rprefix
;
1537 char buf
[PREFIX_STRLEN
];
1542 if (!(if_is_loopback(ifp
)
1543 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1544 if (zif
->rtadv
.AdvSendAdvertisements
)
1545 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1548 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1549 if (interval
% 1000)
1550 vty_out(vty
, " ipv6 nd ra-interval msec %d\n", interval
);
1551 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1552 vty_out(vty
, " ipv6 nd ra-interval %d\n", interval
/ 1000);
1554 if (zif
->rtadv
.AdvIntervalOption
)
1555 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1557 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1558 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1559 zif
->rtadv
.AdvDefaultLifetime
);
1561 if (zif
->rtadv
.HomeAgentPreference
)
1562 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1563 zif
->rtadv
.HomeAgentPreference
);
1565 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1566 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1567 zif
->rtadv
.HomeAgentLifetime
);
1569 if (zif
->rtadv
.AdvHomeAgentFlag
)
1570 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1572 if (zif
->rtadv
.AdvReachableTime
)
1573 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1574 zif
->rtadv
.AdvReachableTime
);
1576 if (zif
->rtadv
.AdvManagedFlag
)
1577 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1579 if (zif
->rtadv
.AdvOtherConfigFlag
)
1580 vty_out(vty
, " ipv6 nd other-config-flag\n");
1582 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1583 vty_out(vty
, " ipv6 nd router-preference %s\n",
1584 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1586 if (zif
->rtadv
.AdvLinkMTU
)
1587 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1589 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1590 vty_out(vty
, " ipv6 nd prefix %s",
1591 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1592 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1593 || (rprefix
->AdvPreferredLifetime
1594 != RTADV_PREFERRED_LIFETIME
)) {
1595 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1596 vty_out(vty
, " infinite");
1598 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1599 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1600 vty_out(vty
, " infinite");
1603 rprefix
->AdvPreferredLifetime
);
1605 if (!rprefix
->AdvOnLinkFlag
)
1606 vty_out(vty
, " off-link");
1607 if (!rprefix
->AdvAutonomousFlag
)
1608 vty_out(vty
, " no-autoconfig");
1609 if (rprefix
->AdvRouterAddressFlag
)
1610 vty_out(vty
, " router-address");
1617 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1619 struct rtadv
*rtadv
= &zns
->rtadv
;
1623 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1625 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1629 if (rtadv
->ra_timer
) {
1630 thread_cancel(rtadv
->ra_timer
);
1631 rtadv
->ra_timer
= NULL
;
1633 if (rtadv
->ra_read
) {
1634 thread_cancel(rtadv
->ra_read
);
1635 rtadv
->ra_read
= NULL
;
1639 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1642 case RTADV_TIMER_MSEC
:
1643 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1647 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1656 void rtadv_init(struct zebra_ns
*zns
)
1658 zns
->rtadv
.sock
= rtadv_make_socket();
1661 void rtadv_terminate(struct zebra_ns
*zns
)
1663 rtadv_event(zns
, RTADV_STOP
, 0);
1664 if (zns
->rtadv
.sock
>= 0) {
1665 close(zns
->rtadv
.sock
);
1666 zns
->rtadv
.sock
= -1;
1669 zns
->rtadv
.adv_if_count
= 0;
1670 zns
->rtadv
.adv_msec_if_count
= 0;
1673 void rtadv_cmd_init(void)
1675 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1676 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1678 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1679 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1680 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1681 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1682 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1683 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1684 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1685 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1686 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1687 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1688 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1689 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1690 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1691 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1692 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1693 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1694 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1695 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1696 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1697 install_element(INTERFACE_NODE
,
1698 &ipv6_nd_adv_interval_config_option_cmd
);
1699 install_element(INTERFACE_NODE
,
1700 &no_ipv6_nd_adv_interval_config_option_cmd
);
1701 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1702 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1703 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1704 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1705 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1706 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1709 static int if_join_all_router(int sock
, struct interface
*ifp
)
1713 struct ipv6_mreq mreq
;
1715 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1716 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1717 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1719 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1722 zlog_warn("%s(%u): Failed to join group, socket %u error %s",
1723 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1725 if (IS_ZEBRA_DEBUG_EVENT
)
1727 "%s(%u): Join All-Routers multicast group, socket %u",
1728 ifp
->name
, ifp
->ifindex
, sock
);
1733 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1737 struct ipv6_mreq mreq
;
1739 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1740 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1741 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1743 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1746 zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
1747 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1749 if (IS_ZEBRA_DEBUG_EVENT
)
1751 "%s(%u): Leave All-Routers multicast group, socket %u",
1752 ifp
->name
, ifp
->ifindex
, sock
);
1758 void rtadv_init(struct zebra_ns
*zns
)
1762 void rtadv_terminate(struct zebra_ns
*zns
)
1766 void rtadv_cmd_init(void)
1770 #endif /* HAVE_RTADV */