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
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 #include "zebra_memory.h"
39 #include "zebra/interface.h"
40 #include "zebra/rtadv.h"
41 #include "zebra/debug.h"
42 #include "zebra/rib.h"
43 #include "zebra/zserv.h"
44 #include "zebra/zebra_ns.h"
45 #include "zebra/zebra_vrf.h"
47 extern struct zebra_privs_t zserv_privs
;
49 #if defined (HAVE_RTADV)
52 #include <netinet/icmp6.h>
55 /* If RFC2133 definition is used. */
56 #ifndef IPV6_JOIN_GROUP
57 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
59 #ifndef IPV6_LEAVE_GROUP
60 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
63 #define ALLNODE "ff02::1"
64 #define ALLROUTER "ff02::2"
66 enum rtadv_event
{RTADV_START
, RTADV_STOP
, RTADV_TIMER
,
67 RTADV_TIMER_MSEC
, RTADV_READ
};
69 static void rtadv_event (struct zebra_ns
*, enum rtadv_event
, int);
71 static int if_join_all_router (int, struct interface
*);
72 static int if_leave_all_router (int, struct interface
*);
75 rtadv_increment_received(struct zebra_ns
*zns
, ifindex_t
*ifindex
)
78 struct interface
*iface
;
81 iface
= if_lookup_by_index_per_ns (zns
, *ifindex
);
82 if (iface
&& iface
->info
)
92 rtadv_recv_packet (struct zebra_ns
*zns
, int sock
, u_char
*buf
, int buflen
,
93 struct sockaddr_in6
*from
, ifindex_t
*ifindex
,
99 struct cmsghdr
*cmsgptr
;
104 /* Fill in message and iovec. */
105 msg
.msg_name
= (void *) from
;
106 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
109 msg
.msg_control
= (void *) adata
;
110 msg
.msg_controllen
= sizeof adata
;
112 iov
.iov_len
= buflen
;
114 /* If recvmsg fail return minus value. */
115 ret
= recvmsg (sock
, &msg
, 0);
119 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
120 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
122 /* I want interface index which this packet comes from. */
123 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
124 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
126 struct in6_pktinfo
*ptr
;
128 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
129 *ifindex
= ptr
->ipi6_ifindex
;
130 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
133 /* Incoming packet's hop limit. */
134 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
135 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
137 int *hoptr
= (int *) CMSG_DATA (cmsgptr
);
142 rtadv_increment_received(zns
, ifindex
);
146 #define RTADV_MSG_SIZE 4096
148 /* Send router advertisement packet. */
150 rtadv_send_packet (int sock
, struct interface
*ifp
)
154 struct cmsghdr
*cmsgptr
;
155 struct in6_pktinfo
*pkt
;
156 struct sockaddr_in6 addr
;
157 static void *adata
= NULL
;
158 unsigned char buf
[RTADV_MSG_SIZE
];
159 struct nd_router_advert
*rtadv
;
162 struct zebra_if
*zif
;
163 struct rtadv_prefix
*rprefix
;
164 u_char all_nodes_addr
[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
165 struct listnode
*node
;
166 u_int16_t pkt_RouterLifetime
;
169 * Allocate control message bufffer. This is dynamic because
170 * CMSG_SPACE is not guaranteed not to call a function. Note that
171 * the size will be different on different architectures due to
172 * differing alignment rules.
176 /* XXX Free on shutdown. */
177 adata
= malloc(CMSG_SPACE(sizeof(struct in6_pktinfo
)));
180 zlog_err("rtadv_send_packet: can't malloc control data");
183 /* Logging of packet. */
184 if (IS_ZEBRA_DEBUG_PACKET
)
185 zlog_debug ("%s(%u): Tx RA, socket %u",
186 ifp
->name
, ifp
->ifindex
, sock
);
188 /* Fill in sockaddr_in6. */
189 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
190 addr
.sin6_family
= AF_INET6
;
192 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
193 #endif /* SIN6_LEN */
194 addr
.sin6_port
= htons (IPPROTO_ICMPV6
);
195 IPV6_ADDR_COPY (&addr
.sin6_addr
, all_nodes_addr
);
197 /* Fetch interface information. */
200 /* Make router advertisement message. */
201 rtadv
= (struct nd_router_advert
*) buf
;
203 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
204 rtadv
->nd_ra_code
= 0;
205 rtadv
->nd_ra_cksum
= 0;
207 rtadv
->nd_ra_curhoplimit
= 64;
209 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
210 rtadv
->nd_ra_flags_reserved
=
211 zif
->rtadv
.AdvDefaultLifetime
== 0 ? 0 : zif
->rtadv
.DefaultPreference
;
212 rtadv
->nd_ra_flags_reserved
<<= 3;
214 if (zif
->rtadv
.AdvManagedFlag
)
215 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
216 if (zif
->rtadv
.AdvOtherConfigFlag
)
217 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
218 if (zif
->rtadv
.AdvHomeAgentFlag
)
219 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_HOME_AGENT
;
220 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
221 * AdvDefaultLifetime is by default based on the value of
222 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
223 * field of Router Advertisements. Given that this field is expressed
224 * in seconds, a small MaxRtrAdvInterval value can result in a zero
225 * value for this field. To prevent this, routers SHOULD keep
226 * AdvDefaultLifetime in at least one second, even if the use of
227 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
228 pkt_RouterLifetime
= zif
->rtadv
.AdvDefaultLifetime
!= -1 ?
229 zif
->rtadv
.AdvDefaultLifetime
:
230 MAX (1, 0.003 * zif
->rtadv
.MaxRtrAdvInterval
);
231 rtadv
->nd_ra_router_lifetime
= htons (pkt_RouterLifetime
);
232 rtadv
->nd_ra_reachable
= htonl (zif
->rtadv
.AdvReachableTime
);
233 rtadv
->nd_ra_retransmit
= htonl (0);
235 len
= sizeof (struct nd_router_advert
);
237 /* If both the Home Agent Preference and Home Agent Lifetime are set to
238 * their default values specified above, this option SHOULD NOT be
239 * included in the Router Advertisement messages sent by this home
240 * agent. -- RFC6275, 7.4 */
243 zif
->rtadv
.AdvHomeAgentFlag
&&
244 (zif
->rtadv
.HomeAgentPreference
|| zif
->rtadv
.HomeAgentLifetime
!= -1)
247 struct nd_opt_homeagent_info
*ndopt_hai
=
248 (struct nd_opt_homeagent_info
*)(buf
+ len
);
249 ndopt_hai
->nd_opt_hai_type
= ND_OPT_HA_INFORMATION
;
250 ndopt_hai
->nd_opt_hai_len
= 1;
251 ndopt_hai
->nd_opt_hai_reserved
= 0;
252 ndopt_hai
->nd_opt_hai_preference
= htons(zif
->rtadv
.HomeAgentPreference
);
253 /* 16-bit unsigned integer. The lifetime associated with the home
254 * agent in units of seconds. The default value is the same as the
255 * Router Lifetime, as specified in the main body of the Router
256 * Advertisement. The maximum value corresponds to 18.2 hours. A
257 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
258 ndopt_hai
->nd_opt_hai_lifetime
= htons
260 zif
->rtadv
.HomeAgentLifetime
!= -1 ?
261 zif
->rtadv
.HomeAgentLifetime
:
262 MAX (1, pkt_RouterLifetime
) /* 0 is OK for RL, but not for HAL*/
264 len
+= sizeof(struct nd_opt_homeagent_info
);
267 if (zif
->rtadv
.AdvIntervalOption
)
269 struct nd_opt_adv_interval
*ndopt_adv
=
270 (struct nd_opt_adv_interval
*)(buf
+ len
);
271 ndopt_adv
->nd_opt_ai_type
= ND_OPT_ADV_INTERVAL
;
272 ndopt_adv
->nd_opt_ai_len
= 1;
273 ndopt_adv
->nd_opt_ai_reserved
= 0;
274 ndopt_adv
->nd_opt_ai_interval
= htonl(zif
->rtadv
.MaxRtrAdvInterval
);
275 len
+= sizeof(struct nd_opt_adv_interval
);
278 /* Fill in prefix. */
279 for (ALL_LIST_ELEMENTS_RO (zif
->rtadv
.AdvPrefixList
, node
, rprefix
))
281 struct nd_opt_prefix_info
*pinfo
;
283 pinfo
= (struct nd_opt_prefix_info
*) (buf
+ len
);
285 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
286 pinfo
->nd_opt_pi_len
= 4;
287 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
289 pinfo
->nd_opt_pi_flags_reserved
= 0;
290 if (rprefix
->AdvOnLinkFlag
)
291 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_ONLINK
;
292 if (rprefix
->AdvAutonomousFlag
)
293 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
294 if (rprefix
->AdvRouterAddressFlag
)
295 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_RADDR
;
297 pinfo
->nd_opt_pi_valid_time
= htonl (rprefix
->AdvValidLifetime
);
298 pinfo
->nd_opt_pi_preferred_time
= htonl (rprefix
->AdvPreferredLifetime
);
299 pinfo
->nd_opt_pi_reserved2
= 0;
301 IPV6_ADDR_COPY (&pinfo
->nd_opt_pi_prefix
, &rprefix
->prefix
.prefix
);
305 u_char buf
[INET6_ADDRSTRLEN
];
307 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
308 buf
, INET6_ADDRSTRLEN
));
313 len
+= sizeof (struct nd_opt_prefix_info
);
316 /* Hardware address. */
317 if (ifp
->hw_addr_len
!= 0)
319 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
321 /* Option length should be rounded up to next octet if
322 the link address does not end on an octet boundary. */
323 buf
[len
++] = (ifp
->hw_addr_len
+ 9) >> 3;
325 memcpy (buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
326 len
+= ifp
->hw_addr_len
;
328 /* Pad option to end on an octet boundary. */
329 memset (buf
+ len
, 0, -(ifp
->hw_addr_len
+ 2) & 0x7);
330 len
+= -(ifp
->hw_addr_len
+ 2) & 0x7;
334 if (zif
->rtadv
.AdvLinkMTU
)
336 struct nd_opt_mtu
* opt
= (struct nd_opt_mtu
*) (buf
+ len
);
337 opt
->nd_opt_mtu_type
= ND_OPT_MTU
;
338 opt
->nd_opt_mtu_len
= 1;
339 opt
->nd_opt_mtu_reserved
= 0;
340 opt
->nd_opt_mtu_mtu
= htonl (zif
->rtadv
.AdvLinkMTU
);
341 len
+= sizeof (struct nd_opt_mtu
);
344 msg
.msg_name
= (void *) &addr
;
345 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
348 msg
.msg_control
= (void *) adata
;
349 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
354 cmsgptr
= ZCMSG_FIRSTHDR(&msg
);
355 cmsgptr
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
356 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
357 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
359 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
360 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
361 pkt
->ipi6_ifindex
= ifp
->ifindex
;
363 ret
= sendmsg (sock
, &msg
, 0);
366 zlog_err ("%s(%u): Tx RA failed, socket %u error %d (%s)",
367 ifp
->name
, ifp
->ifindex
, sock
, errno
, safe_strerror(errno
));
374 rtadv_timer (struct thread
*thread
)
376 struct zebra_ns
*zns
= THREAD_ARG (thread
);
378 struct listnode
*node
, *nnode
;
379 struct interface
*ifp
;
380 struct zebra_if
*zif
;
383 zns
->rtadv
.ra_timer
= NULL
;
384 if (zns
->rtadv
.adv_msec_if_count
== 0)
386 period
= 1000; /* 1 s */
387 rtadv_event (zns
, RTADV_TIMER
, 1 /* 1 s */);
391 period
= 10; /* 10 ms */
392 rtadv_event (zns
, RTADV_TIMER_MSEC
, 10 /* 10 ms */);
395 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
396 for (ALL_LIST_ELEMENTS (vrf
->iflist
, node
, nnode
, ifp
))
398 if (if_is_loopback (ifp
) ||
399 CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
) ||
400 ! if_is_operative (ifp
))
405 if (zif
->rtadv
.AdvSendAdvertisements
)
407 if (zif
->rtadv
.inFastRexmit
)
409 /* We assume we fast rexmit every sec so no additional vars */
410 if (--zif
->rtadv
.NumFastReXmitsRemain
<= 0)
411 zif
->rtadv
.inFastRexmit
= 0;
413 if (IS_ZEBRA_DEBUG_SEND
)
414 zlog_debug("Fast RA Rexmit on interface %s", ifp
->name
);
416 rtadv_send_packet (zns
->rtadv
.sock
, ifp
);
420 zif
->rtadv
.AdvIntervalTimer
-= period
;
421 if (zif
->rtadv
.AdvIntervalTimer
<= 0)
423 /* FIXME: using MaxRtrAdvInterval each time isn't what section
424 6.2.4 of RFC4861 tells to do. */
425 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
426 rtadv_send_packet (zns
->rtadv
.sock
, ifp
);
436 rtadv_process_solicit (struct interface
*ifp
)
438 struct zebra_vrf
*zvrf
= vrf_info_lookup (ifp
->vrf_id
);
439 struct zebra_ns
*zns
= zvrf
->zns
;
442 rtadv_send_packet (zns
->rtadv
.sock
, ifp
);
446 rtadv_process_advert (u_char
*msg
, unsigned int len
, struct interface
*ifp
,
447 struct sockaddr_in6
*addr
)
449 struct nd_router_advert
*radvert
;
450 char addr_str
[INET6_ADDRSTRLEN
];
451 struct zebra_if
*zif
;
456 inet_ntop (AF_INET6
, &addr
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
458 if (len
< sizeof(struct nd_router_advert
)) {
459 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
460 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
463 if (!IN6_IS_ADDR_LINKLOCAL(&addr
->sin6_addr
)) {
464 zlog_warn("%s(%u): Rx RA with non-linklocal source address from %s",
465 ifp
->name
, ifp
->ifindex
, addr_str
);
469 radvert
= (struct nd_router_advert
*) msg
;
471 if ((radvert
->nd_ra_curhoplimit
&& zif
->rtadv
.AdvCurHopLimit
) &&
472 (radvert
->nd_ra_curhoplimit
!= zif
->rtadv
.AdvCurHopLimit
))
474 zlog_warn("%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
475 ifp
->name
, ifp
->ifindex
, addr_str
);
478 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
) &&
479 !zif
->rtadv
.AdvManagedFlag
)
481 zlog_warn("%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
482 ifp
->name
, ifp
->ifindex
, addr_str
);
485 if ((radvert
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
) &&
486 !zif
->rtadv
.AdvOtherConfigFlag
)
488 zlog_warn("%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
489 ifp
->name
, ifp
->ifindex
, addr_str
);
492 if ((radvert
->nd_ra_reachable
&& zif
->rtadv
.AdvReachableTime
) &&
493 (ntohl(radvert
->nd_ra_reachable
) != zif
->rtadv
.AdvReachableTime
))
495 zlog_warn("%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
496 ifp
->name
, ifp
->ifindex
, addr_str
);
499 if ((radvert
->nd_ra_retransmit
&& zif
->rtadv
.AdvRetransTimer
) &&
500 (ntohl(radvert
->nd_ra_retransmit
) != (unsigned int)zif
->rtadv
.AdvRetransTimer
))
502 zlog_warn("%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
503 ifp
->name
, ifp
->ifindex
, addr_str
);
506 /* Create entry for neighbor if not known. */
508 IPV6_ADDR_COPY (&p
.u
.prefix
, &addr
->sin6_addr
);
509 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
511 if (!nbr_connected_check(ifp
, &p
))
512 nbr_connected_add_ipv6 (ifp
, &addr
->sin6_addr
);
517 rtadv_process_packet (u_char
*buf
, unsigned int len
, ifindex_t ifindex
, int hoplimit
,
518 struct sockaddr_in6
*from
, struct zebra_ns
*zns
)
520 struct icmp6_hdr
*icmph
;
521 struct interface
*ifp
;
522 struct zebra_if
*zif
;
523 char addr_str
[INET6_ADDRSTRLEN
];
525 inet_ntop (AF_INET6
, &from
->sin6_addr
, addr_str
, INET6_ADDRSTRLEN
);
527 /* Interface search. */
528 ifp
= if_lookup_by_index_per_ns (zns
, ifindex
);
531 zlog_warn ("RA/RS received on unknown IF %u from %s",
536 if (IS_ZEBRA_DEBUG_PACKET
)
537 zlog_debug ("%s(%u): Rx RA/RS len %d from %s",
538 ifp
->name
, ifp
->ifindex
, len
, addr_str
);
540 if (if_is_loopback (ifp
) ||
541 CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
544 /* Check interface configuration. */
546 if (! zif
->rtadv
.AdvSendAdvertisements
)
549 /* ICMP message length check. */
550 if (len
< sizeof (struct icmp6_hdr
))
552 zlog_warn ("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
553 ifp
->name
, ifp
->ifindex
, len
);
557 icmph
= (struct icmp6_hdr
*) buf
;
559 /* ICMP message type check. */
560 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
&&
561 icmph
->icmp6_type
!= ND_ROUTER_ADVERT
)
563 zlog_warn ("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
564 ifp
->name
, ifp
->ifindex
, icmph
->icmp6_type
);
568 /* Hoplimit check. */
569 if (hoplimit
>= 0 && hoplimit
!= 255)
571 zlog_warn ("%s(%u): Rx RA - Invalid hoplimit %d",
572 ifp
->name
, ifp
->ifindex
, hoplimit
);
576 /* Check ICMP message type. */
577 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
578 rtadv_process_solicit (ifp
);
579 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
580 rtadv_process_advert (buf
, len
, ifp
, from
);
586 rtadv_read (struct thread
*thread
)
590 u_char buf
[RTADV_MSG_SIZE
];
591 struct sockaddr_in6 from
;
592 ifindex_t ifindex
= 0;
594 struct zebra_ns
*zns
= THREAD_ARG (thread
);
596 sock
= THREAD_FD (thread
);
597 zns
->rtadv
.ra_read
= NULL
;
599 /* Register myself. */
600 rtadv_event (zns
, RTADV_READ
, sock
);
602 len
= rtadv_recv_packet (zns
, sock
, buf
, sizeof (buf
), &from
, &ifindex
, &hoplimit
);
606 zlog_warn ("RA/RS recv failed, socket %u error %s",
607 sock
, safe_strerror (errno
));
611 rtadv_process_packet (buf
, (unsigned)len
, ifindex
, hoplimit
, &from
, zns
);
617 rtadv_make_socket (void)
621 struct icmp6_filter filter
;
623 if ( zserv_privs
.change (ZPRIVS_RAISE
) )
624 zlog_err ("rtadv_make_socket: could not raise privs, %s",
625 safe_strerror (errno
) );
627 sock
= socket (AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
629 if ( zserv_privs
.change (ZPRIVS_LOWER
) )
630 zlog_err ("rtadv_make_socket: could not lower privs, %s",
631 safe_strerror (errno
) );
639 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
645 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
651 ret
= setsockopt_ipv6_unicast_hops (sock
, 255);
657 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
663 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
670 ICMP6_FILTER_SETBLOCKALL(&filter
);
671 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT
, &filter
);
672 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT
, &filter
);
674 ret
= setsockopt (sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
675 sizeof (struct icmp6_filter
));
678 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno
));
685 static struct rtadv_prefix
*
686 rtadv_prefix_new (void)
688 return XCALLOC (MTYPE_RTADV_PREFIX
, sizeof (struct rtadv_prefix
));
692 rtadv_prefix_free (struct rtadv_prefix
*rtadv_prefix
)
694 XFREE (MTYPE_RTADV_PREFIX
, rtadv_prefix
);
697 static struct rtadv_prefix
*
698 rtadv_prefix_lookup (struct list
*rplist
, struct prefix_ipv6
*p
)
700 struct listnode
*node
;
701 struct rtadv_prefix
*rprefix
;
703 for (ALL_LIST_ELEMENTS_RO (rplist
, node
, rprefix
))
704 if (prefix_same ((struct prefix
*) &rprefix
->prefix
, (struct prefix
*) p
))
709 static struct rtadv_prefix
*
710 rtadv_prefix_get (struct list
*rplist
, struct prefix_ipv6
*p
)
712 struct rtadv_prefix
*rprefix
;
714 rprefix
= rtadv_prefix_lookup (rplist
, p
);
718 rprefix
= rtadv_prefix_new ();
719 memcpy (&rprefix
->prefix
, p
, sizeof (struct prefix_ipv6
));
720 listnode_add (rplist
, rprefix
);
726 rtadv_prefix_set (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
728 struct rtadv_prefix
*rprefix
;
730 rprefix
= rtadv_prefix_get (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
732 /* Set parameters. */
733 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
734 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
735 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
736 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
737 rprefix
->AdvRouterAddressFlag
= rp
->AdvRouterAddressFlag
;
741 rtadv_prefix_reset (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
743 struct rtadv_prefix
*rprefix
;
745 rprefix
= rtadv_prefix_lookup (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
748 listnode_delete (zif
->rtadv
.AdvPrefixList
, (void *) rprefix
);
749 rtadv_prefix_free (rprefix
);
757 ipv6_nd_suppress_ra_set (struct interface
*ifp
, ipv6_nd_suppress_ra_status status
)
759 struct zebra_if
*zif
;
760 struct zebra_vrf
*zvrf
;
761 struct zebra_ns
*zns
;
764 zvrf
= vrf_info_lookup (ifp
->vrf_id
);
767 if (status
== RA_SUPPRESS
)
769 /* RA is currently enabled */
770 if (zif
->rtadv
.AdvSendAdvertisements
)
772 zif
->rtadv
.AdvSendAdvertisements
= 0;
773 zif
->rtadv
.AdvIntervalTimer
= 0;
774 zns
->rtadv
.adv_if_count
--;
776 if_leave_all_router (zns
->rtadv
.sock
, ifp
);
778 if (zns
->rtadv
.adv_if_count
== 0)
779 rtadv_event (zns
, RTADV_STOP
, 0);
784 if (! zif
->rtadv
.AdvSendAdvertisements
)
786 zif
->rtadv
.AdvSendAdvertisements
= 1;
787 zif
->rtadv
.AdvIntervalTimer
= 0;
788 zns
->rtadv
.adv_if_count
++;
790 if (zif
->rtadv
.MaxRtrAdvInterval
>= 1000)
792 /* Enable Fast RA only when RA interval is in secs */
793 zif
->rtadv
.inFastRexmit
= 1;
794 zif
->rtadv
.NumFastReXmitsRemain
= RTADV_NUM_FAST_REXMITS
;
797 if_join_all_router (zns
->rtadv
.sock
, ifp
);
799 if (zns
->rtadv
.adv_if_count
== 1)
800 rtadv_event (zns
, RTADV_START
, zns
->rtadv
.sock
);
806 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
807 * Note that while the client could request RA on an interface on which the
808 * operator has not enabled RA, RA won't be disabled upon client request
809 * if the operator has explicitly enabled RA. The enable request can also
810 * specify a RA interval (in seconds).
813 zebra_interface_radv_set (struct zserv
*client
, int sock
, u_short length
,
814 struct zebra_vrf
*zvrf
, int enable
)
817 unsigned int ifindex
;
818 struct interface
*ifp
;
819 struct zebra_if
*zif
;
824 /* Get interface index and RA interval. */
825 ifindex
= stream_getl (s
);
826 ra_interval
= stream_getl (s
);
828 if (IS_ZEBRA_DEBUG_EVENT
)
829 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
830 zvrf_id (zvrf
), ifindex
, enable
? "enable" : "disable",
831 zebra_route_string(client
->proto
), ra_interval
);
833 /* Locate interface and check VRF match. */
834 ifp
= if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT
), ifindex
);
837 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
838 zvrf_id (zvrf
), ifindex
, enable
? "enable" : "disable",
839 zebra_route_string(client
->proto
));
842 if (ifp
->vrf_id
!= zvrf_id (zvrf
))
844 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
845 zvrf_id (zvrf
), ifindex
, enable
? "enable" : "disable",
846 zebra_route_string(client
->proto
), ifp
->vrf_id
);
853 ipv6_nd_suppress_ra_set (ifp
, RA_ENABLE
);
855 (ra_interval
* 1000) < zif
->rtadv
.MaxRtrAdvInterval
)
856 zif
->rtadv
.MaxRtrAdvInterval
= ra_interval
* 1000;
860 if (!zif
->rtadv
.configured
)
862 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
863 ipv6_nd_suppress_ra_set (ifp
, RA_SUPPRESS
);
868 DEFUN (ipv6_nd_suppress_ra
,
869 ipv6_nd_suppress_ra_cmd
,
870 "ipv6 nd suppress-ra",
871 "Interface IPv6 config commands\n"
872 "Neighbor discovery\n"
873 "Suppress Router Advertisement\n")
875 VTY_DECLVAR_CONTEXT (interface
, ifp
);
876 struct zebra_if
*zif
= ifp
->info
;
878 if (if_is_loopback (ifp
) ||
879 CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
881 vty_out (vty
, "Cannot configure IPv6 Router Advertisements on this interface%s", VTY_NEWLINE
);
885 ipv6_nd_suppress_ra_set (ifp
, RA_SUPPRESS
);
886 zif
->rtadv
.configured
= 0;
890 DEFUN (no_ipv6_nd_suppress_ra
,
891 no_ipv6_nd_suppress_ra_cmd
,
892 "no ipv6 nd suppress-ra",
894 "Interface IPv6 config commands\n"
895 "Neighbor discovery\n"
896 "Suppress Router Advertisement\n")
898 VTY_DECLVAR_CONTEXT (interface
, ifp
);
899 struct zebra_if
*zif
= ifp
->info
;
901 if (if_is_loopback (ifp
) ||
902 CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
))
904 vty_out (vty
, "Cannot configure IPv6 Router Advertisements on this interface%s", VTY_NEWLINE
);
908 ipv6_nd_suppress_ra_set (ifp
, RA_ENABLE
);
909 zif
->rtadv
.configured
= 1;
913 DEFUN (ipv6_nd_ra_interval_msec
,
914 ipv6_nd_ra_interval_msec_cmd
,
915 "ipv6 nd ra-interval msec (70-1800000)",
916 "Interface IPv6 config commands\n"
917 "Neighbor discovery\n"
918 "Router Advertisement interval\n"
919 "Router Advertisement interval in milliseconds\n"
920 "Router Advertisement interval in milliseconds\n")
923 VTY_DECLVAR_CONTEXT (interface
, ifp
);
925 struct zebra_if
*zif
= ifp
->info
;
926 struct zebra_vrf
*zvrf
= vrf_info_lookup (ifp
->vrf_id
);
927 struct zebra_ns
*zns
;
930 VTY_GET_INTEGER_RANGE ("router advertisement interval", interval
, argv
[idx_number
]->arg
, 70, 1800000);
931 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
* 1000))
933 vty_out (vty
, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE
);
937 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
938 zns
->rtadv
.adv_msec_if_count
--;
941 zns
->rtadv
.adv_msec_if_count
++;
943 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
944 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
945 zif
->rtadv
.AdvIntervalTimer
= 0;
950 DEFUN (ipv6_nd_ra_interval
,
951 ipv6_nd_ra_interval_cmd
,
952 "ipv6 nd ra-interval (1-1800)",
953 "Interface IPv6 config commands\n"
954 "Neighbor discovery\n"
955 "Router Advertisement interval\n"
956 "Router Advertisement interval in seconds\n")
959 VTY_DECLVAR_CONTEXT (interface
, ifp
);
961 struct zebra_if
*zif
= ifp
->info
;
962 struct zebra_vrf
*zvrf
= vrf_info_lookup (ifp
->vrf_id
);
963 struct zebra_ns
*zns
;
966 VTY_GET_INTEGER_RANGE ("router advertisement interval", interval
, argv
[idx_number
]->arg
, 1, 1800);
967 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
))
969 vty_out (vty
, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE
);
973 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
974 zns
->rtadv
.adv_msec_if_count
--;
976 /* convert to milliseconds */
977 interval
= interval
* 1000;
979 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
980 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
981 zif
->rtadv
.AdvIntervalTimer
= 0;
986 DEFUN (no_ipv6_nd_ra_interval
,
987 no_ipv6_nd_ra_interval_cmd
,
988 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
990 "Interface IPv6 config commands\n"
991 "Neighbor discovery\n"
992 "Router Advertisement interval\n"
993 "Router Advertisement interval in seconds\n"
994 "Specify millisecond router advertisement interval\n"
995 "Router Advertisement interval in milliseconds\n")
997 VTY_DECLVAR_CONTEXT (interface
, ifp
);
998 struct zebra_if
*zif
= ifp
->info
;
999 struct zebra_vrf
*zvrf
;
1000 struct zebra_ns
*zns
;
1002 zvrf
= vrf_info_lookup (ifp
->vrf_id
);
1005 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
1006 zns
->rtadv
.adv_msec_if_count
--;
1008 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
1009 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
1010 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
1015 DEFUN (ipv6_nd_ra_lifetime
,
1016 ipv6_nd_ra_lifetime_cmd
,
1017 "ipv6 nd ra-lifetime (0-9000)",
1018 "Interface IPv6 config commands\n"
1019 "Neighbor discovery\n"
1021 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1024 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1025 struct zebra_if
*zif
= ifp
->info
;
1028 VTY_GET_INTEGER_RANGE ("router lifetime", lifetime
, argv
[idx_number
]->arg
, 0, 9000);
1030 /* The value to be placed in the Router Lifetime field
1031 * of Router Advertisements sent from the interface,
1032 * in seconds. MUST be either zero or between
1033 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1034 if ((lifetime
!= 0 && lifetime
* 1000 < zif
->rtadv
.MaxRtrAdvInterval
))
1036 vty_out (vty
, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE
);
1040 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
1045 DEFUN (no_ipv6_nd_ra_lifetime
,
1046 no_ipv6_nd_ra_lifetime_cmd
,
1047 "no ipv6 nd ra-lifetime [(0-9000)]",
1049 "Interface IPv6 config commands\n"
1050 "Neighbor discovery\n"
1052 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1054 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1055 struct zebra_if
*zif
= ifp
->info
;
1057 zif
->rtadv
.AdvDefaultLifetime
= -1;
1062 DEFUN (ipv6_nd_reachable_time
,
1063 ipv6_nd_reachable_time_cmd
,
1064 "ipv6 nd reachable-time (1-3600000)",
1065 "Interface IPv6 config commands\n"
1066 "Neighbor discovery\n"
1068 "Reachable time in milliseconds\n")
1071 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1072 struct zebra_if
*zif
= ifp
->info
;
1073 VTY_GET_INTEGER_RANGE ("reachable time", zif
->rtadv
.AdvReachableTime
, argv
[idx_number
]->arg
, 1, RTADV_MAX_REACHABLE_TIME
);
1077 DEFUN (no_ipv6_nd_reachable_time
,
1078 no_ipv6_nd_reachable_time_cmd
,
1079 "no ipv6 nd reachable-time [(1-3600000)]",
1081 "Interface IPv6 config commands\n"
1082 "Neighbor discovery\n"
1084 "Reachable time in milliseconds\n")
1086 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1087 struct zebra_if
*zif
= ifp
->info
;
1089 zif
->rtadv
.AdvReachableTime
= 0;
1094 DEFUN (ipv6_nd_homeagent_preference
,
1095 ipv6_nd_homeagent_preference_cmd
,
1096 "ipv6 nd home-agent-preference (0-65535)",
1097 "Interface IPv6 config commands\n"
1098 "Neighbor discovery\n"
1099 "Home Agent preference\n"
1100 "preference value (default is 0, least preferred)\n")
1103 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1104 struct zebra_if
*zif
= ifp
->info
;
1105 VTY_GET_INTEGER_RANGE ("home agent preference", zif
->rtadv
.HomeAgentPreference
, argv
[idx_number
]->arg
, 0, 65535);
1109 DEFUN (no_ipv6_nd_homeagent_preference
,
1110 no_ipv6_nd_homeagent_preference_cmd
,
1111 "no ipv6 nd home-agent-preference [(0-65535)]",
1113 "Interface IPv6 config commands\n"
1114 "Neighbor discovery\n"
1115 "Home Agent preference\n"
1116 "preference value (default is 0, least preferred)\n")
1118 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1119 struct zebra_if
*zif
= ifp
->info
;
1121 zif
->rtadv
.HomeAgentPreference
= 0;
1126 DEFUN (ipv6_nd_homeagent_lifetime
,
1127 ipv6_nd_homeagent_lifetime_cmd
,
1128 "ipv6 nd home-agent-lifetime (0-65520)",
1129 "Interface IPv6 config commands\n"
1130 "Neighbor discovery\n"
1131 "Home Agent lifetime\n"
1132 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1135 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1136 struct zebra_if
*zif
= ifp
->info
;
1137 VTY_GET_INTEGER_RANGE ("home agent lifetime", zif
->rtadv
.HomeAgentLifetime
, argv
[idx_number
]->arg
, 0, RTADV_MAX_HALIFETIME
);
1141 DEFUN (no_ipv6_nd_homeagent_lifetime
,
1142 no_ipv6_nd_homeagent_lifetime_cmd
,
1143 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1145 "Interface IPv6 config commands\n"
1146 "Neighbor discovery\n"
1147 "Home Agent lifetime\n"
1148 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1150 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1151 struct zebra_if
*zif
= ifp
->info
;
1153 zif
->rtadv
.HomeAgentLifetime
= -1;
1158 DEFUN (ipv6_nd_managed_config_flag
,
1159 ipv6_nd_managed_config_flag_cmd
,
1160 "ipv6 nd managed-config-flag",
1161 "Interface IPv6 config commands\n"
1162 "Neighbor discovery\n"
1163 "Managed address configuration flag\n")
1165 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1166 struct zebra_if
*zif
= ifp
->info
;
1168 zif
->rtadv
.AdvManagedFlag
= 1;
1173 DEFUN (no_ipv6_nd_managed_config_flag
,
1174 no_ipv6_nd_managed_config_flag_cmd
,
1175 "no ipv6 nd managed-config-flag",
1177 "Interface IPv6 config commands\n"
1178 "Neighbor discovery\n"
1179 "Managed address configuration flag\n")
1181 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1182 struct zebra_if
*zif
= ifp
->info
;
1184 zif
->rtadv
.AdvManagedFlag
= 0;
1189 DEFUN (ipv6_nd_homeagent_config_flag
,
1190 ipv6_nd_homeagent_config_flag_cmd
,
1191 "ipv6 nd home-agent-config-flag",
1192 "Interface IPv6 config commands\n"
1193 "Neighbor discovery\n"
1194 "Home Agent configuration flag\n")
1196 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1197 struct zebra_if
*zif
= ifp
->info
;
1199 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1204 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1205 no_ipv6_nd_homeagent_config_flag_cmd
,
1206 "no ipv6 nd home-agent-config-flag",
1208 "Interface IPv6 config commands\n"
1209 "Neighbor discovery\n"
1210 "Home Agent configuration flag\n")
1212 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1213 struct zebra_if
*zif
= ifp
->info
;
1215 zif
->rtadv
.AdvHomeAgentFlag
= 0;
1220 DEFUN (ipv6_nd_adv_interval_config_option
,
1221 ipv6_nd_adv_interval_config_option_cmd
,
1222 "ipv6 nd adv-interval-option",
1223 "Interface IPv6 config commands\n"
1224 "Neighbor discovery\n"
1225 "Advertisement Interval Option\n")
1227 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1228 struct zebra_if
*zif
= ifp
->info
;
1230 zif
->rtadv
.AdvIntervalOption
= 1;
1235 DEFUN (no_ipv6_nd_adv_interval_config_option
,
1236 no_ipv6_nd_adv_interval_config_option_cmd
,
1237 "no ipv6 nd adv-interval-option",
1239 "Interface IPv6 config commands\n"
1240 "Neighbor discovery\n"
1241 "Advertisement Interval Option\n")
1243 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1244 struct zebra_if
*zif
= ifp
->info
;
1246 zif
->rtadv
.AdvIntervalOption
= 0;
1251 DEFUN (ipv6_nd_other_config_flag
,
1252 ipv6_nd_other_config_flag_cmd
,
1253 "ipv6 nd other-config-flag",
1254 "Interface IPv6 config commands\n"
1255 "Neighbor discovery\n"
1256 "Other statefull configuration flag\n")
1258 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1259 struct zebra_if
*zif
= ifp
->info
;
1261 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1266 DEFUN (no_ipv6_nd_other_config_flag
,
1267 no_ipv6_nd_other_config_flag_cmd
,
1268 "no ipv6 nd other-config-flag",
1270 "Interface IPv6 config commands\n"
1271 "Neighbor discovery\n"
1272 "Other statefull configuration flag\n")
1274 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1275 struct zebra_if
*zif
= ifp
->info
;
1277 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1282 DEFUN (ipv6_nd_prefix
,
1284 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1285 "Interface IPv6 config commands\n"
1286 "Neighbor discovery\n"
1287 "Prefix information\n"
1289 "Valid lifetime in seconds\n"
1290 "Infinite valid lifetime\n"
1291 "Preferred lifetime in seconds\n"
1292 "Infinite preferred lifetime\n"
1293 "Set Router Address flag\n"
1294 "Do not use prefix for onlink determination\n"
1295 "Do not use prefix for autoconfiguration\n"
1296 "Do not use prefix for autoconfiguration\n"
1297 "Do not use prefix for onlink determination\n")
1300 char *prefix
= argv
[3]->arg
;
1301 int lifetimes
= (argc
> 4) && (argv
[4]->type
== RANGE_TKN
|| strmatch (argv
[4]->text
, "infinite"));
1302 int routeropts
= lifetimes
? argc
> 6 : argc
> 4;
1304 int idx_routeropts
= routeropts
? (lifetimes
? 6 : 4) : 0;
1306 char *lifetime
= NULL
, *preflifetime
= NULL
;
1307 int routeraddr
= 0, offlink
= 0, noautoconf
= 0;
1310 lifetime
= argv
[4]->type
== RANGE_TKN
? argv
[4]->arg
: argv
[4]->text
;
1311 preflifetime
= argv
[5]->type
== RANGE_TKN
? argv
[5]->arg
: argv
[5]->text
;
1315 routeraddr
= strmatch (argv
[idx_routeropts
]->text
, "router-address");
1318 offlink
= (argc
> idx_routeropts
+ 1 || strmatch (argv
[idx_routeropts
]->text
, "off-link"));
1319 noautoconf
= (argc
> idx_routeropts
+ 1 || strmatch (argv
[idx_routeropts
]->text
, "no-autoconfig"));
1324 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1325 struct zebra_if
*zebra_if
= ifp
->info
;
1327 struct rtadv_prefix rp
;
1329 ret
= str2prefix_ipv6 (prefix
, &rp
.prefix
);
1332 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
1335 apply_mask_ipv6 (&rp
.prefix
); /* RFC4861 4.6.2 */
1336 rp
.AdvOnLinkFlag
= !offlink
;
1337 rp
.AdvAutonomousFlag
= !noautoconf
;
1338 rp
.AdvRouterAddressFlag
= routeraddr
;
1339 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1340 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1344 rp
.AdvValidLifetime
= strmatch (lifetime
, "infinite") ? UINT32_MAX
: strtoll (lifetime
, NULL
, 10);
1345 rp
.AdvPreferredLifetime
= strmatch (preflifetime
, "infinite") ? UINT32_MAX
: strtoll (preflifetime
, NULL
, 10);
1346 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
)
1348 vty_out (vty
, "Invalid preferred lifetime%s", VTY_NEWLINE
);
1353 rtadv_prefix_set (zebra_if
, &rp
);
1358 DEFUN (no_ipv6_nd_prefix
,
1359 no_ipv6_nd_prefix_cmd
,
1360 "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]>]",
1362 "Interface IPv6 config commands\n"
1363 "Neighbor discovery\n"
1364 "Prefix information\n"
1366 "Valid lifetime in seconds\n"
1367 "Infinite valid lifetime\n"
1368 "Preferred lifetime in seconds\n"
1369 "Infinite preferred lifetime\n"
1370 "Set Router Address flag\n"
1371 "Do not use prefix for onlink determination\n"
1372 "Do not use prefix for autoconfiguration\n"
1373 "Do not use prefix for autoconfiguration\n"
1374 "Do not use prefix for onlink determination\n")
1376 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1377 struct zebra_if
*zebra_if
= ifp
->info
;
1379 struct rtadv_prefix rp
;
1380 char *prefix
= argv
[4]->arg
;
1382 ret
= str2prefix_ipv6 (prefix
, &rp
.prefix
);
1385 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
1388 apply_mask_ipv6 (&rp
.prefix
); /* RFC4861 4.6.2 */
1390 ret
= rtadv_prefix_reset (zebra_if
, &rp
);
1393 vty_out (vty
, "Non-existant IPv6 prefix%s", VTY_NEWLINE
);
1400 DEFUN (ipv6_nd_router_preference
,
1401 ipv6_nd_router_preference_cmd
,
1402 "ipv6 nd router-preference <high|medium|low>",
1403 "Interface IPv6 config commands\n"
1404 "Neighbor discovery\n"
1405 "Default router preference\n"
1406 "High default router preference\n"
1407 "Low default router preference\n"
1408 "Medium default router preference (default)\n")
1410 int idx_high_medium_low
= 3;
1411 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1412 struct zebra_if
*zif
= ifp
->info
;
1415 while (0 != rtadv_pref_strs
[i
])
1417 if (strncmp (argv
[idx_high_medium_low
]->arg
, rtadv_pref_strs
[i
], 1) == 0)
1419 zif
->rtadv
.DefaultPreference
= i
;
1425 return CMD_ERR_NO_MATCH
;
1428 DEFUN (no_ipv6_nd_router_preference
,
1429 no_ipv6_nd_router_preference_cmd
,
1430 "no ipv6 nd router-preference [<high|medium|low>]",
1432 "Interface IPv6 config commands\n"
1433 "Neighbor discovery\n"
1434 "Default router preference\n"
1435 "High default router preference\n"
1436 "Medium default router preference (default)\n"
1437 "Low default router preference\n")
1439 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1440 struct zebra_if
*zif
= ifp
->info
;
1442 zif
->rtadv
.DefaultPreference
= RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1449 "ipv6 nd mtu (1-65535)",
1450 "Interface IPv6 config commands\n"
1451 "Neighbor discovery\n"
1456 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1457 struct zebra_if
*zif
= ifp
->info
;
1458 VTY_GET_INTEGER_RANGE ("MTU", zif
->rtadv
.AdvLinkMTU
, argv
[idx_number
]->arg
, 1, 65535);
1462 DEFUN (no_ipv6_nd_mtu
,
1464 "no ipv6 nd mtu [(1-65535)]",
1466 "Interface IPv6 config commands\n"
1467 "Neighbor discovery\n"
1471 VTY_DECLVAR_CONTEXT (interface
, ifp
);
1472 struct zebra_if
*zif
= ifp
->info
;
1473 zif
->rtadv
.AdvLinkMTU
= 0;
1478 /* Write configuration about router advertisement. */
1480 rtadv_config_write (struct vty
*vty
, struct interface
*ifp
)
1482 struct zebra_if
*zif
;
1483 struct listnode
*node
;
1484 struct rtadv_prefix
*rprefix
;
1485 char buf
[PREFIX_STRLEN
];
1490 if (!(if_is_loopback (ifp
) ||
1491 CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_VRF_LOOPBACK
)))
1493 if (zif
->rtadv
.AdvSendAdvertisements
)
1494 vty_out (vty
, " no ipv6 nd suppress-ra%s", VTY_NEWLINE
);
1497 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1498 if (interval
% 1000)
1499 vty_out (vty
, " ipv6 nd ra-interval msec %d%s", interval
,
1502 if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1503 vty_out (vty
, " ipv6 nd ra-interval %d%s", interval
/ 1000,
1506 if (zif
->rtadv
.AdvIntervalOption
)
1507 vty_out (vty
, " ipv6 nd adv-interval-option%s", VTY_NEWLINE
);
1509 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1510 vty_out (vty
, " ipv6 nd ra-lifetime %d%s", zif
->rtadv
.AdvDefaultLifetime
,
1513 if (zif
->rtadv
.HomeAgentPreference
)
1514 vty_out (vty
, " ipv6 nd home-agent-preference %u%s",
1515 zif
->rtadv
.HomeAgentPreference
, VTY_NEWLINE
);
1517 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1518 vty_out (vty
, " ipv6 nd home-agent-lifetime %u%s",
1519 zif
->rtadv
.HomeAgentLifetime
, VTY_NEWLINE
);
1521 if (zif
->rtadv
.AdvHomeAgentFlag
)
1522 vty_out (vty
, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE
);
1524 if (zif
->rtadv
.AdvReachableTime
)
1525 vty_out (vty
, " ipv6 nd reachable-time %d%s", zif
->rtadv
.AdvReachableTime
,
1528 if (zif
->rtadv
.AdvManagedFlag
)
1529 vty_out (vty
, " ipv6 nd managed-config-flag%s", VTY_NEWLINE
);
1531 if (zif
->rtadv
.AdvOtherConfigFlag
)
1532 vty_out (vty
, " ipv6 nd other-config-flag%s", VTY_NEWLINE
);
1534 if (zif
->rtadv
.DefaultPreference
!= RTADV_PREF_MEDIUM
)
1535 vty_out (vty
, " ipv6 nd router-preference %s%s",
1536 rtadv_pref_strs
[zif
->rtadv
.DefaultPreference
],
1539 if (zif
->rtadv
.AdvLinkMTU
)
1540 vty_out (vty
, " ipv6 nd mtu %d%s", zif
->rtadv
.AdvLinkMTU
, VTY_NEWLINE
);
1542 for (ALL_LIST_ELEMENTS_RO (zif
->rtadv
.AdvPrefixList
, node
, rprefix
))
1544 vty_out (vty
, " ipv6 nd prefix %s",
1545 prefix2str (&rprefix
->prefix
, buf
, sizeof(buf
)));
1546 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
) ||
1547 (rprefix
->AdvPreferredLifetime
!= RTADV_PREFERRED_LIFETIME
))
1549 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1550 vty_out (vty
, " infinite");
1552 vty_out (vty
, " %u", rprefix
->AdvValidLifetime
);
1553 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1554 vty_out (vty
, " infinite");
1556 vty_out (vty
, " %u", rprefix
->AdvPreferredLifetime
);
1558 if (!rprefix
->AdvOnLinkFlag
)
1559 vty_out (vty
, " off-link");
1560 if (!rprefix
->AdvAutonomousFlag
)
1561 vty_out (vty
, " no-autoconfig");
1562 if (rprefix
->AdvRouterAddressFlag
)
1563 vty_out (vty
, " router-address");
1564 vty_out (vty
, "%s", VTY_NEWLINE
);
1570 rtadv_event (struct zebra_ns
*zns
, enum rtadv_event event
, int val
)
1572 struct rtadv
*rtadv
= &zns
->rtadv
;
1577 if (! rtadv
->ra_read
)
1578 rtadv
->ra_read
= thread_add_read (zebrad
.master
, rtadv_read
, zns
, val
);
1579 if (! rtadv
->ra_timer
)
1580 rtadv
->ra_timer
= thread_add_event (zebrad
.master
, rtadv_timer
,
1584 if (rtadv
->ra_timer
)
1586 thread_cancel (rtadv
->ra_timer
);
1587 rtadv
->ra_timer
= NULL
;
1591 thread_cancel (rtadv
->ra_read
);
1592 rtadv
->ra_read
= NULL
;
1596 if (! rtadv
->ra_timer
)
1597 rtadv
->ra_timer
= thread_add_timer (zebrad
.master
, rtadv_timer
, zns
,
1600 case RTADV_TIMER_MSEC
:
1601 if (! rtadv
->ra_timer
)
1602 rtadv
->ra_timer
= thread_add_timer_msec (zebrad
.master
, rtadv_timer
,
1606 if (! rtadv
->ra_read
)
1607 rtadv
->ra_read
= thread_add_read (zebrad
.master
, rtadv_read
, zns
, val
);
1616 rtadv_init (struct zebra_ns
*zns
)
1618 zns
->rtadv
.sock
= rtadv_make_socket ();
1622 rtadv_terminate (struct zebra_ns
*zns
)
1624 rtadv_event (zns
, RTADV_STOP
, 0);
1625 if (zns
->rtadv
.sock
>= 0)
1627 close (zns
->rtadv
.sock
);
1628 zns
->rtadv
.sock
= -1;
1631 zns
->rtadv
.adv_if_count
= 0;
1632 zns
->rtadv
.adv_msec_if_count
= 0;
1636 rtadv_cmd_init (void)
1638 install_element (INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1639 install_element (INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1640 install_element (INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1641 install_element (INTERFACE_NODE
, &ipv6_nd_ra_interval_msec_cmd
);
1642 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1643 install_element (INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1644 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1645 install_element (INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1646 install_element (INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1647 install_element (INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1648 install_element (INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1649 install_element (INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1650 install_element (INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1651 install_element (INTERFACE_NODE
, &ipv6_nd_homeagent_config_flag_cmd
);
1652 install_element (INTERFACE_NODE
, &no_ipv6_nd_homeagent_config_flag_cmd
);
1653 install_element (INTERFACE_NODE
, &ipv6_nd_homeagent_preference_cmd
);
1654 install_element (INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_cmd
);
1655 install_element (INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1656 install_element (INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1657 install_element (INTERFACE_NODE
, &ipv6_nd_adv_interval_config_option_cmd
);
1658 install_element (INTERFACE_NODE
, &no_ipv6_nd_adv_interval_config_option_cmd
);
1659 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_cmd
);
1660 install_element (INTERFACE_NODE
, &no_ipv6_nd_prefix_cmd
);
1661 install_element (INTERFACE_NODE
, &ipv6_nd_router_preference_cmd
);
1662 install_element (INTERFACE_NODE
, &no_ipv6_nd_router_preference_cmd
);
1663 install_element (INTERFACE_NODE
, &ipv6_nd_mtu_cmd
);
1664 install_element (INTERFACE_NODE
, &no_ipv6_nd_mtu_cmd
);
1668 if_join_all_router (int sock
, struct interface
*ifp
)
1672 struct ipv6_mreq mreq
;
1674 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1675 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1676 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1678 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
1679 (char *) &mreq
, sizeof mreq
);
1681 zlog_warn ("%s(%u): Failed to join group, socket %u error %s",
1682 ifp
->name
, ifp
->ifindex
, sock
, safe_strerror (errno
));
1684 if (IS_ZEBRA_DEBUG_EVENT
)
1685 zlog_debug ("%s(%u): Join All-Routers multicast group, socket %u",
1686 ifp
->name
, ifp
->ifindex
, sock
);
1692 if_leave_all_router (int sock
, struct interface
*ifp
)
1696 struct ipv6_mreq mreq
;
1698 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1699 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1700 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1702 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
1703 (char *) &mreq
, sizeof mreq
);
1705 zlog_warn ("%s(%u): Failed to leave group, socket %u error %s",
1706 ifp
->name
, ifp
->ifindex
, sock
,safe_strerror (errno
));
1708 if (IS_ZEBRA_DEBUG_EVENT
)
1709 zlog_debug ("%s(%u): Leave All-Routers multicast group, socket %u",
1710 ifp
->name
, ifp
->ifindex
, sock
);
1717 rtadv_init (struct zebra_ns
*zns
)
1722 rtadv_terminate (struct zebra_ns
*zns
)
1727 rtadv_cmd_init (void)
1731 #endif /* HAVE_RTADV */