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"
39 #include "zebra/interface.h"
40 #include "zebra/rtadv.h"
41 #include "zebra/debug.h"
42 #include "zebra/rib.h"
43 #include "zebra/zserv.h"
44 #include "zebra/zebra_ns.h"
45 #include "zebra/zebra_vrf.h"
47 extern struct zebra_privs_t zserv_privs
;
49 #if defined(HAVE_RTADV)
52 #include <netinet/icmp6.h>
55 /* If RFC2133 definition is used. */
56 #ifndef IPV6_JOIN_GROUP
57 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
59 #ifndef IPV6_LEAVE_GROUP
60 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
63 #define ALLNODE "ff02::1"
64 #define ALLROUTER "ff02::2"
66 /* Order is intentional. Matches RFC4191. This array is also used for
67 command matching, so only modify with care. */
68 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
78 static void rtadv_event(struct zebra_ns
*, enum rtadv_event
, int);
80 static int if_join_all_router(int, struct interface
*);
81 static int if_leave_all_router(int, struct interface
*);
83 static int rtadv_increment_received(struct zebra_ns
*zns
, ifindex_t
*ifindex
)
86 struct interface
*iface
;
89 iface
= if_lookup_by_index_per_ns(zns
, *ifindex
);
90 if (iface
&& iface
->info
) {
98 static int rtadv_recv_packet(struct zebra_ns
*zns
, int sock
, u_char
*buf
,
99 int buflen
, struct sockaddr_in6
*from
,
100 ifindex_t
*ifindex
, int *hoplimit
)
105 struct cmsghdr
*cmsgptr
;
110 /* Fill in message and iovec. */
111 memset(&msg
, 0, sizeof(msg
));
112 msg
.msg_name
= (void *)from
;
113 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
116 msg
.msg_control
= (void *)adata
;
117 msg
.msg_controllen
= sizeof adata
;
119 iov
.iov_len
= buflen
;
121 /* If recvmsg fail return minus value. */
122 ret
= recvmsg(sock
, &msg
, 0);
126 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
127 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
128 /* I want interface index which this packet comes from. */
129 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
130 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
131 struct in6_pktinfo
*ptr
;
133 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
134 *ifindex
= ptr
->ipi6_ifindex
;
135 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
138 /* Incoming packet's hop limit. */
139 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
140 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
141 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
146 rtadv_increment_received(zns
, ifindex
);
150 #define RTADV_MSG_SIZE 4096
152 /* Send router advertisement packet. */
153 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
157 struct cmsghdr
*cmsgptr
;
158 struct in6_pktinfo
*pkt
;
159 struct sockaddr_in6 addr
;
160 static void *adata
= NULL
;
161 unsigned char buf
[RTADV_MSG_SIZE
];
162 struct nd_router_advert
*rtadv
;
165 struct zebra_if
*zif
;
166 struct rtadv_prefix
*rprefix
;
167 u_char all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
168 0, 0, 0, 0, 0, 0, 0, 1};
169 struct listnode
*node
;
170 u_int16_t pkt_RouterLifetime
;
173 * Allocate control message bufffer. This is dynamic because
174 * CMSG_SPACE is not guaranteed not to call a function. Note that
175 * the size will be different on different architectures due to
176 * differing alignment rules.
179 /* XXX Free on shutdown. */
180 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
184 "rtadv_send_packet: can't malloc control data");
189 /* Logging of packet. */
190 if (IS_ZEBRA_DEBUG_PACKET
)
191 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
194 /* Fill in sockaddr_in6. */
195 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
196 addr
.sin6_family
= AF_INET6
;
198 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
199 #endif /* SIN6_LEN */
200 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
201 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
203 /* Fetch interface information. */
206 /* Make router advertisement message. */
207 rtadv
= (struct nd_router_advert
*)buf
;
209 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
210 rtadv
->nd_ra_code
= 0;
211 rtadv
->nd_ra_cksum
= 0;
213 rtadv
->nd_ra_curhoplimit
= 64;
215 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
216 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
218 : zif
->rtadv
.DefaultPreference
;
219 rtadv
->nd_ra_flags_reserved
<<= 3;
221 if (zif
->rtadv
.AdvManagedFlag
)
222 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
223 if (zif
->rtadv
.AdvOtherConfigFlag
)
224 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
225 if (zif
->rtadv
.AdvHomeAgentFlag
)
226 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
227 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
228 * AdvDefaultLifetime is by default based on the value of
229 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
230 * field of Router Advertisements. Given that this field is expressed
231 * in seconds, a small MaxRtrAdvInterval value can result in a zero
232 * value for this field. To prevent this, routers SHOULD keep
233 * AdvDefaultLifetime in at least one second, even if the use of
234 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
236 zif
->rtadv
.AdvDefaultLifetime
!= -1
237 ? zif
->rtadv
.AdvDefaultLifetime
238 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
239 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
240 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
241 rtadv
->nd_ra_retransmit
= htonl(0);
243 len
= sizeof(struct nd_router_advert
);
245 /* If both the Home Agent Preference and Home Agent Lifetime are set to
246 * their default values specified above, this option SHOULD NOT be
247 * included in the Router Advertisement messages sent by this home
248 * agent. -- RFC6275, 7.4 */
249 if (zif
->rtadv
.AdvHomeAgentFlag
250 && (zif
->rtadv
.HomeAgentPreference
251 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
252 struct nd_opt_homeagent_info
*ndopt_hai
=
253 (struct nd_opt_homeagent_info
*)(buf
+ len
);
254 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
255 ndopt_hai
->nd_opt_hai_len
= 1;
256 ndopt_hai
->nd_opt_hai_reserved
= 0;
257 ndopt_hai
->nd_opt_hai_preference
=
258 htons(zif
->rtadv
.HomeAgentPreference
);
259 /* 16-bit unsigned integer. The lifetime associated with the
261 * agent in units of seconds. The default value is the same as
263 * Router Lifetime, as specified in the main body of the Router
264 * Advertisement. The maximum value corresponds to 18.2 hours.
266 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
267 ndopt_hai
->nd_opt_hai_lifetime
=
268 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
269 ? zif
->rtadv
.HomeAgentLifetime
270 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
275 len
+= sizeof(struct nd_opt_homeagent_info
);
278 if (zif
->rtadv
.AdvIntervalOption
) {
279 struct nd_opt_adv_interval
*ndopt_adv
=
280 (struct nd_opt_adv_interval
*)(buf
+ len
);
281 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
282 ndopt_adv
->nd_opt_ai_len
= 1;
283 ndopt_adv
->nd_opt_ai_reserved
= 0;
284 ndopt_adv
->nd_opt_ai_interval
=
285 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
286 len
+= sizeof(struct nd_opt_adv_interval
);
289 /* Fill in prefix. */
290 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
291 struct nd_opt_prefix_info
*pinfo
;
293 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
295 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
296 pinfo
->nd_opt_pi_len
= 4;
297 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
299 pinfo
->nd_opt_pi_flags_reserved
= 0;
300 if (rprefix
->AdvOnLinkFlag
)
301 pinfo
->nd_opt_pi_flags_reserved
|=
302 ND_OPT_PI_FLAG_ONLINK
;
303 if (rprefix
->AdvAutonomousFlag
)
304 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
305 if (rprefix
->AdvRouterAddressFlag
)
306 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
308 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
309 pinfo
->nd_opt_pi_preferred_time
=
310 htonl(rprefix
->AdvPreferredLifetime
);
311 pinfo
->nd_opt_pi_reserved2
= 0;
313 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
314 &rprefix
->prefix
.prefix
);
318 u_char buf
[INET6_ADDRSTRLEN
];
320 zlog_debug("DEBUG %s",
321 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
322 buf
, INET6_ADDRSTRLEN
));
326 len
+= sizeof(struct nd_opt_prefix_info
);
329 /* Hardware address. */
330 if (ifp
->hw_addr_len
!= 0) {
331 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
333 /* Option length should be rounded up to next octet if
334 the link address does not end on an octet boundary. */
335 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
337 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
338 len
+= ifp
->hw_addr_len
;
340 /* Pad option to end on an octet boundary. */
341 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
342 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
346 if (zif
->rtadv
.AdvLinkMTU
) {
347 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
348 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
349 opt
->nd_opt_mtu_len
= 1;
350 opt
->nd_opt_mtu_reserved
= 0;
351 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
352 len
+= sizeof(struct nd_opt_mtu
);
355 msg
.msg_name
= (void *)&addr
;
356 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
359 msg
.msg_control
= (void *)adata
;
360 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
365 cmsgptr
= ZCMSG_FIRSTHDR(&msg
);
366 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
367 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
368 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
370 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
371 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
372 pkt
->ipi6_ifindex
= ifp
->ifindex
;
374 ret
= sendmsg(sock
, &msg
, 0);
376 zlog_err("%s(%u): Tx RA failed, socket %u error %d (%s)",
377 ifp
->name
, ifp
->ifindex
, sock
, errno
,
378 safe_strerror(errno
));
383 static int rtadv_timer(struct thread
*thread
)
385 struct zebra_ns
*zns
= THREAD_ARG(thread
);
387 struct interface
*ifp
;
388 struct zebra_if
*zif
;
391 zns
->rtadv
.ra_timer
= NULL
;
392 if (zns
->rtadv
.adv_msec_if_count
== 0) {
393 period
= 1000; /* 1 s */
394 rtadv_event(zns
, RTADV_TIMER
, 1 /* 1 s */);
396 period
= 10; /* 10 ms */
397 rtadv_event(zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
400 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
401 FOR_ALL_INTERFACES (vrf
, ifp
) {
402 if (if_is_loopback(ifp
)
403 || CHECK_FLAG(ifp
->status
,
404 ZEBRA_INTERFACE_VRF_LOOPBACK
)
405 || !if_is_operative(ifp
))
410 if (zif
->rtadv
.AdvSendAdvertisements
) {
411 if (zif
->rtadv
.inFastRexmit
) {
412 /* We assume we fast rexmit every sec so
415 if (--zif
->rtadv
.NumFastReXmitsRemain
417 zif
->rtadv
.inFastRexmit
= 0;
419 if (IS_ZEBRA_DEBUG_SEND
)
421 "Fast RA Rexmit on interface %s",
424 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
426 zif
->rtadv
.AdvIntervalTimer
-= period
;
427 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
429 MaxRtrAdvInterval each
430 time isn't what section
431 6.2.4 of RFC4861 tells to do.
433 zif
->rtadv
.AdvIntervalTimer
=
437 zns
->rtadv
.sock
, ifp
);
446 static void rtadv_process_solicit(struct interface
*ifp
)
448 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
449 struct zebra_ns
*zns
= zvrf
->zns
;
452 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
455 static void rtadv_process_advert(u_char
*msg
, unsigned int len
,
456 struct interface
*ifp
,
457 struct sockaddr_in6
*addr
)
459 struct nd_router_advert
*radvert
;
460 char addr_str
[INET6_ADDRSTRLEN
];
461 struct zebra_if
*zif
;
466 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
468 if (len
< sizeof(struct nd_router_advert
)) {
469 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
470 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
473 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
475 "%s(%u): Rx RA with non-linklocal source address from %s",
476 ifp
->name
, ifp
->ifindex
, addr_str
);
480 radvert
= (struct nd_router_advert
*)msg
;
482 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
483 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
485 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
486 ifp
->name
, ifp
->ifindex
, addr_str
);
489 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
490 && !zif
->rtadv
.AdvManagedFlag
) {
492 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
493 ifp
->name
, ifp
->ifindex
, addr_str
);
496 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
497 && !zif
->rtadv
.AdvOtherConfigFlag
) {
499 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
500 ifp
->name
, ifp
->ifindex
, addr_str
);
503 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
504 && (ntohl(radvert
->nd_ra_reachable
)
505 != zif
->rtadv
.AdvReachableTime
)) {
507 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
508 ifp
->name
, ifp
->ifindex
, addr_str
);
511 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
512 && (ntohl(radvert
->nd_ra_retransmit
)
513 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
515 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
516 ifp
->name
, ifp
->ifindex
, addr_str
);
519 /* Create entry for neighbor if not known. */
521 IPV6_ADDR_COPY(&p
.u
.prefix
, &addr
->sin6_addr
);
522 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
524 if (!nbr_connected_check(ifp
, &p
))
525 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
529 static void rtadv_process_packet(u_char
*buf
, unsigned int len
,
530 ifindex_t ifindex
, int hoplimit
,
531 struct sockaddr_in6
*from
,
532 struct zebra_ns
*zns
)
534 struct icmp6_hdr
*icmph
;
535 struct interface
*ifp
;
536 struct zebra_if
*zif
;
537 char addr_str
[INET6_ADDRSTRLEN
];
539 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
541 /* Interface search. */
542 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
544 zlog_warn("RA/RS received on unknown IF %u from %s", ifindex
,
549 if (IS_ZEBRA_DEBUG_PACKET
)
550 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
551 ifp
->ifindex
, len
, addr_str
);
553 if (if_is_loopback(ifp
)
554 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
557 /* Check interface configuration. */
559 if (!zif
->rtadv
.AdvSendAdvertisements
)
562 /* ICMP message length check. */
563 if (len
< sizeof(struct icmp6_hdr
)) {
564 zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
565 ifp
->name
, ifp
->ifindex
, len
);
569 icmph
= (struct icmp6_hdr
*)buf
;
571 /* ICMP message type check. */
572 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
573 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
574 zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
575 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
579 /* Hoplimit check. */
580 if (hoplimit
>= 0 && hoplimit
!= 255) {
581 zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
582 ifp
->ifindex
, hoplimit
);
586 /* Check ICMP message type. */
587 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
588 rtadv_process_solicit(ifp
);
589 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
590 rtadv_process_advert(buf
, len
, ifp
, from
);
595 static int rtadv_read(struct thread
*thread
)
599 u_char buf
[RTADV_MSG_SIZE
];
600 struct sockaddr_in6 from
;
601 ifindex_t ifindex
= 0;
603 struct zebra_ns
*zns
= THREAD_ARG(thread
);
605 sock
= THREAD_FD(thread
);
606 zns
->rtadv
.ra_read
= NULL
;
608 /* Register myself. */
609 rtadv_event(zns
, RTADV_READ
, sock
);
611 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
615 zlog_warn("RA/RS recv failed, socket %u error %s", sock
,
616 safe_strerror(errno
));
620 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
625 static int rtadv_make_socket(ns_id_t ns_id
)
629 struct icmp6_filter filter
;
631 if (zserv_privs
.change(ZPRIVS_RAISE
))
632 zlog_err("rtadv_make_socket: could not raise privs, %s",
633 safe_strerror(errno
));
635 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
637 if (zserv_privs
.change(ZPRIVS_LOWER
))
638 zlog_err("rtadv_make_socket: could not lower privs, %s",
639 safe_strerror(errno
));
645 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
650 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
655 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
660 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
665 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
671 ICMP6_FILTER_SETBLOCKALL(&filter
);
672 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
673 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
675 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
676 sizeof(struct icmp6_filter
));
678 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
686 static struct rtadv_prefix
*rtadv_prefix_new(void)
688 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
691 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
693 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
696 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
697 struct prefix_ipv6
*p
)
699 struct listnode
*node
;
700 struct rtadv_prefix
*rprefix
;
702 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
703 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
709 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
710 struct prefix_ipv6
*p
)
712 struct rtadv_prefix
*rprefix
;
714 rprefix
= rtadv_prefix_lookup(rplist
, p
);
718 rprefix
= rtadv_prefix_new();
719 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
720 listnode_add(rplist
, rprefix
);
725 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
727 struct rtadv_prefix
*rprefix
;
729 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
731 /* Set parameters. */
732 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
733 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
734 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
735 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
736 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
739 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
741 struct rtadv_prefix
*rprefix
;
743 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
744 if (rprefix
!= NULL
) {
745 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
746 rtadv_prefix_free(rprefix
);
752 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
753 ipv6_nd_suppress_ra_status status
)
755 struct zebra_if
*zif
;
756 struct zebra_vrf
*zvrf
;
757 struct zebra_ns
*zns
;
760 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
763 if (status
== RA_SUPPRESS
) {
764 /* RA is currently enabled */
765 if (zif
->rtadv
.AdvSendAdvertisements
) {
766 zif
->rtadv
.AdvSendAdvertisements
= 0;
767 zif
->rtadv
.AdvIntervalTimer
= 0;
768 zns
->rtadv
.adv_if_count
--;
770 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
772 if (zns
->rtadv
.adv_if_count
== 0)
773 rtadv_event(zns
, RTADV_STOP
, 0);
776 if (!zif
->rtadv
.AdvSendAdvertisements
) {
777 zif
->rtadv
.AdvSendAdvertisements
= 1;
778 zif
->rtadv
.AdvIntervalTimer
= 0;
779 zns
->rtadv
.adv_if_count
++;
781 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
782 /* Enable Fast RA only when RA interval is in
784 zif
->rtadv
.inFastRexmit
= 1;
785 zif
->rtadv
.NumFastReXmitsRemain
=
786 RTADV_NUM_FAST_REXMITS
;
789 if_join_all_router(zns
->rtadv
.sock
, ifp
);
791 if (zns
->rtadv
.adv_if_count
== 1)
792 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
798 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
799 * Note that while the client could request RA on an interface on which the
800 * operator has not enabled RA, RA won't be disabled upon client request
801 * if the operator has explicitly enabled RA. The enable request can also
802 * specify a RA interval (in seconds).
804 void zebra_interface_radv_set(struct zserv
*client
, u_short length
,
805 struct zebra_vrf
*zvrf
, int enable
)
809 struct interface
*ifp
;
810 struct zebra_if
*zif
;
815 /* Get interface index and RA interval. */
816 STREAM_GETL(s
, ifindex
);
817 STREAM_GETL(s
, ra_interval
);
819 if (IS_ZEBRA_DEBUG_EVENT
)
820 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
821 zvrf_id(zvrf
), ifindex
,
822 enable
? "enable" : "disable",
823 zebra_route_string(client
->proto
), ra_interval
);
825 /* Locate interface and check VRF match. */
826 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
828 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
829 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
830 zebra_route_string(client
->proto
));
833 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
834 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
835 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
836 zebra_route_string(client
->proto
), ifp
->vrf_id
);
842 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
843 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
845 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
846 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
847 VTY_RA_INTERVAL_CONFIGURED
))
848 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
850 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
851 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
852 VTY_RA_INTERVAL_CONFIGURED
))
853 zif
->rtadv
.MaxRtrAdvInterval
=
854 RTADV_MAX_RTR_ADV_INTERVAL
;
855 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
856 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
862 DEFUN (ipv6_nd_suppress_ra
,
863 ipv6_nd_suppress_ra_cmd
,
864 "ipv6 nd suppress-ra",
865 "Interface IPv6 config commands\n"
866 "Neighbor discovery\n"
867 "Suppress Router Advertisement\n")
869 VTY_DECLVAR_CONTEXT(interface
, ifp
);
870 struct zebra_if
*zif
= ifp
->info
;
872 if (if_is_loopback(ifp
)
873 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
875 "Cannot configure IPv6 Router Advertisements on this interface\n");
876 return CMD_WARNING_CONFIG_FAILED
;
879 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
880 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
882 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
886 DEFUN (no_ipv6_nd_suppress_ra
,
887 no_ipv6_nd_suppress_ra_cmd
,
888 "no ipv6 nd suppress-ra",
890 "Interface IPv6 config commands\n"
891 "Neighbor discovery\n"
892 "Suppress Router Advertisement\n")
894 VTY_DECLVAR_CONTEXT(interface
, ifp
);
895 struct zebra_if
*zif
= ifp
->info
;
897 if (if_is_loopback(ifp
)
898 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
900 "Cannot configure IPv6 Router Advertisements on this interface\n");
901 return CMD_WARNING_CONFIG_FAILED
;
904 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
905 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
909 DEFUN (ipv6_nd_ra_interval_msec
,
910 ipv6_nd_ra_interval_msec_cmd
,
911 "ipv6 nd ra-interval msec (70-1800000)",
912 "Interface IPv6 config commands\n"
913 "Neighbor discovery\n"
914 "Router Advertisement interval\n"
915 "Router Advertisement interval in milliseconds\n"
916 "Router Advertisement interval in milliseconds\n")
919 VTY_DECLVAR_CONTEXT(interface
, ifp
);
921 struct zebra_if
*zif
= ifp
->info
;
922 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
923 struct zebra_ns
*zns
;
926 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
927 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
928 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
930 "This ra-interval would conflict with configured ra-lifetime!\n");
931 return CMD_WARNING_CONFIG_FAILED
;
934 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
935 zns
->rtadv
.adv_msec_if_count
--;
938 zns
->rtadv
.adv_msec_if_count
++;
940 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
941 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
942 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
943 zif
->rtadv
.AdvIntervalTimer
= 0;
948 DEFUN (ipv6_nd_ra_interval
,
949 ipv6_nd_ra_interval_cmd
,
950 "ipv6 nd ra-interval (1-1800)",
951 "Interface IPv6 config commands\n"
952 "Neighbor discovery\n"
953 "Router Advertisement interval\n"
954 "Router Advertisement interval in seconds\n")
957 VTY_DECLVAR_CONTEXT(interface
, ifp
);
959 struct zebra_if
*zif
= ifp
->info
;
960 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
961 struct zebra_ns
*zns
;
964 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
965 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
966 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
968 "This ra-interval would conflict with configured ra-lifetime!\n");
969 return CMD_WARNING_CONFIG_FAILED
;
972 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
973 zns
->rtadv
.adv_msec_if_count
--;
975 /* convert to milliseconds */
976 interval
= interval
* 1000;
978 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
979 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
980 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
981 zif
->rtadv
.AdvIntervalTimer
= 0;
986 DEFUN (no_ipv6_nd_ra_interval
,
987 no_ipv6_nd_ra_interval_cmd
,
988 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
990 "Interface IPv6 config commands\n"
991 "Neighbor discovery\n"
992 "Router Advertisement interval\n"
993 "Router Advertisement interval in seconds\n"
994 "Specify millisecond router advertisement interval\n"
995 "Router Advertisement interval in milliseconds\n")
997 VTY_DECLVAR_CONTEXT(interface
, ifp
);
998 struct zebra_if
*zif
= ifp
->info
;
999 struct zebra_vrf
*zvrf
;
1000 struct zebra_ns
*zns
;
1002 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1005 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1006 zns
->rtadv
.adv_msec_if_count
--;
1008 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1010 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1011 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1013 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1015 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1016 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1021 DEFUN (ipv6_nd_ra_lifetime
,
1022 ipv6_nd_ra_lifetime_cmd
,
1023 "ipv6 nd ra-lifetime (0-9000)",
1024 "Interface IPv6 config commands\n"
1025 "Neighbor discovery\n"
1027 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1030 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1031 struct zebra_if
*zif
= ifp
->info
;
1034 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1036 /* The value to be placed in the Router Lifetime field
1037 * of Router Advertisements sent from the interface,
1038 * in seconds. MUST be either zero or between
1039 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1040 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1042 "This ra-lifetime would conflict with configured ra-interval\n");
1043 return CMD_WARNING_CONFIG_FAILED
;
1046 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1051 DEFUN (no_ipv6_nd_ra_lifetime
,
1052 no_ipv6_nd_ra_lifetime_cmd
,
1053 "no ipv6 nd ra-lifetime [(0-9000)]",
1055 "Interface IPv6 config commands\n"
1056 "Neighbor discovery\n"
1058 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1060 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1061 struct zebra_if
*zif
= ifp
->info
;
1063 zif
->rtadv
.AdvDefaultLifetime
= -1;
1068 DEFUN (ipv6_nd_reachable_time
,
1069 ipv6_nd_reachable_time_cmd
,
1070 "ipv6 nd reachable-time (1-3600000)",
1071 "Interface IPv6 config commands\n"
1072 "Neighbor discovery\n"
1074 "Reachable time in milliseconds\n")
1077 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1078 struct zebra_if
*zif
= ifp
->info
;
1079 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1083 DEFUN (no_ipv6_nd_reachable_time
,
1084 no_ipv6_nd_reachable_time_cmd
,
1085 "no ipv6 nd reachable-time [(1-3600000)]",
1087 "Interface IPv6 config commands\n"
1088 "Neighbor discovery\n"
1090 "Reachable time in milliseconds\n")
1092 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1093 struct zebra_if
*zif
= ifp
->info
;
1095 zif
->rtadv
.AdvReachableTime
= 0;
1100 DEFUN (ipv6_nd_homeagent_preference
,
1101 ipv6_nd_homeagent_preference_cmd
,
1102 "ipv6 nd home-agent-preference (0-65535)",
1103 "Interface IPv6 config commands\n"
1104 "Neighbor discovery\n"
1105 "Home Agent preference\n"
1106 "preference value (default is 0, least preferred)\n")
1109 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1110 struct zebra_if
*zif
= ifp
->info
;
1111 zif
->rtadv
.HomeAgentPreference
=
1112 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1116 DEFUN (no_ipv6_nd_homeagent_preference
,
1117 no_ipv6_nd_homeagent_preference_cmd
,
1118 "no ipv6 nd home-agent-preference [(0-65535)]",
1120 "Interface IPv6 config commands\n"
1121 "Neighbor discovery\n"
1122 "Home Agent preference\n"
1123 "preference value (default is 0, least preferred)\n")
1125 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1126 struct zebra_if
*zif
= ifp
->info
;
1128 zif
->rtadv
.HomeAgentPreference
= 0;
1133 DEFUN (ipv6_nd_homeagent_lifetime
,
1134 ipv6_nd_homeagent_lifetime_cmd
,
1135 "ipv6 nd home-agent-lifetime (0-65520)",
1136 "Interface IPv6 config commands\n"
1137 "Neighbor discovery\n"
1138 "Home Agent lifetime\n"
1139 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1142 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1143 struct zebra_if
*zif
= ifp
->info
;
1144 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1148 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1149 no_ipv6_nd_homeagent_lifetime_cmd
,
1150 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1152 "Interface IPv6 config commands\n"
1153 "Neighbor discovery\n"
1154 "Home Agent lifetime\n"
1155 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1157 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1158 struct zebra_if
*zif
= ifp
->info
;
1160 zif
->rtadv
.HomeAgentLifetime
= -1;
1165 DEFUN (ipv6_nd_managed_config_flag
,
1166 ipv6_nd_managed_config_flag_cmd
,
1167 "ipv6 nd managed-config-flag",
1168 "Interface IPv6 config commands\n"
1169 "Neighbor discovery\n"
1170 "Managed address configuration flag\n")
1172 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1173 struct zebra_if
*zif
= ifp
->info
;
1175 zif
->rtadv
.AdvManagedFlag
= 1;
1180 DEFUN (no_ipv6_nd_managed_config_flag
,
1181 no_ipv6_nd_managed_config_flag_cmd
,
1182 "no ipv6 nd managed-config-flag",
1184 "Interface IPv6 config commands\n"
1185 "Neighbor discovery\n"
1186 "Managed address configuration flag\n")
1188 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1189 struct zebra_if
*zif
= ifp
->info
;
1191 zif
->rtadv
.AdvManagedFlag
= 0;
1196 DEFUN (ipv6_nd_homeagent_config_flag
,
1197 ipv6_nd_homeagent_config_flag_cmd
,
1198 "ipv6 nd home-agent-config-flag",
1199 "Interface IPv6 config commands\n"
1200 "Neighbor discovery\n"
1201 "Home Agent configuration flag\n")
1203 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1204 struct zebra_if
*zif
= ifp
->info
;
1206 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1211 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1212 no_ipv6_nd_homeagent_config_flag_cmd
,
1213 "no ipv6 nd home-agent-config-flag",
1215 "Interface IPv6 config commands\n"
1216 "Neighbor discovery\n"
1217 "Home Agent configuration flag\n")
1219 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1220 struct zebra_if
*zif
= ifp
->info
;
1222 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1227 DEFUN (ipv6_nd_adv_interval_config_option
,
1228 ipv6_nd_adv_interval_config_option_cmd
,
1229 "ipv6 nd adv-interval-option",
1230 "Interface IPv6 config commands\n"
1231 "Neighbor discovery\n"
1232 "Advertisement Interval Option\n")
1234 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1235 struct zebra_if
*zif
= ifp
->info
;
1237 zif
->rtadv
.AdvIntervalOption
= 1;
1242 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1243 no_ipv6_nd_adv_interval_config_option_cmd
,
1244 "no ipv6 nd adv-interval-option",
1246 "Interface IPv6 config commands\n"
1247 "Neighbor discovery\n"
1248 "Advertisement Interval Option\n")
1250 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1251 struct zebra_if
*zif
= ifp
->info
;
1253 zif
->rtadv
.AdvIntervalOption
= 0;
1258 DEFUN (ipv6_nd_other_config_flag
,
1259 ipv6_nd_other_config_flag_cmd
,
1260 "ipv6 nd other-config-flag",
1261 "Interface IPv6 config commands\n"
1262 "Neighbor discovery\n"
1263 "Other statefull configuration flag\n")
1265 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1266 struct zebra_if
*zif
= ifp
->info
;
1268 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1273 DEFUN (no_ipv6_nd_other_config_flag
,
1274 no_ipv6_nd_other_config_flag_cmd
,
1275 "no ipv6 nd other-config-flag",
1277 "Interface IPv6 config commands\n"
1278 "Neighbor discovery\n"
1279 "Other statefull configuration flag\n")
1281 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1282 struct zebra_if
*zif
= ifp
->info
;
1284 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1289 DEFUN (ipv6_nd_prefix
,
1291 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1292 "Interface IPv6 config commands\n"
1293 "Neighbor discovery\n"
1294 "Prefix information\n"
1296 "Valid lifetime in seconds\n"
1297 "Infinite valid lifetime\n"
1298 "Preferred lifetime in seconds\n"
1299 "Infinite preferred lifetime\n"
1300 "Set Router Address flag\n"
1301 "Do not use prefix for onlink determination\n"
1302 "Do not use prefix for autoconfiguration\n"
1303 "Do not use prefix for autoconfiguration\n"
1304 "Do not use prefix for onlink determination\n")
1307 char *prefix
= argv
[3]->arg
;
1308 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1309 || strmatch(argv
[4]->text
, "infinite"));
1310 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1312 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1314 char *lifetime
= NULL
, *preflifetime
= NULL
;
1315 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1317 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1319 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1324 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1326 offlink
= (argc
> idx_routeropts
+ 1
1327 || strmatch(argv
[idx_routeropts
]->text
,
1329 noautoconf
= (argc
> idx_routeropts
+ 1
1330 || strmatch(argv
[idx_routeropts
]->text
,
1336 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1337 struct zebra_if
*zebra_if
= ifp
->info
;
1339 struct rtadv_prefix rp
;
1341 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1343 vty_out(vty
, "Malformed IPv6 prefix\n");
1344 return CMD_WARNING_CONFIG_FAILED
;
1346 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1347 rp
.AdvOnLinkFlag
= !offlink
;
1348 rp
.AdvAutonomousFlag
= !noautoconf
;
1349 rp
.AdvRouterAddressFlag
= routeraddr
;
1350 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1351 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1354 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1356 : strtoll(lifetime
, NULL
, 10);
1357 rp
.AdvPreferredLifetime
=
1358 strmatch(preflifetime
, "infinite")
1360 : strtoll(preflifetime
, NULL
, 10);
1361 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1362 vty_out(vty
, "Invalid preferred lifetime\n");
1363 return CMD_WARNING_CONFIG_FAILED
;
1367 rtadv_prefix_set(zebra_if
, &rp
);
1372 DEFUN (no_ipv6_nd_prefix
,
1373 no_ipv6_nd_prefix_cmd
,
1374 "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]>]",
1376 "Interface IPv6 config commands\n"
1377 "Neighbor discovery\n"
1378 "Prefix information\n"
1380 "Valid lifetime in seconds\n"
1381 "Infinite valid lifetime\n"
1382 "Preferred lifetime in seconds\n"
1383 "Infinite preferred lifetime\n"
1384 "Set Router Address flag\n"
1385 "Do not use prefix for onlink determination\n"
1386 "Do not use prefix for autoconfiguration\n"
1387 "Do not use prefix for autoconfiguration\n"
1388 "Do not use prefix for onlink determination\n")
1390 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1391 struct zebra_if
*zebra_if
= ifp
->info
;
1393 struct rtadv_prefix rp
;
1394 char *prefix
= argv
[4]->arg
;
1396 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1398 vty_out(vty
, "Malformed IPv6 prefix\n");
1399 return CMD_WARNING_CONFIG_FAILED
;
1401 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1403 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1405 vty_out(vty
, "Non-existant IPv6 prefix\n");
1406 return CMD_WARNING_CONFIG_FAILED
;
1412 DEFUN (ipv6_nd_router_preference
,
1413 ipv6_nd_router_preference_cmd
,
1414 "ipv6 nd router-preference <high|medium|low>",
1415 "Interface IPv6 config commands\n"
1416 "Neighbor discovery\n"
1417 "Default router preference\n"
1418 "High default router preference\n"
1419 "Medium default router preference (default)\n"
1420 "Low default router preference\n")
1422 int idx_high_medium_low
= 3;
1423 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1424 struct zebra_if
*zif
= ifp
->info
;
1427 while (0 != rtadv_pref_strs
[i
]) {
1428 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1431 zif
->rtadv
.DefaultPreference
= i
;
1437 return CMD_ERR_NO_MATCH
;
1440 DEFUN (no_ipv6_nd_router_preference
,
1441 no_ipv6_nd_router_preference_cmd
,
1442 "no ipv6 nd router-preference [<high|medium|low>]",
1444 "Interface IPv6 config commands\n"
1445 "Neighbor discovery\n"
1446 "Default router preference\n"
1447 "High default router preference\n"
1448 "Medium default router preference (default)\n"
1449 "Low default router preference\n")
1451 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1452 struct zebra_if
*zif
= ifp
->info
;
1454 zif
->rtadv
.DefaultPreference
=
1455 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1462 "ipv6 nd mtu (1-65535)",
1463 "Interface IPv6 config commands\n"
1464 "Neighbor discovery\n"
1469 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1470 struct zebra_if
*zif
= ifp
->info
;
1471 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1475 DEFUN (no_ipv6_nd_mtu
,
1477 "no ipv6 nd mtu [(1-65535)]",
1479 "Interface IPv6 config commands\n"
1480 "Neighbor discovery\n"
1484 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1485 struct zebra_if
*zif
= ifp
->info
;
1486 zif
->rtadv
.AdvLinkMTU
= 0;
1490 /* Dump interface ND information to vty. */
1491 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1493 struct zebra_if
*zif
;
1494 struct rtadvconf
*rtadv
;
1497 zif
= (struct zebra_if
*)ifp
->info
;
1498 rtadv
= &zif
->rtadv
;
1500 if (rtadv
->AdvSendAdvertisements
) {
1502 " ND advertised reachable time is %d milliseconds\n",
1503 rtadv
->AdvReachableTime
);
1505 " ND advertised retransmit interval is %d milliseconds\n",
1506 rtadv
->AdvRetransTimer
);
1507 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1508 zif
->ra_sent
, zif
->ra_rcvd
);
1509 interval
= rtadv
->MaxRtrAdvInterval
;
1510 if (interval
% 1000)
1512 " ND router advertisements are sent every "
1513 "%d milliseconds\n",
1517 " ND router advertisements are sent every "
1520 if (rtadv
->AdvDefaultLifetime
!= -1)
1522 " ND router advertisements live for %d seconds\n",
1523 rtadv
->AdvDefaultLifetime
);
1526 " ND router advertisements lifetime tracks ra-interval\n");
1528 " ND router advertisement default router preference is "
1530 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1531 if (rtadv
->AdvManagedFlag
)
1533 " Hosts use DHCP to obtain routable addresses.\n");
1536 " Hosts use stateless autoconfig for addresses.\n");
1537 if (rtadv
->AdvHomeAgentFlag
) {
1539 " ND router advertisements with Home Agent flag bit set.\n");
1540 if (rtadv
->HomeAgentLifetime
!= -1)
1542 " Home Agent lifetime is %u seconds\n",
1543 rtadv
->HomeAgentLifetime
);
1546 " Home Agent lifetime tracks ra-lifetime\n");
1547 vty_out(vty
, " Home Agent preference is %u\n",
1548 rtadv
->HomeAgentPreference
);
1550 if (rtadv
->AdvIntervalOption
)
1552 " ND router advertisements with Adv. Interval option.\n");
1558 /* Write configuration about router advertisement. */
1559 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1561 struct zebra_if
*zif
;
1562 struct listnode
*node
;
1563 struct rtadv_prefix
*rprefix
;
1564 char buf
[PREFIX_STRLEN
];
1569 if (!(if_is_loopback(ifp
)
1570 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1571 if (zif
->rtadv
.AdvSendAdvertisements
1572 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1573 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1576 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1577 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
1578 if (interval
% 1000)
1579 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
1581 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1582 vty_out(vty
, " ipv6 nd ra-interval %d\n",
1586 if (zif
->rtadv
.AdvIntervalOption
)
1587 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1589 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1590 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1591 zif
->rtadv
.AdvDefaultLifetime
);
1593 if (zif
->rtadv
.HomeAgentPreference
)
1594 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1595 zif
->rtadv
.HomeAgentPreference
);
1597 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1598 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1599 zif
->rtadv
.HomeAgentLifetime
);
1601 if (zif
->rtadv
.AdvHomeAgentFlag
)
1602 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1604 if (zif
->rtadv
.AdvReachableTime
)
1605 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1606 zif
->rtadv
.AdvReachableTime
);
1608 if (zif
->rtadv
.AdvManagedFlag
)
1609 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1611 if (zif
->rtadv
.AdvOtherConfigFlag
)
1612 vty_out(vty
, " ipv6 nd other-config-flag\n");
1614 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1615 vty_out(vty
, " ipv6 nd router-preference %s\n",
1616 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1618 if (zif
->rtadv
.AdvLinkMTU
)
1619 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1621 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1622 vty_out(vty
, " ipv6 nd prefix %s",
1623 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1624 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1625 || (rprefix
->AdvPreferredLifetime
1626 != RTADV_PREFERRED_LIFETIME
)) {
1627 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1628 vty_out(vty
, " infinite");
1630 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1631 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1632 vty_out(vty
, " infinite");
1635 rprefix
->AdvPreferredLifetime
);
1637 if (!rprefix
->AdvOnLinkFlag
)
1638 vty_out(vty
, " off-link");
1639 if (!rprefix
->AdvAutonomousFlag
)
1640 vty_out(vty
, " no-autoconfig");
1641 if (rprefix
->AdvRouterAddressFlag
)
1642 vty_out(vty
, " router-address");
1649 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1651 struct rtadv
*rtadv
= &zns
->rtadv
;
1655 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1657 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1661 if (rtadv
->ra_timer
) {
1662 thread_cancel(rtadv
->ra_timer
);
1663 rtadv
->ra_timer
= NULL
;
1665 if (rtadv
->ra_read
) {
1666 thread_cancel(rtadv
->ra_read
);
1667 rtadv
->ra_read
= NULL
;
1671 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1674 case RTADV_TIMER_MSEC
:
1675 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1679 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1688 void rtadv_init(struct zebra_ns
*zns
)
1690 zns
->rtadv
.sock
= rtadv_make_socket(zns
->ns_id
);
1693 void rtadv_terminate(struct zebra_ns
*zns
)
1695 rtadv_event(zns
, RTADV_STOP
, 0);
1696 if (zns
->rtadv
.sock
>= 0) {
1697 close(zns
->rtadv
.sock
);
1698 zns
->rtadv
.sock
= -1;
1701 zns
->rtadv
.adv_if_count
= 0;
1702 zns
->rtadv
.adv_msec_if_count
= 0;
1705 void rtadv_cmd_init(void)
1707 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1708 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1710 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1711 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1712 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1713 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1714 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1715 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1716 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1717 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1718 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1719 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1720 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1721 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1722 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1723 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1724 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1725 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1726 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1727 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1728 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1729 install_element(INTERFACE_NODE
,
1730 &ipv6_nd_adv_interval_config_option_cmd
);
1731 install_element(INTERFACE_NODE
,
1732 &no_ipv6_nd_adv_interval_config_option_cmd
);
1733 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1734 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1735 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1736 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1737 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1738 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1741 static int if_join_all_router(int sock
, struct interface
*ifp
)
1745 struct ipv6_mreq mreq
;
1747 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1748 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1749 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1751 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1754 zlog_warn("%s(%u): Failed to join group, socket %u error %s",
1755 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1757 if (IS_ZEBRA_DEBUG_EVENT
)
1759 "%s(%u): Join All-Routers multicast group, socket %u",
1760 ifp
->name
, ifp
->ifindex
, sock
);
1765 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1769 struct ipv6_mreq mreq
;
1771 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1772 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1773 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1775 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1778 zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
1779 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1781 if (IS_ZEBRA_DEBUG_EVENT
)
1783 "%s(%u): Leave All-Routers multicast group, socket %u",
1784 ifp
->name
, ifp
->ifindex
, sock
);
1790 void rtadv_init(struct zebra_ns
*zns
)
1794 void rtadv_terminate(struct zebra_ns
*zns
)
1798 void rtadv_cmd_init(void)
1802 #endif /* HAVE_RTADV */