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
;
48 /* currently undefined in icmp6.h */
51 #if defined(HAVE_RTADV)
54 #include <netinet/icmp6.h>
57 /* If RFC2133 definition is used. */
58 #ifndef IPV6_JOIN_GROUP
59 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
61 #ifndef IPV6_LEAVE_GROUP
62 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
65 #define ALLNODE "ff02::1"
66 #define ALLROUTER "ff02::2"
68 /* Order is intentional. Matches RFC4191. This array is also used for
69 command matching, so only modify with care. */
70 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
80 static void rtadv_event(struct zebra_ns
*, enum rtadv_event
, int);
82 static int if_join_all_router(int, struct interface
*);
83 static int if_leave_all_router(int, struct interface
*);
85 static int rtadv_increment_received(struct zebra_ns
*zns
, ifindex_t
*ifindex
)
88 struct interface
*iface
;
91 iface
= if_lookup_by_index_per_ns(zns
, *ifindex
);
92 if (iface
&& iface
->info
) {
100 static int rtadv_recv_packet(struct zebra_ns
*zns
, int sock
, uint8_t *buf
,
101 int buflen
, struct sockaddr_in6
*from
,
102 ifindex_t
*ifindex
, int *hoplimit
)
107 struct cmsghdr
*cmsgptr
;
112 /* Fill in message and iovec. */
113 memset(&msg
, 0, sizeof(msg
));
114 msg
.msg_name
= (void *)from
;
115 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
118 msg
.msg_control
= (void *)adata
;
119 msg
.msg_controllen
= sizeof adata
;
121 iov
.iov_len
= buflen
;
123 /* If recvmsg fail return minus value. */
124 ret
= recvmsg(sock
, &msg
, 0);
128 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
129 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
130 /* I want interface index which this packet comes from. */
131 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
132 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
133 struct in6_pktinfo
*ptr
;
135 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
136 *ifindex
= ptr
->ipi6_ifindex
;
137 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
140 /* Incoming packet's hop limit. */
141 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
142 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
143 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
148 rtadv_increment_received(zns
, ifindex
);
152 #define RTADV_MSG_SIZE 4096
154 /* Send router advertisement packet. */
155 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
159 struct cmsghdr
*cmsgptr
;
160 struct in6_pktinfo
*pkt
;
161 struct sockaddr_in6 addr
;
162 static void *adata
= NULL
;
163 unsigned char buf
[RTADV_MSG_SIZE
];
164 struct nd_router_advert
*rtadv
;
167 struct zebra_if
*zif
;
168 struct rtadv_prefix
*rprefix
;
169 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
170 0, 0, 0, 0, 0, 0, 0, 1};
171 struct listnode
*node
;
172 uint16_t pkt_RouterLifetime
;
175 * Allocate control message bufffer. This is dynamic because
176 * CMSG_SPACE is not guaranteed not to call a function. Note that
177 * the size will be different on different architectures due to
178 * differing alignment rules.
181 /* XXX Free on shutdown. */
182 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
186 "rtadv_send_packet: can't malloc control data");
191 /* Logging of packet. */
192 if (IS_ZEBRA_DEBUG_PACKET
)
193 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
196 /* Fill in sockaddr_in6. */
197 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
198 addr
.sin6_family
= AF_INET6
;
200 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
201 #endif /* SIN6_LEN */
202 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
203 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
205 /* Fetch interface information. */
208 /* Make router advertisement message. */
209 rtadv
= (struct nd_router_advert
*)buf
;
211 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
212 rtadv
->nd_ra_code
= 0;
213 rtadv
->nd_ra_cksum
= 0;
215 rtadv
->nd_ra_curhoplimit
= 64;
217 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
218 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
220 : zif
->rtadv
.DefaultPreference
;
221 rtadv
->nd_ra_flags_reserved
<<= 3;
223 if (zif
->rtadv
.AdvManagedFlag
)
224 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
225 if (zif
->rtadv
.AdvOtherConfigFlag
)
226 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
227 if (zif
->rtadv
.AdvHomeAgentFlag
)
228 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
230 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_V4_GOAWAY
;
232 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
233 * AdvDefaultLifetime is by default based on the value of
234 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
235 * field of Router Advertisements. Given that this field is expressed
236 * in seconds, a small MaxRtrAdvInterval value can result in a zero
237 * value for this field. To prevent this, routers SHOULD keep
238 * AdvDefaultLifetime in at least one second, even if the use of
239 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
241 zif
->rtadv
.AdvDefaultLifetime
!= -1
242 ? zif
->rtadv
.AdvDefaultLifetime
243 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
244 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
245 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
246 rtadv
->nd_ra_retransmit
= htonl(0);
248 len
= sizeof(struct nd_router_advert
);
250 /* If both the Home Agent Preference and Home Agent Lifetime are set to
251 * their default values specified above, this option SHOULD NOT be
252 * included in the Router Advertisement messages sent by this home
253 * agent. -- RFC6275, 7.4 */
254 if (zif
->rtadv
.AdvHomeAgentFlag
255 && (zif
->rtadv
.HomeAgentPreference
256 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
257 struct nd_opt_homeagent_info
*ndopt_hai
=
258 (struct nd_opt_homeagent_info
*)(buf
+ len
);
259 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
260 ndopt_hai
->nd_opt_hai_len
= 1;
261 ndopt_hai
->nd_opt_hai_reserved
= 0;
262 ndopt_hai
->nd_opt_hai_preference
=
263 htons(zif
->rtadv
.HomeAgentPreference
);
264 /* 16-bit unsigned integer. The lifetime associated with the
266 * agent in units of seconds. The default value is the same as
268 * Router Lifetime, as specified in the main body of the Router
269 * Advertisement. The maximum value corresponds to 18.2 hours.
271 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
272 ndopt_hai
->nd_opt_hai_lifetime
=
273 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
274 ? zif
->rtadv
.HomeAgentLifetime
275 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
280 len
+= sizeof(struct nd_opt_homeagent_info
);
283 if (zif
->rtadv
.AdvIntervalOption
) {
284 struct nd_opt_adv_interval
*ndopt_adv
=
285 (struct nd_opt_adv_interval
*)(buf
+ len
);
286 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
287 ndopt_adv
->nd_opt_ai_len
= 1;
288 ndopt_adv
->nd_opt_ai_reserved
= 0;
289 ndopt_adv
->nd_opt_ai_interval
=
290 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
291 len
+= sizeof(struct nd_opt_adv_interval
);
294 /* Fill in prefix. */
295 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
296 struct nd_opt_prefix_info
*pinfo
;
298 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
300 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
301 pinfo
->nd_opt_pi_len
= 4;
302 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
304 pinfo
->nd_opt_pi_flags_reserved
= 0;
305 if (rprefix
->AdvOnLinkFlag
)
306 pinfo
->nd_opt_pi_flags_reserved
|=
307 ND_OPT_PI_FLAG_ONLINK
;
308 if (rprefix
->AdvAutonomousFlag
)
309 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
310 if (rprefix
->AdvRouterAddressFlag
)
311 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
313 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
314 pinfo
->nd_opt_pi_preferred_time
=
315 htonl(rprefix
->AdvPreferredLifetime
);
316 pinfo
->nd_opt_pi_reserved2
= 0;
318 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
319 &rprefix
->prefix
.prefix
);
323 uint8_t buf
[INET6_ADDRSTRLEN
];
325 zlog_debug("DEBUG %s",
326 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
327 buf
, INET6_ADDRSTRLEN
));
331 len
+= sizeof(struct nd_opt_prefix_info
);
334 /* Hardware address. */
335 if (ifp
->hw_addr_len
!= 0) {
336 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
338 /* Option length should be rounded up to next octet if
339 the link address does not end on an octet boundary. */
340 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
342 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
343 len
+= ifp
->hw_addr_len
;
345 /* Pad option to end on an octet boundary. */
346 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
347 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
351 if (zif
->rtadv
.AdvLinkMTU
) {
352 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
353 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
354 opt
->nd_opt_mtu_len
= 1;
355 opt
->nd_opt_mtu_reserved
= 0;
356 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
357 len
+= sizeof(struct nd_opt_mtu
);
360 msg
.msg_name
= (void *)&addr
;
361 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
364 msg
.msg_control
= (void *)adata
;
365 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
370 cmsgptr
= ZCMSG_FIRSTHDR(&msg
);
371 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
372 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
373 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
375 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
376 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
377 pkt
->ipi6_ifindex
= ifp
->ifindex
;
379 ret
= sendmsg(sock
, &msg
, 0);
381 zlog_err("%s(%u): Tx RA failed, socket %u error %d (%s)",
382 ifp
->name
, ifp
->ifindex
, sock
, errno
,
383 safe_strerror(errno
));
388 static int rtadv_timer(struct thread
*thread
)
390 struct zebra_ns
*zns
= THREAD_ARG(thread
);
392 struct interface
*ifp
;
393 struct zebra_if
*zif
;
396 zns
->rtadv
.ra_timer
= NULL
;
397 if (zns
->rtadv
.adv_msec_if_count
== 0) {
398 period
= 1000; /* 1 s */
399 rtadv_event(zns
, RTADV_TIMER
, 1 /* 1 s */);
401 period
= 10; /* 10 ms */
402 rtadv_event(zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
405 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
406 FOR_ALL_INTERFACES (vrf
, ifp
) {
407 if (if_is_loopback(ifp
)
408 || CHECK_FLAG(ifp
->status
,
409 ZEBRA_INTERFACE_VRF_LOOPBACK
)
410 || !if_is_operative(ifp
))
415 if (zif
->rtadv
.AdvSendAdvertisements
) {
416 if (zif
->rtadv
.inFastRexmit
) {
417 /* We assume we fast rexmit every sec so
420 if (--zif
->rtadv
.NumFastReXmitsRemain
422 zif
->rtadv
.inFastRexmit
= 0;
424 if (IS_ZEBRA_DEBUG_SEND
)
426 "Fast RA Rexmit on interface %s",
429 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
431 zif
->rtadv
.AdvIntervalTimer
-= period
;
432 if (zif
->rtadv
.AdvIntervalTimer
<= 0) {
434 MaxRtrAdvInterval each
435 time isn't what section
436 6.2.4 of RFC4861 tells to do.
438 zif
->rtadv
.AdvIntervalTimer
=
442 zns
->rtadv
.sock
, ifp
);
451 static void rtadv_process_solicit(struct interface
*ifp
)
453 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
454 struct zebra_ns
*zns
= zvrf
->zns
;
457 rtadv_send_packet(zns
->rtadv
.sock
, ifp
);
460 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
461 struct interface
*ifp
,
462 struct sockaddr_in6
*addr
)
464 struct nd_router_advert
*radvert
;
465 char addr_str
[INET6_ADDRSTRLEN
];
466 struct zebra_if
*zif
;
471 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
473 if (len
< sizeof(struct nd_router_advert
)) {
474 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
475 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
478 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
480 "%s(%u): Rx RA with non-linklocal source address from %s",
481 ifp
->name
, ifp
->ifindex
, addr_str
);
485 radvert
= (struct nd_router_advert
*)msg
;
487 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
488 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
490 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
491 ifp
->name
, ifp
->ifindex
, addr_str
);
494 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
495 && !zif
->rtadv
.AdvManagedFlag
) {
497 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
498 ifp
->name
, ifp
->ifindex
, addr_str
);
501 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
502 && !zif
->rtadv
.AdvOtherConfigFlag
) {
504 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
505 ifp
->name
, ifp
->ifindex
, addr_str
);
508 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
509 && (ntohl(radvert
->nd_ra_reachable
)
510 != zif
->rtadv
.AdvReachableTime
)) {
512 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
513 ifp
->name
, ifp
->ifindex
, addr_str
);
516 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
517 && (ntohl(radvert
->nd_ra_retransmit
)
518 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
520 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
521 ifp
->name
, ifp
->ifindex
, addr_str
);
524 /* Create entry for neighbor if not known. */
526 IPV6_ADDR_COPY(&p
.u
.prefix
, &addr
->sin6_addr
);
527 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
529 if (!nbr_connected_check(ifp
, &p
))
530 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
534 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
535 ifindex_t ifindex
, int hoplimit
,
536 struct sockaddr_in6
*from
,
537 struct zebra_ns
*zns
)
539 struct icmp6_hdr
*icmph
;
540 struct interface
*ifp
;
541 struct zebra_if
*zif
;
542 char addr_str
[INET6_ADDRSTRLEN
];
544 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
546 /* Interface search. */
547 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
549 zlog_warn("RA/RS received on unknown IF %u from %s", ifindex
,
554 if (IS_ZEBRA_DEBUG_PACKET
)
555 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
556 ifp
->ifindex
, len
, addr_str
);
558 if (if_is_loopback(ifp
)
559 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
562 /* Check interface configuration. */
564 if (!zif
->rtadv
.AdvSendAdvertisements
)
567 /* ICMP message length check. */
568 if (len
< sizeof(struct icmp6_hdr
)) {
569 zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
570 ifp
->name
, ifp
->ifindex
, len
);
574 icmph
= (struct icmp6_hdr
*)buf
;
576 /* ICMP message type check. */
577 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
578 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
579 zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
580 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
584 /* Hoplimit check. */
585 if (hoplimit
>= 0 && hoplimit
!= 255) {
586 zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
587 ifp
->ifindex
, hoplimit
);
591 /* Check ICMP message type. */
592 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
593 rtadv_process_solicit(ifp
);
594 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
595 rtadv_process_advert(buf
, len
, ifp
, from
);
600 static int rtadv_read(struct thread
*thread
)
604 uint8_t buf
[RTADV_MSG_SIZE
];
605 struct sockaddr_in6 from
;
606 ifindex_t ifindex
= 0;
608 struct zebra_ns
*zns
= THREAD_ARG(thread
);
610 sock
= THREAD_FD(thread
);
611 zns
->rtadv
.ra_read
= NULL
;
613 /* Register myself. */
614 rtadv_event(zns
, RTADV_READ
, sock
);
616 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
620 zlog_warn("RA/RS recv failed, socket %u error %s", sock
,
621 safe_strerror(errno
));
625 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
630 static int rtadv_make_socket(ns_id_t ns_id
)
634 struct icmp6_filter filter
;
636 if (zserv_privs
.change(ZPRIVS_RAISE
))
637 zlog_err("rtadv_make_socket: could not raise privs, %s",
638 safe_strerror(errno
));
640 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
642 if (zserv_privs
.change(ZPRIVS_LOWER
))
643 zlog_err("rtadv_make_socket: could not lower privs, %s",
644 safe_strerror(errno
));
650 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
655 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
660 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
665 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
670 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
676 ICMP6_FILTER_SETBLOCKALL(&filter
);
677 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
678 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
680 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
681 sizeof(struct icmp6_filter
));
683 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
691 static struct rtadv_prefix
*rtadv_prefix_new(void)
693 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
696 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
698 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
701 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
702 struct prefix_ipv6
*p
)
704 struct listnode
*node
;
705 struct rtadv_prefix
*rprefix
;
707 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
708 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
714 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
715 struct prefix_ipv6
*p
)
717 struct rtadv_prefix
*rprefix
;
719 rprefix
= rtadv_prefix_lookup(rplist
, p
);
723 rprefix
= rtadv_prefix_new();
724 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
725 listnode_add(rplist
, rprefix
);
730 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
732 struct rtadv_prefix
*rprefix
;
734 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
736 /* Set parameters. */
737 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
738 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
739 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
740 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
741 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
744 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
746 struct rtadv_prefix
*rprefix
;
748 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
749 if (rprefix
!= NULL
) {
750 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
751 rtadv_prefix_free(rprefix
);
757 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
758 ipv6_nd_suppress_ra_status status
)
760 struct zebra_if
*zif
;
761 struct zebra_vrf
*zvrf
;
762 struct zebra_ns
*zns
;
765 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
768 if (status
== RA_SUPPRESS
) {
769 /* RA is currently enabled */
770 if (zif
->rtadv
.AdvSendAdvertisements
) {
771 zif
->rtadv
.AdvSendAdvertisements
= 0;
772 zif
->rtadv
.AdvIntervalTimer
= 0;
773 zns
->rtadv
.adv_if_count
--;
775 if_leave_all_router(zns
->rtadv
.sock
, ifp
);
777 if (zns
->rtadv
.adv_if_count
== 0)
778 rtadv_event(zns
, RTADV_STOP
, 0);
781 if (!zif
->rtadv
.AdvSendAdvertisements
) {
782 zif
->rtadv
.AdvSendAdvertisements
= 1;
783 zif
->rtadv
.AdvIntervalTimer
= 0;
784 zns
->rtadv
.adv_if_count
++;
786 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
787 /* Enable Fast RA only when RA interval is in
789 zif
->rtadv
.inFastRexmit
= 1;
790 zif
->rtadv
.NumFastReXmitsRemain
=
791 RTADV_NUM_FAST_REXMITS
;
794 if_join_all_router(zns
->rtadv
.sock
, ifp
);
796 if (zns
->rtadv
.adv_if_count
== 1)
797 rtadv_event(zns
, RTADV_START
, zns
->rtadv
.sock
);
803 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
804 * Note that while the client could request RA on an interface on which the
805 * operator has not enabled RA, RA won't be disabled upon client request
806 * if the operator has explicitly enabled RA. The enable request can also
807 * specify a RA interval (in seconds).
809 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
813 struct interface
*ifp
;
814 struct zebra_if
*zif
;
819 /* Get interface index and RA interval. */
820 STREAM_GETL(s
, ifindex
);
821 STREAM_GETL(s
, ra_interval
);
823 if (IS_ZEBRA_DEBUG_EVENT
)
824 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
825 zvrf_id(zvrf
), ifindex
,
826 enable
? "enable" : "disable",
827 zebra_route_string(client
->proto
), ra_interval
);
829 /* Locate interface and check VRF match. */
830 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
832 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
833 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
834 zebra_route_string(client
->proto
));
837 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
838 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
839 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
840 zebra_route_string(client
->proto
), ifp
->vrf_id
);
846 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
847 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
849 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
850 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
851 VTY_RA_INTERVAL_CONFIGURED
))
852 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
854 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
855 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
856 VTY_RA_INTERVAL_CONFIGURED
))
857 zif
->rtadv
.MaxRtrAdvInterval
=
858 RTADV_MAX_RTR_ADV_INTERVAL
;
859 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
860 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
866 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
868 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
870 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
872 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
875 DEFUN (ipv6_nd_suppress_ra
,
876 ipv6_nd_suppress_ra_cmd
,
877 "ipv6 nd suppress-ra",
878 "Interface IPv6 config commands\n"
879 "Neighbor discovery\n"
880 "Suppress Router Advertisement\n")
882 VTY_DECLVAR_CONTEXT(interface
, ifp
);
883 struct zebra_if
*zif
= ifp
->info
;
885 if (if_is_loopback(ifp
)
886 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
888 "Cannot configure IPv6 Router Advertisements on this interface\n");
889 return CMD_WARNING_CONFIG_FAILED
;
892 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
893 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
895 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
899 DEFUN (no_ipv6_nd_suppress_ra
,
900 no_ipv6_nd_suppress_ra_cmd
,
901 "no ipv6 nd suppress-ra",
903 "Interface IPv6 config commands\n"
904 "Neighbor discovery\n"
905 "Suppress Router Advertisement\n")
907 VTY_DECLVAR_CONTEXT(interface
, ifp
);
908 struct zebra_if
*zif
= ifp
->info
;
910 if (if_is_loopback(ifp
)
911 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
913 "Cannot configure IPv6 Router Advertisements on this interface\n");
914 return CMD_WARNING_CONFIG_FAILED
;
917 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
918 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
922 DEFUN (ipv6_nd_ra_interval_msec
,
923 ipv6_nd_ra_interval_msec_cmd
,
924 "ipv6 nd ra-interval msec (70-1800000)",
925 "Interface IPv6 config commands\n"
926 "Neighbor discovery\n"
927 "Router Advertisement interval\n"
928 "Router Advertisement interval in milliseconds\n"
929 "Router Advertisement interval in milliseconds\n")
932 VTY_DECLVAR_CONTEXT(interface
, ifp
);
934 struct zebra_if
*zif
= ifp
->info
;
935 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
936 struct zebra_ns
*zns
;
939 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
940 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
941 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
943 "This ra-interval would conflict with configured ra-lifetime!\n");
944 return CMD_WARNING_CONFIG_FAILED
;
947 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
948 zns
->rtadv
.adv_msec_if_count
--;
951 zns
->rtadv
.adv_msec_if_count
++;
953 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
954 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
955 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
956 zif
->rtadv
.AdvIntervalTimer
= 0;
961 DEFUN (ipv6_nd_ra_interval
,
962 ipv6_nd_ra_interval_cmd
,
963 "ipv6 nd ra-interval (1-1800)",
964 "Interface IPv6 config commands\n"
965 "Neighbor discovery\n"
966 "Router Advertisement interval\n"
967 "Router Advertisement interval in seconds\n")
970 VTY_DECLVAR_CONTEXT(interface
, ifp
);
972 struct zebra_if
*zif
= ifp
->info
;
973 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
974 struct zebra_ns
*zns
;
977 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
978 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
979 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
981 "This ra-interval would conflict with configured ra-lifetime!\n");
982 return CMD_WARNING_CONFIG_FAILED
;
985 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
986 zns
->rtadv
.adv_msec_if_count
--;
988 /* convert to milliseconds */
989 interval
= interval
* 1000;
991 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
992 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
993 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
994 zif
->rtadv
.AdvIntervalTimer
= 0;
999 DEFUN (no_ipv6_nd_ra_interval
,
1000 no_ipv6_nd_ra_interval_cmd
,
1001 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1003 "Interface IPv6 config commands\n"
1004 "Neighbor discovery\n"
1005 "Router Advertisement interval\n"
1006 "Router Advertisement interval in seconds\n"
1007 "Specify millisecond router advertisement interval\n"
1008 "Router Advertisement interval in milliseconds\n")
1010 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1011 struct zebra_if
*zif
= ifp
->info
;
1012 struct zebra_vrf
*zvrf
;
1013 struct zebra_ns
*zns
;
1015 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1018 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1019 zns
->rtadv
.adv_msec_if_count
--;
1021 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1023 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1024 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1026 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1028 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1029 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1034 DEFUN (ipv6_nd_ra_lifetime
,
1035 ipv6_nd_ra_lifetime_cmd
,
1036 "ipv6 nd ra-lifetime (0-9000)",
1037 "Interface IPv6 config commands\n"
1038 "Neighbor discovery\n"
1040 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1043 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1044 struct zebra_if
*zif
= ifp
->info
;
1047 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1049 /* The value to be placed in the Router Lifetime field
1050 * of Router Advertisements sent from the interface,
1051 * in seconds. MUST be either zero or between
1052 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1053 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1055 "This ra-lifetime would conflict with configured ra-interval\n");
1056 return CMD_WARNING_CONFIG_FAILED
;
1059 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1064 DEFUN (no_ipv6_nd_ra_lifetime
,
1065 no_ipv6_nd_ra_lifetime_cmd
,
1066 "no ipv6 nd ra-lifetime [(0-9000)]",
1068 "Interface IPv6 config commands\n"
1069 "Neighbor discovery\n"
1071 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1073 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1074 struct zebra_if
*zif
= ifp
->info
;
1076 zif
->rtadv
.AdvDefaultLifetime
= -1;
1081 DEFUN (ipv6_nd_reachable_time
,
1082 ipv6_nd_reachable_time_cmd
,
1083 "ipv6 nd reachable-time (1-3600000)",
1084 "Interface IPv6 config commands\n"
1085 "Neighbor discovery\n"
1087 "Reachable time in milliseconds\n")
1090 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1091 struct zebra_if
*zif
= ifp
->info
;
1092 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1096 DEFUN (no_ipv6_nd_reachable_time
,
1097 no_ipv6_nd_reachable_time_cmd
,
1098 "no ipv6 nd reachable-time [(1-3600000)]",
1100 "Interface IPv6 config commands\n"
1101 "Neighbor discovery\n"
1103 "Reachable time in milliseconds\n")
1105 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1106 struct zebra_if
*zif
= ifp
->info
;
1108 zif
->rtadv
.AdvReachableTime
= 0;
1113 DEFUN (ipv6_nd_homeagent_preference
,
1114 ipv6_nd_homeagent_preference_cmd
,
1115 "ipv6 nd home-agent-preference (0-65535)",
1116 "Interface IPv6 config commands\n"
1117 "Neighbor discovery\n"
1118 "Home Agent preference\n"
1119 "preference value (default is 0, least preferred)\n")
1122 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1123 struct zebra_if
*zif
= ifp
->info
;
1124 zif
->rtadv
.HomeAgentPreference
=
1125 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1129 DEFUN (no_ipv6_nd_homeagent_preference
,
1130 no_ipv6_nd_homeagent_preference_cmd
,
1131 "no ipv6 nd home-agent-preference [(0-65535)]",
1133 "Interface IPv6 config commands\n"
1134 "Neighbor discovery\n"
1135 "Home Agent preference\n"
1136 "preference value (default is 0, least preferred)\n")
1138 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1139 struct zebra_if
*zif
= ifp
->info
;
1141 zif
->rtadv
.HomeAgentPreference
= 0;
1146 DEFUN (ipv6_nd_homeagent_lifetime
,
1147 ipv6_nd_homeagent_lifetime_cmd
,
1148 "ipv6 nd home-agent-lifetime (0-65520)",
1149 "Interface IPv6 config commands\n"
1150 "Neighbor discovery\n"
1151 "Home Agent lifetime\n"
1152 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1155 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1156 struct zebra_if
*zif
= ifp
->info
;
1157 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1161 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1162 no_ipv6_nd_homeagent_lifetime_cmd
,
1163 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1165 "Interface IPv6 config commands\n"
1166 "Neighbor discovery\n"
1167 "Home Agent lifetime\n"
1168 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1170 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1171 struct zebra_if
*zif
= ifp
->info
;
1173 zif
->rtadv
.HomeAgentLifetime
= -1;
1178 DEFUN (ipv6_nd_managed_config_flag
,
1179 ipv6_nd_managed_config_flag_cmd
,
1180 "ipv6 nd managed-config-flag",
1181 "Interface IPv6 config commands\n"
1182 "Neighbor discovery\n"
1183 "Managed address configuration flag\n")
1185 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1186 struct zebra_if
*zif
= ifp
->info
;
1188 zif
->rtadv
.AdvManagedFlag
= 1;
1193 DEFUN (no_ipv6_nd_managed_config_flag
,
1194 no_ipv6_nd_managed_config_flag_cmd
,
1195 "no ipv6 nd managed-config-flag",
1197 "Interface IPv6 config commands\n"
1198 "Neighbor discovery\n"
1199 "Managed address configuration flag\n")
1201 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1202 struct zebra_if
*zif
= ifp
->info
;
1204 zif
->rtadv
.AdvManagedFlag
= 0;
1209 DEFUN (ipv6_nd_homeagent_config_flag
,
1210 ipv6_nd_homeagent_config_flag_cmd
,
1211 "ipv6 nd home-agent-config-flag",
1212 "Interface IPv6 config commands\n"
1213 "Neighbor discovery\n"
1214 "Home Agent configuration flag\n")
1216 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1217 struct zebra_if
*zif
= ifp
->info
;
1219 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1224 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1225 no_ipv6_nd_homeagent_config_flag_cmd
,
1226 "no ipv6 nd home-agent-config-flag",
1228 "Interface IPv6 config commands\n"
1229 "Neighbor discovery\n"
1230 "Home Agent configuration flag\n")
1232 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1233 struct zebra_if
*zif
= ifp
->info
;
1235 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1240 DEFUN (ipv6_nd_adv_interval_config_option
,
1241 ipv6_nd_adv_interval_config_option_cmd
,
1242 "ipv6 nd adv-interval-option",
1243 "Interface IPv6 config commands\n"
1244 "Neighbor discovery\n"
1245 "Advertisement Interval Option\n")
1247 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1248 struct zebra_if
*zif
= ifp
->info
;
1250 zif
->rtadv
.AdvIntervalOption
= 1;
1255 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1256 no_ipv6_nd_adv_interval_config_option_cmd
,
1257 "no ipv6 nd adv-interval-option",
1259 "Interface IPv6 config commands\n"
1260 "Neighbor discovery\n"
1261 "Advertisement Interval Option\n")
1263 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1264 struct zebra_if
*zif
= ifp
->info
;
1266 zif
->rtadv
.AdvIntervalOption
= 0;
1271 DEFUN (ipv6_nd_other_config_flag
,
1272 ipv6_nd_other_config_flag_cmd
,
1273 "ipv6 nd other-config-flag",
1274 "Interface IPv6 config commands\n"
1275 "Neighbor discovery\n"
1276 "Other statefull configuration flag\n")
1278 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1279 struct zebra_if
*zif
= ifp
->info
;
1281 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1286 DEFUN (no_ipv6_nd_other_config_flag
,
1287 no_ipv6_nd_other_config_flag_cmd
,
1288 "no ipv6 nd other-config-flag",
1290 "Interface IPv6 config commands\n"
1291 "Neighbor discovery\n"
1292 "Other statefull configuration flag\n")
1294 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1295 struct zebra_if
*zif
= ifp
->info
;
1297 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1302 DEFUN (ipv6_nd_prefix
,
1304 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1305 "Interface IPv6 config commands\n"
1306 "Neighbor discovery\n"
1307 "Prefix information\n"
1309 "Valid lifetime in seconds\n"
1310 "Infinite valid lifetime\n"
1311 "Preferred lifetime in seconds\n"
1312 "Infinite preferred lifetime\n"
1313 "Set Router Address flag\n"
1314 "Do not use prefix for onlink determination\n"
1315 "Do not use prefix for autoconfiguration\n"
1316 "Do not use prefix for autoconfiguration\n"
1317 "Do not use prefix for onlink determination\n")
1320 char *prefix
= argv
[3]->arg
;
1321 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1322 || strmatch(argv
[4]->text
, "infinite"));
1323 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1325 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1327 char *lifetime
= NULL
, *preflifetime
= NULL
;
1328 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1330 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1332 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1337 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1339 offlink
= (argc
> idx_routeropts
+ 1
1340 || strmatch(argv
[idx_routeropts
]->text
,
1342 noautoconf
= (argc
> idx_routeropts
+ 1
1343 || strmatch(argv
[idx_routeropts
]->text
,
1349 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1350 struct zebra_if
*zebra_if
= ifp
->info
;
1352 struct rtadv_prefix rp
;
1354 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1356 vty_out(vty
, "Malformed IPv6 prefix\n");
1357 return CMD_WARNING_CONFIG_FAILED
;
1359 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1360 rp
.AdvOnLinkFlag
= !offlink
;
1361 rp
.AdvAutonomousFlag
= !noautoconf
;
1362 rp
.AdvRouterAddressFlag
= routeraddr
;
1363 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1364 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1367 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1369 : strtoll(lifetime
, NULL
, 10);
1370 rp
.AdvPreferredLifetime
=
1371 strmatch(preflifetime
, "infinite")
1373 : strtoll(preflifetime
, NULL
, 10);
1374 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1375 vty_out(vty
, "Invalid preferred lifetime\n");
1376 return CMD_WARNING_CONFIG_FAILED
;
1380 rtadv_prefix_set(zebra_if
, &rp
);
1385 DEFUN (no_ipv6_nd_prefix
,
1386 no_ipv6_nd_prefix_cmd
,
1387 "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]>]",
1389 "Interface IPv6 config commands\n"
1390 "Neighbor discovery\n"
1391 "Prefix information\n"
1393 "Valid lifetime in seconds\n"
1394 "Infinite valid lifetime\n"
1395 "Preferred lifetime in seconds\n"
1396 "Infinite preferred lifetime\n"
1397 "Set Router Address flag\n"
1398 "Do not use prefix for onlink determination\n"
1399 "Do not use prefix for autoconfiguration\n"
1400 "Do not use prefix for autoconfiguration\n"
1401 "Do not use prefix for onlink determination\n")
1403 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1404 struct zebra_if
*zebra_if
= ifp
->info
;
1406 struct rtadv_prefix rp
;
1407 char *prefix
= argv
[4]->arg
;
1409 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1411 vty_out(vty
, "Malformed IPv6 prefix\n");
1412 return CMD_WARNING_CONFIG_FAILED
;
1414 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1416 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1418 vty_out(vty
, "Non-existant IPv6 prefix\n");
1419 return CMD_WARNING_CONFIG_FAILED
;
1425 DEFUN (ipv6_nd_router_preference
,
1426 ipv6_nd_router_preference_cmd
,
1427 "ipv6 nd router-preference <high|medium|low>",
1428 "Interface IPv6 config commands\n"
1429 "Neighbor discovery\n"
1430 "Default router preference\n"
1431 "High default router preference\n"
1432 "Medium default router preference (default)\n"
1433 "Low default router preference\n")
1435 int idx_high_medium_low
= 3;
1436 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1437 struct zebra_if
*zif
= ifp
->info
;
1440 while (0 != rtadv_pref_strs
[i
]) {
1441 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1444 zif
->rtadv
.DefaultPreference
= i
;
1450 return CMD_ERR_NO_MATCH
;
1453 DEFUN (no_ipv6_nd_router_preference
,
1454 no_ipv6_nd_router_preference_cmd
,
1455 "no ipv6 nd router-preference [<high|medium|low>]",
1457 "Interface IPv6 config commands\n"
1458 "Neighbor discovery\n"
1459 "Default router preference\n"
1460 "High default router preference\n"
1461 "Medium default router preference (default)\n"
1462 "Low default router preference\n")
1464 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1465 struct zebra_if
*zif
= ifp
->info
;
1467 zif
->rtadv
.DefaultPreference
=
1468 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1475 "ipv6 nd mtu (1-65535)",
1476 "Interface IPv6 config commands\n"
1477 "Neighbor discovery\n"
1482 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1483 struct zebra_if
*zif
= ifp
->info
;
1484 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1488 DEFUN (no_ipv6_nd_mtu
,
1490 "no ipv6 nd mtu [(1-65535)]",
1492 "Interface IPv6 config commands\n"
1493 "Neighbor discovery\n"
1497 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1498 struct zebra_if
*zif
= ifp
->info
;
1499 zif
->rtadv
.AdvLinkMTU
= 0;
1503 DEFUN (ipv6_nd_v4_goaway
,
1504 ipv6_nd_v4_goaway_cmd
,
1505 "[no] ipv6 nd v4 goaway",
1507 "Interface IPv6 config commands\n"
1508 "Neighbor discovery\n"
1510 "Set V4 GoAway Flag\n")
1512 AdvGoAwayFlag
= !strmatch(argv
[0]->text
, "no");
1516 /* Dump interface ND information to vty. */
1517 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1519 struct zebra_if
*zif
;
1520 struct rtadvconf
*rtadv
;
1523 zif
= (struct zebra_if
*)ifp
->info
;
1524 rtadv
= &zif
->rtadv
;
1526 if (rtadv
->AdvSendAdvertisements
) {
1528 " ND advertised reachable time is %d milliseconds\n",
1529 rtadv
->AdvReachableTime
);
1531 " ND advertised retransmit interval is %d milliseconds\n",
1532 rtadv
->AdvRetransTimer
);
1533 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1534 zif
->ra_sent
, zif
->ra_rcvd
);
1535 interval
= rtadv
->MaxRtrAdvInterval
;
1536 if (interval
% 1000)
1538 " ND router advertisements are sent every "
1539 "%d milliseconds\n",
1543 " ND router advertisements are sent every "
1546 if (rtadv
->AdvDefaultLifetime
!= -1)
1548 " ND router advertisements live for %d seconds\n",
1549 rtadv
->AdvDefaultLifetime
);
1552 " ND router advertisements lifetime tracks ra-interval\n");
1554 " ND router advertisement default router preference is "
1556 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1557 if (rtadv
->AdvManagedFlag
)
1559 " Hosts use DHCP to obtain routable addresses.\n");
1562 " Hosts use stateless autoconfig for addresses.\n");
1563 if (rtadv
->AdvHomeAgentFlag
) {
1565 " ND router advertisements with Home Agent flag bit set.\n");
1566 if (rtadv
->HomeAgentLifetime
!= -1)
1568 " Home Agent lifetime is %u seconds\n",
1569 rtadv
->HomeAgentLifetime
);
1572 " Home Agent lifetime tracks ra-lifetime\n");
1573 vty_out(vty
, " Home Agent preference is %u\n",
1574 rtadv
->HomeAgentPreference
);
1576 if (rtadv
->AdvIntervalOption
)
1578 " ND router advertisements with Adv. Interval option.\n");
1584 /* Write configuration about router advertisement. */
1585 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1587 struct zebra_if
*zif
;
1588 struct listnode
*node
;
1589 struct rtadv_prefix
*rprefix
;
1590 char buf
[PREFIX_STRLEN
];
1595 if (!(if_is_loopback(ifp
)
1596 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1597 if (zif
->rtadv
.AdvSendAdvertisements
1598 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1599 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1602 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1603 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
1604 if (interval
% 1000)
1605 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
1607 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1608 vty_out(vty
, " ipv6 nd ra-interval %d\n",
1612 if (zif
->rtadv
.AdvIntervalOption
)
1613 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1615 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1616 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1617 zif
->rtadv
.AdvDefaultLifetime
);
1619 if (zif
->rtadv
.HomeAgentPreference
)
1620 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1621 zif
->rtadv
.HomeAgentPreference
);
1623 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1624 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1625 zif
->rtadv
.HomeAgentLifetime
);
1627 if (zif
->rtadv
.AdvHomeAgentFlag
)
1628 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1630 if (zif
->rtadv
.AdvReachableTime
)
1631 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1632 zif
->rtadv
.AdvReachableTime
);
1634 if (zif
->rtadv
.AdvManagedFlag
)
1635 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1637 if (zif
->rtadv
.AdvOtherConfigFlag
)
1638 vty_out(vty
, " ipv6 nd other-config-flag\n");
1640 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1641 vty_out(vty
, " ipv6 nd router-preference %s\n",
1642 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1644 if (zif
->rtadv
.AdvLinkMTU
)
1645 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1648 vty_out(vty
, " ipv6 nd v4 goaway\n");
1650 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1651 vty_out(vty
, " ipv6 nd prefix %s",
1652 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1653 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1654 || (rprefix
->AdvPreferredLifetime
1655 != RTADV_PREFERRED_LIFETIME
)) {
1656 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1657 vty_out(vty
, " infinite");
1659 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1660 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1661 vty_out(vty
, " infinite");
1664 rprefix
->AdvPreferredLifetime
);
1666 if (!rprefix
->AdvOnLinkFlag
)
1667 vty_out(vty
, " off-link");
1668 if (!rprefix
->AdvAutonomousFlag
)
1669 vty_out(vty
, " no-autoconfig");
1670 if (rprefix
->AdvRouterAddressFlag
)
1671 vty_out(vty
, " router-address");
1678 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1680 struct rtadv
*rtadv
= &zns
->rtadv
;
1684 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1686 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1690 if (rtadv
->ra_timer
) {
1691 thread_cancel(rtadv
->ra_timer
);
1692 rtadv
->ra_timer
= NULL
;
1694 if (rtadv
->ra_read
) {
1695 thread_cancel(rtadv
->ra_read
);
1696 rtadv
->ra_read
= NULL
;
1700 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1703 case RTADV_TIMER_MSEC
:
1704 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1708 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1717 void rtadv_init(struct zebra_ns
*zns
)
1719 zns
->rtadv
.sock
= rtadv_make_socket(zns
->ns_id
);
1722 void rtadv_terminate(struct zebra_ns
*zns
)
1724 rtadv_event(zns
, RTADV_STOP
, 0);
1725 if (zns
->rtadv
.sock
>= 0) {
1726 close(zns
->rtadv
.sock
);
1727 zns
->rtadv
.sock
= -1;
1730 zns
->rtadv
.adv_if_count
= 0;
1731 zns
->rtadv
.adv_msec_if_count
= 0;
1734 void rtadv_cmd_init(void)
1736 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1737 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1739 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1740 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1741 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1742 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1743 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1744 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1745 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1746 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1747 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1748 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1749 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1750 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1751 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1752 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1753 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1754 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1755 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1756 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1757 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1758 install_element(INTERFACE_NODE
,
1759 &ipv6_nd_adv_interval_config_option_cmd
);
1760 install_element(INTERFACE_NODE
,
1761 &no_ipv6_nd_adv_interval_config_option_cmd
);
1762 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1763 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1764 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1765 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1766 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1767 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1768 install_element(INTERFACE_NODE
, &ipv6_nd_v4_goaway_cmd
);
1771 static int if_join_all_router(int sock
, struct interface
*ifp
)
1775 struct ipv6_mreq mreq
;
1777 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1778 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1779 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1781 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1784 zlog_warn("%s(%u): Failed to join group, socket %u error %s",
1785 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1787 if (IS_ZEBRA_DEBUG_EVENT
)
1789 "%s(%u): Join All-Routers multicast group, socket %u",
1790 ifp
->name
, ifp
->ifindex
, sock
);
1795 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1799 struct ipv6_mreq mreq
;
1801 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1802 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1803 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1805 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1808 zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
1809 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1811 if (IS_ZEBRA_DEBUG_EVENT
)
1813 "%s(%u): Leave All-Routers multicast group, socket %u",
1814 ifp
->name
, ifp
->ifindex
, sock
);
1820 void rtadv_init(struct zebra_ns
*zns
)
1824 void rtadv_terminate(struct zebra_ns
*zns
)
1828 void rtadv_cmd_init(void)
1832 #endif /* HAVE_RTADV */