1 /* Router advertisement
2 * Copyright (C) 2016 Cumulus Networks
3 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
4 * Copyright (C) 1999 Kunihiro Ishiguro
6 * This file is part of GNU Zebra.
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "zebra_memory.h"
38 #include "lib_errors.h"
40 #include "zebra/interface.h"
41 #include "zebra/rtadv.h"
42 #include "zebra/debug.h"
43 #include "zebra/rib.h"
44 #include "zebra/zapi_msg.h"
45 #include "zebra/zebra_ns.h"
46 #include "zebra/zebra_vrf.h"
47 #include "zebra/zebra_errors.h"
48 #include "zebra/zebra_router.h"
50 extern struct zebra_privs_t zserv_privs
;
52 #if defined(HAVE_RTADV)
55 #include <netinet/icmp6.h>
58 /* If RFC2133 definition is used. */
59 #ifndef IPV6_JOIN_GROUP
60 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
62 #ifndef IPV6_LEAVE_GROUP
63 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
66 #define ALLNODE "ff02::1"
67 #define ALLROUTER "ff02::2"
69 /* Order is intentional. Matches RFC4191. This array is also used for
70 command matching, so only modify with care. */
71 const char *rtadv_pref_strs
[] = {"medium", "high", "INVALID", "low", 0};
81 static void rtadv_event(struct zebra_ns
*, enum rtadv_event
, int);
83 static int if_join_all_router(int, struct interface
*);
84 static int if_leave_all_router(int, struct interface
*);
86 static int rtadv_increment_received(struct zebra_ns
*zns
, ifindex_t
*ifindex
)
89 struct interface
*iface
;
92 iface
= if_lookup_by_index_per_ns(zns
, *ifindex
);
93 if (iface
&& iface
->info
) {
101 static int rtadv_recv_packet(struct zebra_ns
*zns
, int sock
, uint8_t *buf
,
102 int buflen
, struct sockaddr_in6
*from
,
103 ifindex_t
*ifindex
, int *hoplimit
)
108 struct cmsghdr
*cmsgptr
;
113 /* Fill in message and iovec. */
114 memset(&msg
, 0, sizeof(msg
));
115 msg
.msg_name
= (void *)from
;
116 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
119 msg
.msg_control
= (void *)adata
;
120 msg
.msg_controllen
= sizeof adata
;
122 iov
.iov_len
= buflen
;
124 /* If recvmsg fail return minus value. */
125 ret
= recvmsg(sock
, &msg
, 0);
129 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
130 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
131 /* I want interface index which this packet comes from. */
132 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
133 && cmsgptr
->cmsg_type
== IPV6_PKTINFO
) {
134 struct in6_pktinfo
*ptr
;
136 ptr
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
137 *ifindex
= ptr
->ipi6_ifindex
;
138 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
141 /* Incoming packet's hop limit. */
142 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
143 && cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
) {
144 int *hoptr
= (int *)CMSG_DATA(cmsgptr
);
149 rtadv_increment_received(zns
, ifindex
);
153 #define RTADV_MSG_SIZE 4096
155 /* Send router advertisement packet. */
156 static void rtadv_send_packet(int sock
, struct interface
*ifp
)
160 struct cmsghdr
*cmsgptr
;
161 struct in6_pktinfo
*pkt
;
162 struct sockaddr_in6 addr
;
163 static void *adata
= NULL
;
164 unsigned char buf
[RTADV_MSG_SIZE
];
165 struct nd_router_advert
*rtadv
;
168 struct zebra_if
*zif
;
169 struct rtadv_prefix
*rprefix
;
170 uint8_t all_nodes_addr
[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0, 1};
172 struct listnode
*node
;
173 uint16_t pkt_RouterLifetime
;
176 * Allocate control message bufffer. This is dynamic because
177 * CMSG_SPACE is not guaranteed not to call a function. Note that
178 * the size will be different on different architectures due to
179 * differing alignment rules.
182 /* XXX Free on shutdown. */
183 adata
= calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo
)));
187 "rtadv_send_packet: can't malloc control data");
192 /* Logging of packet. */
193 if (IS_ZEBRA_DEBUG_PACKET
)
194 zlog_debug("%s(%u): Tx RA, socket %u", ifp
->name
, ifp
->ifindex
,
197 /* Fill in sockaddr_in6. */
198 memset(&addr
, 0, sizeof(struct sockaddr_in6
));
199 addr
.sin6_family
= AF_INET6
;
201 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
202 #endif /* SIN6_LEN */
203 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
204 IPV6_ADDR_COPY(&addr
.sin6_addr
, all_nodes_addr
);
206 /* Fetch interface information. */
209 /* Make router advertisement message. */
210 rtadv
= (struct nd_router_advert
*)buf
;
212 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
213 rtadv
->nd_ra_code
= 0;
214 rtadv
->nd_ra_cksum
= 0;
216 rtadv
->nd_ra_curhoplimit
= 64;
218 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
219 rtadv
->nd_ra_flags_reserved
= zif
->rtadv
.AdvDefaultLifetime
== 0
221 : zif
->rtadv
.DefaultPreference
;
222 rtadv
->nd_ra_flags_reserved
<<= 3;
224 if (zif
->rtadv
.AdvManagedFlag
)
225 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
226 if (zif
->rtadv
.AdvOtherConfigFlag
)
227 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
228 if (zif
->rtadv
.AdvHomeAgentFlag
)
229 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
230 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
231 * AdvDefaultLifetime is by default based on the value of
232 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
233 * field of Router Advertisements. Given that this field is expressed
234 * in seconds, a small MaxRtrAdvInterval value can result in a zero
235 * value for this field. To prevent this, routers SHOULD keep
236 * AdvDefaultLifetime in at least one second, even if the use of
237 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
239 zif
->rtadv
.AdvDefaultLifetime
!= -1
240 ? zif
->rtadv
.AdvDefaultLifetime
241 : MAX(1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
242 rtadv
->nd_ra_router_lifetime
= htons(pkt_RouterLifetime
);
243 rtadv
->nd_ra_reachable
= htonl(zif
->rtadv
.AdvReachableTime
);
244 rtadv
->nd_ra_retransmit
= htonl(0);
246 len
= sizeof(struct nd_router_advert
);
248 /* If both the Home Agent Preference and Home Agent Lifetime are set to
249 * their default values specified above, this option SHOULD NOT be
250 * included in the Router Advertisement messages sent by this home
251 * agent. -- RFC6275, 7.4 */
252 if (zif
->rtadv
.AdvHomeAgentFlag
253 && (zif
->rtadv
.HomeAgentPreference
254 || zif
->rtadv
.HomeAgentLifetime
!= -1)) {
255 struct nd_opt_homeagent_info
*ndopt_hai
=
256 (struct nd_opt_homeagent_info
*)(buf
+ len
);
257 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
258 ndopt_hai
->nd_opt_hai_len
= 1;
259 ndopt_hai
->nd_opt_hai_reserved
= 0;
260 ndopt_hai
->nd_opt_hai_preference
=
261 htons(zif
->rtadv
.HomeAgentPreference
);
262 /* 16-bit unsigned integer. The lifetime associated with the
264 * agent in units of seconds. The default value is the same as
266 * Router Lifetime, as specified in the main body of the Router
267 * Advertisement. The maximum value corresponds to 18.2 hours.
269 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
270 ndopt_hai
->nd_opt_hai_lifetime
=
271 htons(zif
->rtadv
.HomeAgentLifetime
!= -1
272 ? zif
->rtadv
.HomeAgentLifetime
273 : MAX(1, pkt_RouterLifetime
) /* 0 is OK
278 len
+= sizeof(struct nd_opt_homeagent_info
);
281 if (zif
->rtadv
.AdvIntervalOption
) {
282 struct nd_opt_adv_interval
*ndopt_adv
=
283 (struct nd_opt_adv_interval
*)(buf
+ len
);
284 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
285 ndopt_adv
->nd_opt_ai_len
= 1;
286 ndopt_adv
->nd_opt_ai_reserved
= 0;
287 ndopt_adv
->nd_opt_ai_interval
=
288 htonl(zif
->rtadv
.MaxRtrAdvInterval
);
289 len
+= sizeof(struct nd_opt_adv_interval
);
292 /* Fill in prefix. */
293 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
294 struct nd_opt_prefix_info
*pinfo
;
296 pinfo
= (struct nd_opt_prefix_info
*)(buf
+ len
);
298 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
299 pinfo
->nd_opt_pi_len
= 4;
300 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
302 pinfo
->nd_opt_pi_flags_reserved
= 0;
303 if (rprefix
->AdvOnLinkFlag
)
304 pinfo
->nd_opt_pi_flags_reserved
|=
305 ND_OPT_PI_FLAG_ONLINK
;
306 if (rprefix
->AdvAutonomousFlag
)
307 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
308 if (rprefix
->AdvRouterAddressFlag
)
309 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
311 pinfo
->nd_opt_pi_valid_time
= htonl(rprefix
->AdvValidLifetime
);
312 pinfo
->nd_opt_pi_preferred_time
=
313 htonl(rprefix
->AdvPreferredLifetime
);
314 pinfo
->nd_opt_pi_reserved2
= 0;
316 IPV6_ADDR_COPY(&pinfo
->nd_opt_pi_prefix
,
317 &rprefix
->prefix
.prefix
);
321 uint8_t buf
[INET6_ADDRSTRLEN
];
323 zlog_debug("DEBUG %s",
324 inet_ntop(AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
325 buf
, INET6_ADDRSTRLEN
));
329 len
+= sizeof(struct nd_opt_prefix_info
);
332 /* Hardware address. */
333 if (ifp
->hw_addr_len
!= 0) {
334 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
336 /* Option length should be rounded up to next octet if
337 the link address does not end on an octet boundary. */
338 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
340 memcpy(buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
341 len
+= ifp
->hw_addr_len
;
343 /* Pad option to end on an octet boundary. */
344 memset(buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
345 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
349 if (zif
->rtadv
.AdvLinkMTU
) {
350 struct nd_opt_mtu
*opt
= (struct nd_opt_mtu
*)(buf
+ len
);
351 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
352 opt
->nd_opt_mtu_len
= 1;
353 opt
->nd_opt_mtu_reserved
= 0;
354 opt
->nd_opt_mtu_mtu
= htonl(zif
->rtadv
.AdvLinkMTU
);
355 len
+= sizeof(struct nd_opt_mtu
);
358 msg
.msg_name
= (void *)&addr
;
359 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
362 msg
.msg_control
= (void *)adata
;
363 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
368 cmsgptr
= CMSG_FIRSTHDR(&msg
);
369 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
370 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
371 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
373 pkt
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
374 memset(&pkt
->ipi6_addr
, 0, sizeof(struct in6_addr
));
375 pkt
->ipi6_ifindex
= ifp
->ifindex
;
377 ret
= sendmsg(sock
, &msg
, 0);
379 flog_err_sys(EC_LIB_SOCKET
,
380 "%s(%u): Tx RA failed, socket %u error %d (%s)",
381 ifp
->name
, ifp
->ifindex
, sock
, errno
,
382 safe_strerror(errno
));
387 static int rtadv_timer(struct thread
*thread
)
389 struct zebra_ns
*zns
= THREAD_ARG(thread
);
391 struct interface
*ifp
;
392 struct zebra_if
*zif
;
395 zrouter
.rtadv
.ra_timer
= NULL
;
396 if (zrouter
.rtadv
.adv_msec_if_count
== 0) {
397 period
= 1000; /* 1 s */
398 rtadv_event(zns
, RTADV_TIMER
, 1 /* 1 s */);
400 period
= 10; /* 10 ms */
401 rtadv_event(zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
404 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
405 FOR_ALL_INTERFACES (vrf
, ifp
) {
406 if (if_is_loopback(ifp
)
407 || CHECK_FLAG(ifp
->status
,
408 ZEBRA_INTERFACE_VRF_LOOPBACK
)
409 || !if_is_operative(ifp
))
414 if (zif
->rtadv
.AdvSendAdvertisements
) {
415 if (zif
->rtadv
.inFastRexmit
) {
416 /* We assume we fast rexmit every sec so
419 if (--zif
->rtadv
.NumFastReXmitsRemain
421 zif
->rtadv
.inFastRexmit
= 0;
423 if (IS_ZEBRA_DEBUG_SEND
)
425 "Fast RA Rexmit on interface %s",
428 rtadv_send_packet(zrouter
.rtadv
.sock
,
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
=
452 static void rtadv_process_solicit(struct interface
*ifp
)
454 struct zebra_vrf
*zvrf
= vrf_info_lookup(ifp
->vrf_id
);
455 struct zebra_ns
*zns
= zvrf
->zns
;
458 rtadv_send_packet(zrouter
.rtadv
.sock
, ifp
);
462 * This function processes optional attributes off of
463 * end of a RA packet received. At this point in
464 * time we only care about this in one situation
465 * which is when a interface does not have a LL
466 * v6 address. We still need to be able to install
467 * the mac address for v4 to v6 resolution
469 static void rtadv_process_optional(uint8_t *optional
, unsigned int len
,
470 struct interface
*ifp
,
471 struct sockaddr_in6
*addr
)
476 struct nd_opt_hdr
*opt_hdr
= (struct nd_opt_hdr
*)optional
;
478 switch(opt_hdr
->nd_opt_type
) {
479 case ND_OPT_SOURCE_LINKADDR
:
480 mac
= (char *)(optional
+2);
481 if_nbr_mac_to_ipv4ll_neigh_update(ifp
, mac
,
482 &addr
->sin6_addr
, 1);
488 len
-= 8 * opt_hdr
->nd_opt_len
;
489 optional
+= 8 * opt_hdr
->nd_opt_len
;
493 static void rtadv_process_advert(uint8_t *msg
, unsigned int len
,
494 struct interface
*ifp
,
495 struct sockaddr_in6
*addr
)
497 struct nd_router_advert
*radvert
;
498 char addr_str
[INET6_ADDRSTRLEN
];
499 struct zebra_if
*zif
;
504 inet_ntop(AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
506 if (len
< sizeof(struct nd_router_advert
)) {
507 if (IS_ZEBRA_DEBUG_PACKET
)
508 zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
509 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
513 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
514 rtadv_process_optional(msg
+ sizeof(struct nd_router_advert
),
515 len
- sizeof(struct nd_router_advert
),
517 if (IS_ZEBRA_DEBUG_PACKET
)
518 zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s",
519 ifp
->name
, ifp
->ifindex
, addr_str
);
523 radvert
= (struct nd_router_advert
*)msg
;
525 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
)
526 && (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
)) {
528 EC_ZEBRA_RA_PARAM_MISMATCH
,
529 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
530 ifp
->name
, ifp
->ifindex
, addr_str
);
533 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
534 && !zif
->rtadv
.AdvManagedFlag
) {
536 EC_ZEBRA_RA_PARAM_MISMATCH
,
537 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
538 ifp
->name
, ifp
->ifindex
, addr_str
);
541 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
542 && !zif
->rtadv
.AdvOtherConfigFlag
) {
544 EC_ZEBRA_RA_PARAM_MISMATCH
,
545 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
546 ifp
->name
, ifp
->ifindex
, addr_str
);
549 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
)
550 && (ntohl(radvert
->nd_ra_reachable
)
551 != zif
->rtadv
.AdvReachableTime
)) {
553 EC_ZEBRA_RA_PARAM_MISMATCH
,
554 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
555 ifp
->name
, ifp
->ifindex
, addr_str
);
558 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
)
559 && (ntohl(radvert
->nd_ra_retransmit
)
560 != (unsigned int)zif
->rtadv
.AdvRetransTimer
)) {
562 EC_ZEBRA_RA_PARAM_MISMATCH
,
563 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
564 ifp
->name
, ifp
->ifindex
, addr_str
);
567 /* Create entry for neighbor if not known. */
569 IPV6_ADDR_COPY(&p
.u
.prefix6
, &addr
->sin6_addr
);
570 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
572 if (!nbr_connected_check(ifp
, &p
))
573 nbr_connected_add_ipv6(ifp
, &addr
->sin6_addr
);
577 static void rtadv_process_packet(uint8_t *buf
, unsigned int len
,
578 ifindex_t ifindex
, int hoplimit
,
579 struct sockaddr_in6
*from
,
580 struct zebra_ns
*zns
)
582 struct icmp6_hdr
*icmph
;
583 struct interface
*ifp
;
584 struct zebra_if
*zif
;
585 char addr_str
[INET6_ADDRSTRLEN
];
587 inet_ntop(AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
589 /* Interface search. */
590 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
592 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
593 "RA/RS received on unknown IF %u from %s", ifindex
,
598 if (IS_ZEBRA_DEBUG_PACKET
)
599 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp
->name
,
600 ifp
->ifindex
, len
, addr_str
);
602 if (if_is_loopback(ifp
)
603 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
606 /* Check interface configuration. */
608 if (!zif
->rtadv
.AdvSendAdvertisements
)
611 /* ICMP message length check. */
612 if (len
< sizeof(struct icmp6_hdr
)) {
613 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
614 ifp
->name
, ifp
->ifindex
, len
);
618 icmph
= (struct icmp6_hdr
*)buf
;
620 /* ICMP message type check. */
621 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
622 && icmph
->icmp6_type
!= ND_ROUTER_ADVERT
) {
623 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
624 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
628 /* Hoplimit check. */
629 if (hoplimit
>= 0 && hoplimit
!= 255) {
630 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp
->name
,
631 ifp
->ifindex
, hoplimit
);
635 /* Check ICMP message type. */
636 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
637 rtadv_process_solicit(ifp
);
638 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
639 rtadv_process_advert(buf
, len
, ifp
, from
);
644 static int rtadv_read(struct thread
*thread
)
648 uint8_t buf
[RTADV_MSG_SIZE
];
649 struct sockaddr_in6 from
;
650 ifindex_t ifindex
= 0;
652 struct zebra_ns
*zns
= THREAD_ARG(thread
);
654 sock
= THREAD_FD(thread
);
655 zrouter
.rtadv
.ra_read
= NULL
;
657 /* Register myself. */
658 rtadv_event(zns
, RTADV_READ
, sock
);
660 len
= rtadv_recv_packet(zns
, sock
, buf
, sizeof(buf
), &from
, &ifindex
,
664 flog_err_sys(EC_LIB_SOCKET
,
665 "RA/RS recv failed, socket %u error %s", sock
,
666 safe_strerror(errno
));
670 rtadv_process_packet(buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
675 static int rtadv_make_socket(ns_id_t ns_id
)
679 struct icmp6_filter filter
;
681 frr_elevate_privs(&zserv_privs
) {
683 sock
= ns_socket(AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
, ns_id
);
691 ret
= setsockopt_ipv6_pktinfo(sock
, 1);
696 ret
= setsockopt_ipv6_multicast_loop(sock
, 0);
701 ret
= setsockopt_ipv6_unicast_hops(sock
, 255);
706 ret
= setsockopt_ipv6_multicast_hops(sock
, 255);
711 ret
= setsockopt_ipv6_hoplimit(sock
, 1);
717 ICMP6_FILTER_SETBLOCKALL(&filter
);
718 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
719 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT
, &filter
);
721 ret
= setsockopt(sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
722 sizeof(struct icmp6_filter
));
724 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno
));
732 static struct rtadv_prefix
*rtadv_prefix_new(void)
734 return XCALLOC(MTYPE_RTADV_PREFIX
, sizeof(struct rtadv_prefix
));
737 static void rtadv_prefix_free(struct rtadv_prefix
*rtadv_prefix
)
739 XFREE(MTYPE_RTADV_PREFIX
, rtadv_prefix
);
742 static struct rtadv_prefix
*rtadv_prefix_lookup(struct list
*rplist
,
743 struct prefix_ipv6
*p
)
745 struct listnode
*node
;
746 struct rtadv_prefix
*rprefix
;
748 for (ALL_LIST_ELEMENTS_RO(rplist
, node
, rprefix
))
749 if (prefix_same((struct prefix
*)&rprefix
->prefix
,
755 static struct rtadv_prefix
*rtadv_prefix_get(struct list
*rplist
,
756 struct prefix_ipv6
*p
)
758 struct rtadv_prefix
*rprefix
;
760 rprefix
= rtadv_prefix_lookup(rplist
, p
);
764 rprefix
= rtadv_prefix_new();
765 memcpy(&rprefix
->prefix
, p
, sizeof(struct prefix_ipv6
));
766 listnode_add(rplist
, rprefix
);
771 static void rtadv_prefix_set(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
773 struct rtadv_prefix
*rprefix
;
775 rprefix
= rtadv_prefix_get(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
777 /* Set parameters. */
778 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
779 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
780 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
781 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
782 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
785 static int rtadv_prefix_reset(struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
787 struct rtadv_prefix
*rprefix
;
789 rprefix
= rtadv_prefix_lookup(zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
790 if (rprefix
!= NULL
) {
791 listnode_delete(zif
->rtadv
.AdvPrefixList
, (void *)rprefix
);
792 rtadv_prefix_free(rprefix
);
798 static void ipv6_nd_suppress_ra_set(struct interface
*ifp
,
799 ipv6_nd_suppress_ra_status status
)
801 struct zebra_if
*zif
;
802 struct zebra_vrf
*zvrf
;
803 struct zebra_ns
*zns
;
806 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
809 if (status
== RA_SUPPRESS
) {
810 /* RA is currently enabled */
811 if (zif
->rtadv
.AdvSendAdvertisements
) {
812 zif
->rtadv
.AdvSendAdvertisements
= 0;
813 zif
->rtadv
.AdvIntervalTimer
= 0;
814 zrouter
.rtadv
.adv_if_count
--;
816 if_leave_all_router(zrouter
.rtadv
.sock
, ifp
);
818 if (zrouter
.rtadv
.adv_if_count
== 0)
819 rtadv_event(zns
, RTADV_STOP
, 0);
822 if (!zif
->rtadv
.AdvSendAdvertisements
) {
823 zif
->rtadv
.AdvSendAdvertisements
= 1;
824 zif
->rtadv
.AdvIntervalTimer
= 0;
825 zrouter
.rtadv
.adv_if_count
++;
827 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000) {
828 /* Enable Fast RA only when RA interval is in
830 zif
->rtadv
.inFastRexmit
= 1;
831 zif
->rtadv
.NumFastReXmitsRemain
=
832 RTADV_NUM_FAST_REXMITS
;
835 if_join_all_router(zrouter
.rtadv
.sock
, ifp
);
837 if (zrouter
.rtadv
.adv_if_count
== 1)
838 rtadv_event(zns
, RTADV_START
,
845 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
846 * Note that while the client could request RA on an interface on which the
847 * operator has not enabled RA, RA won't be disabled upon client request
848 * if the operator has explicitly enabled RA. The enable request can also
849 * specify a RA interval (in seconds).
851 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS
, int enable
)
855 struct interface
*ifp
;
856 struct zebra_if
*zif
;
861 /* Get interface index and RA interval. */
862 STREAM_GETL(s
, ifindex
);
863 STREAM_GETL(s
, ra_interval
);
865 if (IS_ZEBRA_DEBUG_EVENT
)
866 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
867 zvrf_id(zvrf
), ifindex
,
868 enable
? "enable" : "disable",
869 zebra_route_string(client
->proto
), ra_interval
);
871 /* Locate interface and check VRF match. */
872 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
), ifindex
);
874 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE
,
875 "%u: IF %u RA %s client %s - interface unknown",
876 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
877 zebra_route_string(client
->proto
));
880 if (ifp
->vrf_id
!= zvrf_id(zvrf
)) {
882 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
883 zvrf_id(zvrf
), ifindex
, enable
? "enable" : "disable",
884 zebra_route_string(client
->proto
), ifp
->vrf_id
);
890 SET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
891 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
893 && (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
894 && !CHECK_FLAG(zif
->rtadv
.ra_configured
,
895 VTY_RA_INTERVAL_CONFIGURED
))
896 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
898 UNSET_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
);
899 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
,
900 VTY_RA_INTERVAL_CONFIGURED
))
901 zif
->rtadv
.MaxRtrAdvInterval
=
902 RTADV_MAX_RTR_ADV_INTERVAL
;
903 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
904 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
910 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS
)
912 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 0);
914 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS
)
916 zebra_interface_radv_set(client
, hdr
, msg
, zvrf
, 1);
919 DEFUN (ipv6_nd_suppress_ra
,
920 ipv6_nd_suppress_ra_cmd
,
921 "ipv6 nd suppress-ra",
922 "Interface IPv6 config commands\n"
923 "Neighbor discovery\n"
924 "Suppress Router Advertisement\n")
926 VTY_DECLVAR_CONTEXT(interface
, ifp
);
927 struct zebra_if
*zif
= ifp
->info
;
929 if (if_is_loopback(ifp
)
930 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
932 "Cannot configure IPv6 Router Advertisements on this interface\n");
933 return CMD_WARNING_CONFIG_FAILED
;
936 if (!CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
937 ipv6_nd_suppress_ra_set(ifp
, RA_SUPPRESS
);
939 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
943 DEFUN (no_ipv6_nd_suppress_ra
,
944 no_ipv6_nd_suppress_ra_cmd
,
945 "no ipv6 nd suppress-ra",
947 "Interface IPv6 config commands\n"
948 "Neighbor discovery\n"
949 "Suppress Router Advertisement\n")
951 VTY_DECLVAR_CONTEXT(interface
, ifp
);
952 struct zebra_if
*zif
= ifp
->info
;
954 if (if_is_loopback(ifp
)
955 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)) {
957 "Cannot configure IPv6 Router Advertisements on this interface\n");
958 return CMD_WARNING_CONFIG_FAILED
;
961 ipv6_nd_suppress_ra_set(ifp
, RA_ENABLE
);
962 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
);
966 DEFUN (ipv6_nd_ra_interval_msec
,
967 ipv6_nd_ra_interval_msec_cmd
,
968 "ipv6 nd ra-interval msec (70-1800000)",
969 "Interface IPv6 config commands\n"
970 "Neighbor discovery\n"
971 "Router Advertisement interval\n"
972 "Router Advertisement interval in milliseconds\n"
973 "Router Advertisement interval in milliseconds\n")
976 VTY_DECLVAR_CONTEXT(interface
, ifp
);
978 struct zebra_if
*zif
= ifp
->info
;
980 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
981 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
982 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000)) {
984 "This ra-interval would conflict with configured ra-lifetime!\n");
985 return CMD_WARNING_CONFIG_FAILED
;
988 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
989 zrouter
.rtadv
.adv_msec_if_count
--;
992 zrouter
.rtadv
.adv_msec_if_count
++;
994 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
995 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
996 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
997 zif
->rtadv
.AdvIntervalTimer
= 0;
1002 DEFUN (ipv6_nd_ra_interval
,
1003 ipv6_nd_ra_interval_cmd
,
1004 "ipv6 nd ra-interval (1-1800)",
1005 "Interface IPv6 config commands\n"
1006 "Neighbor discovery\n"
1007 "Router Advertisement interval\n"
1008 "Router Advertisement interval in seconds\n")
1011 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1013 struct zebra_if
*zif
= ifp
->info
;
1015 interval
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1016 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1
1017 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
)) {
1019 "This ra-interval would conflict with configured ra-lifetime!\n");
1020 return CMD_WARNING_CONFIG_FAILED
;
1023 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1024 zrouter
.rtadv
.adv_msec_if_count
--;
1026 /* convert to milliseconds */
1027 interval
= interval
* 1000;
1029 SET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1030 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
1031 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
1032 zif
->rtadv
.AdvIntervalTimer
= 0;
1037 DEFUN (no_ipv6_nd_ra_interval
,
1038 no_ipv6_nd_ra_interval_cmd
,
1039 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1041 "Interface IPv6 config commands\n"
1042 "Neighbor discovery\n"
1043 "Router Advertisement interval\n"
1044 "Router Advertisement interval in seconds\n"
1045 "Specify millisecond router advertisement interval\n"
1046 "Router Advertisement interval in milliseconds\n")
1048 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1049 struct zebra_if
*zif
= ifp
->info
;
1051 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1052 zrouter
.rtadv
.adv_msec_if_count
--;
1054 UNSET_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
);
1056 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, BGP_RA_CONFIGURED
))
1057 zif
->rtadv
.MaxRtrAdvInterval
= 10000;
1059 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1061 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1062 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1067 DEFUN (ipv6_nd_ra_lifetime
,
1068 ipv6_nd_ra_lifetime_cmd
,
1069 "ipv6 nd ra-lifetime (0-9000)",
1070 "Interface IPv6 config commands\n"
1071 "Neighbor discovery\n"
1073 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1076 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1077 struct zebra_if
*zif
= ifp
->info
;
1080 lifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1082 /* The value to be placed in the Router Lifetime field
1083 * of Router Advertisements sent from the interface,
1084 * in seconds. MUST be either zero or between
1085 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1086 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
)) {
1088 "This ra-lifetime would conflict with configured ra-interval\n");
1089 return CMD_WARNING_CONFIG_FAILED
;
1092 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1097 DEFUN (no_ipv6_nd_ra_lifetime
,
1098 no_ipv6_nd_ra_lifetime_cmd
,
1099 "no ipv6 nd ra-lifetime [(0-9000)]",
1101 "Interface IPv6 config commands\n"
1102 "Neighbor discovery\n"
1104 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1106 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1107 struct zebra_if
*zif
= ifp
->info
;
1109 zif
->rtadv
.AdvDefaultLifetime
= -1;
1114 DEFUN (ipv6_nd_reachable_time
,
1115 ipv6_nd_reachable_time_cmd
,
1116 "ipv6 nd reachable-time (1-3600000)",
1117 "Interface IPv6 config commands\n"
1118 "Neighbor discovery\n"
1120 "Reachable time in milliseconds\n")
1123 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1124 struct zebra_if
*zif
= ifp
->info
;
1125 zif
->rtadv
.AdvReachableTime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1129 DEFUN (no_ipv6_nd_reachable_time
,
1130 no_ipv6_nd_reachable_time_cmd
,
1131 "no ipv6 nd reachable-time [(1-3600000)]",
1133 "Interface IPv6 config commands\n"
1134 "Neighbor discovery\n"
1136 "Reachable time in milliseconds\n")
1138 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1139 struct zebra_if
*zif
= ifp
->info
;
1141 zif
->rtadv
.AdvReachableTime
= 0;
1146 DEFUN (ipv6_nd_homeagent_preference
,
1147 ipv6_nd_homeagent_preference_cmd
,
1148 "ipv6 nd home-agent-preference (0-65535)",
1149 "Interface IPv6 config commands\n"
1150 "Neighbor discovery\n"
1151 "Home Agent preference\n"
1152 "preference value (default is 0, least preferred)\n")
1155 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1156 struct zebra_if
*zif
= ifp
->info
;
1157 zif
->rtadv
.HomeAgentPreference
=
1158 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1162 DEFUN (no_ipv6_nd_homeagent_preference
,
1163 no_ipv6_nd_homeagent_preference_cmd
,
1164 "no ipv6 nd home-agent-preference [(0-65535)]",
1166 "Interface IPv6 config commands\n"
1167 "Neighbor discovery\n"
1168 "Home Agent preference\n"
1169 "preference value (default is 0, least preferred)\n")
1171 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1172 struct zebra_if
*zif
= ifp
->info
;
1174 zif
->rtadv
.HomeAgentPreference
= 0;
1179 DEFUN (ipv6_nd_homeagent_lifetime
,
1180 ipv6_nd_homeagent_lifetime_cmd
,
1181 "ipv6 nd home-agent-lifetime (0-65520)",
1182 "Interface IPv6 config commands\n"
1183 "Neighbor discovery\n"
1184 "Home Agent lifetime\n"
1185 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1188 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1189 struct zebra_if
*zif
= ifp
->info
;
1190 zif
->rtadv
.HomeAgentLifetime
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1194 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1195 no_ipv6_nd_homeagent_lifetime_cmd
,
1196 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1198 "Interface IPv6 config commands\n"
1199 "Neighbor discovery\n"
1200 "Home Agent lifetime\n"
1201 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1203 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1204 struct zebra_if
*zif
= ifp
->info
;
1206 zif
->rtadv
.HomeAgentLifetime
= -1;
1211 DEFUN (ipv6_nd_managed_config_flag
,
1212 ipv6_nd_managed_config_flag_cmd
,
1213 "ipv6 nd managed-config-flag",
1214 "Interface IPv6 config commands\n"
1215 "Neighbor discovery\n"
1216 "Managed address configuration flag\n")
1218 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1219 struct zebra_if
*zif
= ifp
->info
;
1221 zif
->rtadv
.AdvManagedFlag
= 1;
1226 DEFUN (no_ipv6_nd_managed_config_flag
,
1227 no_ipv6_nd_managed_config_flag_cmd
,
1228 "no ipv6 nd managed-config-flag",
1230 "Interface IPv6 config commands\n"
1231 "Neighbor discovery\n"
1232 "Managed address configuration flag\n")
1234 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1235 struct zebra_if
*zif
= ifp
->info
;
1237 zif
->rtadv
.AdvManagedFlag
= 0;
1242 DEFUN (ipv6_nd_homeagent_config_flag
,
1243 ipv6_nd_homeagent_config_flag_cmd
,
1244 "ipv6 nd home-agent-config-flag",
1245 "Interface IPv6 config commands\n"
1246 "Neighbor discovery\n"
1247 "Home Agent configuration flag\n")
1249 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1250 struct zebra_if
*zif
= ifp
->info
;
1252 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1257 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1258 no_ipv6_nd_homeagent_config_flag_cmd
,
1259 "no ipv6 nd home-agent-config-flag",
1261 "Interface IPv6 config commands\n"
1262 "Neighbor discovery\n"
1263 "Home Agent configuration flag\n")
1265 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1266 struct zebra_if
*zif
= ifp
->info
;
1268 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1273 DEFUN (ipv6_nd_adv_interval_config_option
,
1274 ipv6_nd_adv_interval_config_option_cmd
,
1275 "ipv6 nd adv-interval-option",
1276 "Interface IPv6 config commands\n"
1277 "Neighbor discovery\n"
1278 "Advertisement Interval Option\n")
1280 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1281 struct zebra_if
*zif
= ifp
->info
;
1283 zif
->rtadv
.AdvIntervalOption
= 1;
1288 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1289 no_ipv6_nd_adv_interval_config_option_cmd
,
1290 "no ipv6 nd adv-interval-option",
1292 "Interface IPv6 config commands\n"
1293 "Neighbor discovery\n"
1294 "Advertisement Interval Option\n")
1296 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1297 struct zebra_if
*zif
= ifp
->info
;
1299 zif
->rtadv
.AdvIntervalOption
= 0;
1304 DEFUN (ipv6_nd_other_config_flag
,
1305 ipv6_nd_other_config_flag_cmd
,
1306 "ipv6 nd other-config-flag",
1307 "Interface IPv6 config commands\n"
1308 "Neighbor discovery\n"
1309 "Other statefull configuration flag\n")
1311 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1312 struct zebra_if
*zif
= ifp
->info
;
1314 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1319 DEFUN (no_ipv6_nd_other_config_flag
,
1320 no_ipv6_nd_other_config_flag_cmd
,
1321 "no ipv6 nd other-config-flag",
1323 "Interface IPv6 config commands\n"
1324 "Neighbor discovery\n"
1325 "Other statefull configuration flag\n")
1327 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1328 struct zebra_if
*zif
= ifp
->info
;
1330 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1335 DEFUN (ipv6_nd_prefix
,
1337 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1338 "Interface IPv6 config commands\n"
1339 "Neighbor discovery\n"
1340 "Prefix information\n"
1342 "Valid lifetime in seconds\n"
1343 "Infinite valid lifetime\n"
1344 "Preferred lifetime in seconds\n"
1345 "Infinite preferred lifetime\n"
1346 "Set Router Address flag\n"
1347 "Do not use prefix for onlink determination\n"
1348 "Do not use prefix for autoconfiguration\n"
1349 "Do not use prefix for autoconfiguration\n"
1350 "Do not use prefix for onlink determination\n")
1353 char *prefix
= argv
[3]->arg
;
1354 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
1355 || strmatch(argv
[4]->text
, "infinite"));
1356 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1358 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1360 char *lifetime
= NULL
, *preflifetime
= NULL
;
1361 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1363 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
1365 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
1370 strmatch(argv
[idx_routeropts
]->text
, "router-address");
1372 offlink
= (argc
> idx_routeropts
+ 1
1373 || strmatch(argv
[idx_routeropts
]->text
,
1375 noautoconf
= (argc
> idx_routeropts
+ 1
1376 || strmatch(argv
[idx_routeropts
]->text
,
1382 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1383 struct zebra_if
*zebra_if
= ifp
->info
;
1385 struct rtadv_prefix rp
;
1387 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1389 vty_out(vty
, "Malformed IPv6 prefix\n");
1390 return CMD_WARNING_CONFIG_FAILED
;
1392 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1393 rp
.AdvOnLinkFlag
= !offlink
;
1394 rp
.AdvAutonomousFlag
= !noautoconf
;
1395 rp
.AdvRouterAddressFlag
= routeraddr
;
1396 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1397 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1400 rp
.AdvValidLifetime
= strmatch(lifetime
, "infinite")
1402 : strtoll(lifetime
, NULL
, 10);
1403 rp
.AdvPreferredLifetime
=
1404 strmatch(preflifetime
, "infinite")
1406 : strtoll(preflifetime
, NULL
, 10);
1407 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
) {
1408 vty_out(vty
, "Invalid preferred lifetime\n");
1409 return CMD_WARNING_CONFIG_FAILED
;
1413 rtadv_prefix_set(zebra_if
, &rp
);
1418 DEFUN (no_ipv6_nd_prefix
,
1419 no_ipv6_nd_prefix_cmd
,
1420 "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]>]",
1422 "Interface IPv6 config commands\n"
1423 "Neighbor discovery\n"
1424 "Prefix information\n"
1426 "Valid lifetime in seconds\n"
1427 "Infinite valid lifetime\n"
1428 "Preferred lifetime in seconds\n"
1429 "Infinite preferred lifetime\n"
1430 "Set Router Address flag\n"
1431 "Do not use prefix for onlink determination\n"
1432 "Do not use prefix for autoconfiguration\n"
1433 "Do not use prefix for autoconfiguration\n"
1434 "Do not use prefix for onlink determination\n")
1436 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1437 struct zebra_if
*zebra_if
= ifp
->info
;
1439 struct rtadv_prefix rp
;
1440 char *prefix
= argv
[4]->arg
;
1442 ret
= str2prefix_ipv6(prefix
, &rp
.prefix
);
1444 vty_out(vty
, "Malformed IPv6 prefix\n");
1445 return CMD_WARNING_CONFIG_FAILED
;
1447 apply_mask_ipv6(&rp
.prefix
); /* RFC4861 4.6.2 */
1449 ret
= rtadv_prefix_reset(zebra_if
, &rp
);
1451 vty_out(vty
, "Non-existant IPv6 prefix\n");
1452 return CMD_WARNING_CONFIG_FAILED
;
1458 DEFUN (ipv6_nd_router_preference
,
1459 ipv6_nd_router_preference_cmd
,
1460 "ipv6 nd router-preference <high|medium|low>",
1461 "Interface IPv6 config commands\n"
1462 "Neighbor discovery\n"
1463 "Default router preference\n"
1464 "High default router preference\n"
1465 "Medium default router preference (default)\n"
1466 "Low default router preference\n")
1468 int idx_high_medium_low
= 3;
1469 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1470 struct zebra_if
*zif
= ifp
->info
;
1473 while (0 != rtadv_pref_strs
[i
]) {
1474 if (strncmp(argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
],
1477 zif
->rtadv
.DefaultPreference
= i
;
1483 return CMD_ERR_NO_MATCH
;
1486 DEFUN (no_ipv6_nd_router_preference
,
1487 no_ipv6_nd_router_preference_cmd
,
1488 "no ipv6 nd router-preference [<high|medium|low>]",
1490 "Interface IPv6 config commands\n"
1491 "Neighbor discovery\n"
1492 "Default router preference\n"
1493 "High default router preference\n"
1494 "Medium default router preference (default)\n"
1495 "Low default router preference\n")
1497 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1498 struct zebra_if
*zif
= ifp
->info
;
1500 zif
->rtadv
.DefaultPreference
=
1501 RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1508 "ipv6 nd mtu (1-65535)",
1509 "Interface IPv6 config commands\n"
1510 "Neighbor discovery\n"
1515 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1516 struct zebra_if
*zif
= ifp
->info
;
1517 zif
->rtadv
.AdvLinkMTU
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
1521 DEFUN (no_ipv6_nd_mtu
,
1523 "no ipv6 nd mtu [(1-65535)]",
1525 "Interface IPv6 config commands\n"
1526 "Neighbor discovery\n"
1530 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1531 struct zebra_if
*zif
= ifp
->info
;
1532 zif
->rtadv
.AdvLinkMTU
= 0;
1536 /* Dump interface ND information to vty. */
1537 static int nd_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1539 struct zebra_if
*zif
;
1540 struct rtadvconf
*rtadv
;
1543 zif
= (struct zebra_if
*)ifp
->info
;
1544 rtadv
= &zif
->rtadv
;
1546 if (rtadv
->AdvSendAdvertisements
) {
1548 " ND advertised reachable time is %d milliseconds\n",
1549 rtadv
->AdvReachableTime
);
1551 " ND advertised retransmit interval is %d milliseconds\n",
1552 rtadv
->AdvRetransTimer
);
1553 vty_out(vty
, " ND router advertisements sent: %d rcvd: %d\n",
1554 zif
->ra_sent
, zif
->ra_rcvd
);
1555 interval
= rtadv
->MaxRtrAdvInterval
;
1556 if (interval
% 1000)
1558 " ND router advertisements are sent every "
1559 "%d milliseconds\n",
1563 " ND router advertisements are sent every "
1566 if (rtadv
->AdvDefaultLifetime
!= -1)
1568 " ND router advertisements live for %d seconds\n",
1569 rtadv
->AdvDefaultLifetime
);
1572 " ND router advertisements lifetime tracks ra-interval\n");
1574 " ND router advertisement default router preference is "
1576 rtadv_pref_strs
[rtadv
->DefaultPreference
]);
1577 if (rtadv
->AdvManagedFlag
)
1579 " Hosts use DHCP to obtain routable addresses.\n");
1582 " Hosts use stateless autoconfig for addresses.\n");
1583 if (rtadv
->AdvHomeAgentFlag
) {
1585 " ND router advertisements with Home Agent flag bit set.\n");
1586 if (rtadv
->HomeAgentLifetime
!= -1)
1588 " Home Agent lifetime is %u seconds\n",
1589 rtadv
->HomeAgentLifetime
);
1592 " Home Agent lifetime tracks ra-lifetime\n");
1593 vty_out(vty
, " Home Agent preference is %u\n",
1594 rtadv
->HomeAgentPreference
);
1596 if (rtadv
->AdvIntervalOption
)
1598 " ND router advertisements with Adv. Interval option.\n");
1604 /* Write configuration about router advertisement. */
1605 static int rtadv_config_write(struct vty
*vty
, struct interface
*ifp
)
1607 struct zebra_if
*zif
;
1608 struct listnode
*node
;
1609 struct rtadv_prefix
*rprefix
;
1610 char buf
[PREFIX_STRLEN
];
1615 if (!(if_is_loopback(ifp
)
1616 || CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))) {
1617 if (zif
->rtadv
.AdvSendAdvertisements
1618 && CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_CONFIGURED
))
1619 vty_out(vty
, " no ipv6 nd suppress-ra\n");
1622 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1623 if (CHECK_FLAG(zif
->rtadv
.ra_configured
, VTY_RA_INTERVAL_CONFIGURED
)) {
1624 if (interval
% 1000)
1625 vty_out(vty
, " ipv6 nd ra-interval msec %d\n",
1627 else if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1628 vty_out(vty
, " ipv6 nd ra-interval %d\n",
1632 if (zif
->rtadv
.AdvIntervalOption
)
1633 vty_out(vty
, " ipv6 nd adv-interval-option\n");
1635 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1636 vty_out(vty
, " ipv6 nd ra-lifetime %d\n",
1637 zif
->rtadv
.AdvDefaultLifetime
);
1639 if (zif
->rtadv
.HomeAgentPreference
)
1640 vty_out(vty
, " ipv6 nd home-agent-preference %u\n",
1641 zif
->rtadv
.HomeAgentPreference
);
1643 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1644 vty_out(vty
, " ipv6 nd home-agent-lifetime %u\n",
1645 zif
->rtadv
.HomeAgentLifetime
);
1647 if (zif
->rtadv
.AdvHomeAgentFlag
)
1648 vty_out(vty
, " ipv6 nd home-agent-config-flag\n");
1650 if (zif
->rtadv
.AdvReachableTime
)
1651 vty_out(vty
, " ipv6 nd reachable-time %d\n",
1652 zif
->rtadv
.AdvReachableTime
);
1654 if (zif
->rtadv
.AdvManagedFlag
)
1655 vty_out(vty
, " ipv6 nd managed-config-flag\n");
1657 if (zif
->rtadv
.AdvOtherConfigFlag
)
1658 vty_out(vty
, " ipv6 nd other-config-flag\n");
1660 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1661 vty_out(vty
, " ipv6 nd router-preference %s\n",
1662 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
]);
1664 if (zif
->rtadv
.AdvLinkMTU
)
1665 vty_out(vty
, " ipv6 nd mtu %d\n", zif
->rtadv
.AdvLinkMTU
);
1667 for (ALL_LIST_ELEMENTS_RO(zif
->rtadv
.AdvPrefixList
, node
, rprefix
)) {
1668 vty_out(vty
, " ipv6 nd prefix %s",
1669 prefix2str(&rprefix
->prefix
, buf
, sizeof(buf
)));
1670 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
)
1671 || (rprefix
->AdvPreferredLifetime
1672 != RTADV_PREFERRED_LIFETIME
)) {
1673 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1674 vty_out(vty
, " infinite");
1676 vty_out(vty
, " %u", rprefix
->AdvValidLifetime
);
1677 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1678 vty_out(vty
, " infinite");
1681 rprefix
->AdvPreferredLifetime
);
1683 if (!rprefix
->AdvOnLinkFlag
)
1684 vty_out(vty
, " off-link");
1685 if (!rprefix
->AdvAutonomousFlag
)
1686 vty_out(vty
, " no-autoconfig");
1687 if (rprefix
->AdvRouterAddressFlag
)
1688 vty_out(vty
, " router-address");
1695 static void rtadv_event(struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1697 struct rtadv
*rtadv
= &zrouter
.rtadv
;
1701 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1703 thread_add_event(zebrad
.master
, rtadv_timer
, zns
, 0,
1707 if (rtadv
->ra_timer
) {
1708 thread_cancel(rtadv
->ra_timer
);
1709 rtadv
->ra_timer
= NULL
;
1711 if (rtadv
->ra_read
) {
1712 thread_cancel(rtadv
->ra_read
);
1713 rtadv
->ra_read
= NULL
;
1717 thread_add_timer(zebrad
.master
, rtadv_timer
, zns
, val
,
1720 case RTADV_TIMER_MSEC
:
1721 thread_add_timer_msec(zebrad
.master
, rtadv_timer
, zns
, val
,
1725 thread_add_read(zebrad
.master
, rtadv_read
, zns
, val
,
1734 void rtadv_init(struct zebra_ns
*zns
)
1736 zrouter
.rtadv
.sock
= rtadv_make_socket(zns
->ns_id
);
1739 void rtadv_terminate(struct zebra_ns
*zns
)
1741 rtadv_event(zns
, RTADV_STOP
, 0);
1742 if (zrouter
.rtadv
.sock
>= 0) {
1743 close(zrouter
.rtadv
.sock
);
1744 zrouter
.rtadv
.sock
= -1;
1747 zrouter
.rtadv
.adv_if_count
= 0;
1748 zrouter
.rtadv
.adv_msec_if_count
= 0;
1751 void rtadv_cmd_init(void)
1753 hook_register(zebra_if_extra_info
, nd_dump_vty
);
1754 hook_register(zebra_if_config_wr
, rtadv_config_write
);
1756 install_element(INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1757 install_element(INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1758 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1759 install_element(INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1760 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1761 install_element(INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1762 install_element(INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1763 install_element(INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1764 install_element(INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1765 install_element(INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1766 install_element(INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1767 install_element(INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1768 install_element(INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1769 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1770 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1771 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1772 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1773 install_element(INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1774 install_element(INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1775 install_element(INTERFACE_NODE
,
1776 &ipv6_nd_adv_interval_config_option_cmd
);
1777 install_element(INTERFACE_NODE
,
1778 &no_ipv6_nd_adv_interval_config_option_cmd
);
1779 install_element(INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1780 install_element(INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1781 install_element(INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1782 install_element(INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1783 install_element(INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1784 install_element(INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1787 static int if_join_all_router(int sock
, struct interface
*ifp
)
1791 struct ipv6_mreq mreq
;
1793 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1794 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1795 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1797 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, (char *)&mreq
,
1800 flog_err_sys(EC_LIB_SOCKET
,
1801 "%s(%u): Failed to join group, socket %u error %s",
1802 ifp
->name
, ifp
->ifindex
, sock
,
1803 safe_strerror(errno
));
1805 if (IS_ZEBRA_DEBUG_EVENT
)
1807 "%s(%u): Join All-Routers multicast group, socket %u",
1808 ifp
->name
, ifp
->ifindex
, sock
);
1813 static int if_leave_all_router(int sock
, struct interface
*ifp
)
1817 struct ipv6_mreq mreq
;
1819 memset(&mreq
, 0, sizeof(struct ipv6_mreq
));
1820 inet_pton(AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1821 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1823 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, (char *)&mreq
,
1828 "%s(%u): Failed to leave group, socket %u error %s",
1829 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror(errno
));
1831 if (IS_ZEBRA_DEBUG_EVENT
)
1833 "%s(%u): Leave All-Routers multicast group, socket %u",
1834 ifp
->name
, ifp
->ifindex
, sock
);
1840 void rtadv_init(struct zebra_ns
*zns
)
1844 void rtadv_terminate(struct zebra_ns
*zns
)
1848 void rtadv_cmd_init(void)
1852 #endif /* HAVE_RTADV */