]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rtadv.c
Merge pull request #10962 from louis-6wind/lfa-netlink
[mirror_frr.git] / zebra / rtadv.c
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
5 *
6 * This file is part of GNU Zebra.
7 *
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
11 * later version.
12 *
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.
17 *
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
21 */
22
23 #include <zebra.h>
24
25 #include "memory.h"
26 #include "sockopt.h"
27 #include "thread.h"
28 #include "if.h"
29 #include "stream.h"
30 #include "log.h"
31 #include "prefix.h"
32 #include "linklist.h"
33 #include "command.h"
34 #include "privs.h"
35 #include "vrf.h"
36 #include "ns.h"
37 #include "lib_errors.h"
38
39 #include "zebra/interface.h"
40 #include "zebra/rtadv.h"
41 #include "zebra/debug.h"
42 #include "zebra/rib.h"
43 #include "zebra/zapi_msg.h"
44 #include "zebra/zebra_vrf.h"
45 #include "zebra/zebra_errors.h"
46 #include "zebra/zebra_router.h"
47
48 extern struct zebra_privs_t zserv_privs;
49
50 static uint32_t interfaces_configured_for_ra_from_bgp;
51
52 #if defined(HAVE_RTADV)
53
54 #ifndef VTYSH_EXTRACT_PL
55 #include "zebra/rtadv_clippy.c"
56 #endif
57
58 DEFINE_MTYPE_STATIC(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix");
59 DEFINE_MTYPE_STATIC(ZEBRA, ADV_IF, "Advertised Interface");
60
61 #ifdef OPEN_BSD
62 #include <netinet/icmp6.h>
63 #endif
64
65 /* If RFC2133 definition is used. */
66 #ifndef IPV6_JOIN_GROUP
67 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
68 #endif
69 #ifndef IPV6_LEAVE_GROUP
70 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
71 #endif
72
73 #define ALLNODE "ff02::1"
74 #define ALLROUTER "ff02::2"
75
76 /* adv list node */
77 struct adv_if {
78 char name[INTERFACE_NAMSIZ];
79 struct adv_if_list_item list_item;
80 };
81
82 static int adv_if_cmp(const struct adv_if *a, const struct adv_if *b)
83 {
84 return if_cmp_name_func(a->name, b->name);
85 }
86
87 DECLARE_SORTLIST_UNIQ(adv_if_list, struct adv_if, list_item, adv_if_cmp);
88
89 static int rtadv_prefix_cmp(const struct rtadv_prefix *a,
90 const struct rtadv_prefix *b)
91 {
92 return prefix_cmp(&a->prefix, &b->prefix);
93 }
94
95 DECLARE_RBTREE_UNIQ(rtadv_prefixes, struct rtadv_prefix, item,
96 rtadv_prefix_cmp);
97
98 DEFINE_MTYPE_STATIC(ZEBRA, RTADV_RDNSS, "Router Advertisement RDNSS");
99 DEFINE_MTYPE_STATIC(ZEBRA, RTADV_DNSSL, "Router Advertisement DNSSL");
100
101 /* Order is intentional. Matches RFC4191. This array is also used for
102 command matching, so only modify with care. */
103 static const char *const rtadv_pref_strs[] = {
104 "medium", "high", "INVALID", "low", 0
105 };
106
107 enum rtadv_event {
108 RTADV_START,
109 RTADV_STOP,
110 RTADV_TIMER,
111 RTADV_TIMER_MSEC,
112 RTADV_READ
113 };
114
115 static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int);
116
117 static int if_join_all_router(int, struct interface *);
118 static int if_leave_all_router(int, struct interface *);
119
120 static struct zebra_vrf *rtadv_interface_get_zvrf(const struct interface *ifp)
121 {
122 /* We use the default vrf for rtadv handling except in netns */
123 if (!vrf_is_backend_netns())
124 return vrf_info_lookup(VRF_DEFAULT);
125
126 return ifp->vrf->info;
127 }
128
129 static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
130 {
131 int ret = -1;
132 struct interface *iface;
133 struct zebra_if *zif;
134
135 iface = if_lookup_by_index(*ifindex, zvrf->vrf->vrf_id);
136 if (iface && iface->info) {
137 zif = iface->info;
138 zif->ra_rcvd++;
139 ret = 0;
140 }
141 return ret;
142 }
143
144 static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
145 int buflen, struct sockaddr_in6 *from,
146 ifindex_t *ifindex, int *hoplimit)
147 {
148 int ret;
149 struct msghdr msg;
150 struct iovec iov;
151 struct cmsghdr *cmsgptr;
152 struct in6_addr dst;
153
154 char adata[1024];
155
156 /* Fill in message and iovec. */
157 memset(&msg, 0, sizeof(msg));
158 msg.msg_name = (void *)from;
159 msg.msg_namelen = sizeof(struct sockaddr_in6);
160 msg.msg_iov = &iov;
161 msg.msg_iovlen = 1;
162 msg.msg_control = (void *)adata;
163 msg.msg_controllen = sizeof(adata);
164 iov.iov_base = buf;
165 iov.iov_len = buflen;
166
167 /* If recvmsg fail return minus value. */
168 ret = recvmsg(sock, &msg, 0);
169 if (ret < 0)
170 return ret;
171
172 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
173 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
174 /* I want interface index which this packet comes from. */
175 if (cmsgptr->cmsg_level == IPPROTO_IPV6
176 && cmsgptr->cmsg_type == IPV6_PKTINFO) {
177 struct in6_pktinfo *ptr;
178
179 ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
180 *ifindex = ptr->ipi6_ifindex;
181 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
182 }
183
184 /* Incoming packet's hop limit. */
185 if (cmsgptr->cmsg_level == IPPROTO_IPV6
186 && cmsgptr->cmsg_type == IPV6_HOPLIMIT) {
187 int *hoptr = (int *)CMSG_DATA(cmsgptr);
188 *hoplimit = *hoptr;
189 }
190 }
191
192 rtadv_increment_received(zvrf, ifindex);
193 return ret;
194 }
195
196 #define RTADV_MSG_SIZE 4096
197
198 /* Send router advertisement packet. */
199 static void rtadv_send_packet(int sock, struct interface *ifp,
200 enum ipv6_nd_suppress_ra_status stop)
201 {
202 struct msghdr msg;
203 struct iovec iov;
204 struct cmsghdr *cmsgptr;
205 struct in6_pktinfo *pkt;
206 struct sockaddr_in6 addr;
207 static void *adata = NULL;
208 unsigned char buf[RTADV_MSG_SIZE];
209 struct nd_router_advert *rtadv;
210 int ret;
211 int len = 0;
212 struct zebra_if *zif;
213 struct rtadv_prefix *rprefix;
214 uint8_t all_nodes_addr[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
215 0, 0, 0, 0, 0, 0, 0, 1};
216 struct listnode *node;
217 uint16_t pkt_RouterLifetime;
218
219 /*
220 * Allocate control message bufffer. This is dynamic because
221 * CMSG_SPACE is not guaranteed not to call a function. Note that
222 * the size will be different on different architectures due to
223 * differing alignment rules.
224 */
225 if (adata == NULL) {
226 /* XXX Free on shutdown. */
227 adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
228
229 if (adata == NULL) {
230 zlog_debug(
231 "rtadv_send_packet: can't malloc control data");
232 exit(-1);
233 }
234 }
235
236 /* Logging of packet. */
237 if (IS_ZEBRA_DEBUG_PACKET)
238 zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp->name,
239 ifp->vrf->name, ifp->ifindex, sock);
240
241 /* Fill in sockaddr_in6. */
242 memset(&addr, 0, sizeof(struct sockaddr_in6));
243 addr.sin6_family = AF_INET6;
244 #ifdef SIN6_LEN
245 addr.sin6_len = sizeof(struct sockaddr_in6);
246 #endif /* SIN6_LEN */
247 addr.sin6_port = htons(IPPROTO_ICMPV6);
248 IPV6_ADDR_COPY(&addr.sin6_addr, all_nodes_addr);
249
250 /* Fetch interface information. */
251 zif = ifp->info;
252
253 /* Make router advertisement message. */
254 rtadv = (struct nd_router_advert *)buf;
255
256 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
257 rtadv->nd_ra_code = 0;
258 rtadv->nd_ra_cksum = 0;
259
260 rtadv->nd_ra_curhoplimit = zif->rtadv.AdvCurHopLimit;
261
262 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
263 rtadv->nd_ra_flags_reserved = zif->rtadv.AdvDefaultLifetime == 0
264 ? 0
265 : zif->rtadv.DefaultPreference;
266 rtadv->nd_ra_flags_reserved <<= 3;
267
268 if (zif->rtadv.AdvManagedFlag)
269 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
270 if (zif->rtadv.AdvOtherConfigFlag)
271 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
272 if (zif->rtadv.AdvHomeAgentFlag)
273 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
274 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
275 * AdvDefaultLifetime is by default based on the value of
276 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
277 * field of Router Advertisements. Given that this field is expressed
278 * in seconds, a small MaxRtrAdvInterval value can result in a zero
279 * value for this field. To prevent this, routers SHOULD keep
280 * AdvDefaultLifetime in at least one second, even if the use of
281 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
282 pkt_RouterLifetime =
283 zif->rtadv.AdvDefaultLifetime != -1
284 ? zif->rtadv.AdvDefaultLifetime
285 : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
286
287 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
288 rtadv->nd_ra_router_lifetime =
289 (stop == RA_SUPPRESS) ? htons(0) : htons(pkt_RouterLifetime);
290 rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime);
291 rtadv->nd_ra_retransmit = htonl(zif->rtadv.AdvRetransTimer);
292
293 len = sizeof(struct nd_router_advert);
294
295 /* If both the Home Agent Preference and Home Agent Lifetime are set to
296 * their default values specified above, this option SHOULD NOT be
297 * included in the Router Advertisement messages sent by this home
298 * agent. -- RFC6275, 7.4 */
299 if (zif->rtadv.AdvHomeAgentFlag
300 && (zif->rtadv.HomeAgentPreference
301 || zif->rtadv.HomeAgentLifetime != -1)) {
302 struct nd_opt_homeagent_info *ndopt_hai =
303 (struct nd_opt_homeagent_info *)(buf + len);
304 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
305 ndopt_hai->nd_opt_hai_len = 1;
306 ndopt_hai->nd_opt_hai_reserved = 0;
307 ndopt_hai->nd_opt_hai_preference =
308 htons(zif->rtadv.HomeAgentPreference);
309 /* 16-bit unsigned integer. The lifetime associated with the
310 * home
311 * agent in units of seconds. The default value is the same as
312 * the
313 * Router Lifetime, as specified in the main body of the Router
314 * Advertisement. The maximum value corresponds to 18.2 hours.
315 * A
316 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
317 ndopt_hai->nd_opt_hai_lifetime =
318 htons(zif->rtadv.HomeAgentLifetime != -1
319 ? zif->rtadv.HomeAgentLifetime
320 : MAX(1, pkt_RouterLifetime) /* 0 is OK
321 for RL,
322 but not
323 for HAL*/
324 );
325 len += sizeof(struct nd_opt_homeagent_info);
326 }
327
328 if (zif->rtadv.AdvIntervalOption) {
329 struct nd_opt_adv_interval *ndopt_adv =
330 (struct nd_opt_adv_interval *)(buf + len);
331 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
332 ndopt_adv->nd_opt_ai_len = 1;
333 ndopt_adv->nd_opt_ai_reserved = 0;
334 ndopt_adv->nd_opt_ai_interval =
335 htonl(zif->rtadv.MaxRtrAdvInterval);
336 len += sizeof(struct nd_opt_adv_interval);
337 }
338
339 /* Fill in prefix. */
340 frr_each (rtadv_prefixes, zif->rtadv.prefixes, rprefix) {
341 struct nd_opt_prefix_info *pinfo;
342
343 pinfo = (struct nd_opt_prefix_info *)(buf + len);
344
345 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
346 pinfo->nd_opt_pi_len = 4;
347 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
348
349 pinfo->nd_opt_pi_flags_reserved = 0;
350 if (rprefix->AdvOnLinkFlag)
351 pinfo->nd_opt_pi_flags_reserved |=
352 ND_OPT_PI_FLAG_ONLINK;
353 if (rprefix->AdvAutonomousFlag)
354 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
355 if (rprefix->AdvRouterAddressFlag)
356 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
357
358 pinfo->nd_opt_pi_valid_time = htonl(rprefix->AdvValidLifetime);
359 pinfo->nd_opt_pi_preferred_time =
360 htonl(rprefix->AdvPreferredLifetime);
361 pinfo->nd_opt_pi_reserved2 = 0;
362
363 IPV6_ADDR_COPY(&pinfo->nd_opt_pi_prefix,
364 &rprefix->prefix.prefix);
365
366 len += sizeof(struct nd_opt_prefix_info);
367 }
368
369 /* Hardware address. */
370 if (ifp->hw_addr_len != 0) {
371 buf[len++] = ND_OPT_SOURCE_LINKADDR;
372
373 /* Option length should be rounded up to next octet if
374 the link address does not end on an octet boundary. */
375 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
376
377 memcpy(buf + len, ifp->hw_addr, ifp->hw_addr_len);
378 len += ifp->hw_addr_len;
379
380 /* Pad option to end on an octet boundary. */
381 memset(buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
382 len += -(ifp->hw_addr_len + 2) & 0x7;
383 }
384
385 /* MTU */
386 if (zif->rtadv.AdvLinkMTU) {
387 struct nd_opt_mtu *opt = (struct nd_opt_mtu *)(buf + len);
388 opt->nd_opt_mtu_type = ND_OPT_MTU;
389 opt->nd_opt_mtu_len = 1;
390 opt->nd_opt_mtu_reserved = 0;
391 opt->nd_opt_mtu_mtu = htonl(zif->rtadv.AdvLinkMTU);
392 len += sizeof(struct nd_opt_mtu);
393 }
394
395 /*
396 * There is no limit on the number of configurable recursive DNS
397 * servers or search list entries. We don't want the RA message
398 * to exceed the link's MTU (risking fragmentation) or even
399 * blow the stack buffer allocated for it.
400 */
401 size_t max_len = MIN(ifp->mtu6 - 40, sizeof(buf));
402
403 /* Recursive DNS servers */
404 struct rtadv_rdnss *rdnss;
405
406 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
407 size_t opt_len =
408 sizeof(struct nd_opt_rdnss) + sizeof(struct in6_addr);
409
410 if (len + opt_len > max_len) {
411 zlog_warn(
412 "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
413 ifp->name, ifp->vrf->name, ifp->ifindex);
414 goto no_more_opts;
415 }
416 struct nd_opt_rdnss *opt = (struct nd_opt_rdnss *)(buf + len);
417
418 opt->nd_opt_rdnss_type = ND_OPT_RDNSS;
419 opt->nd_opt_rdnss_len = opt_len / 8;
420 opt->nd_opt_rdnss_reserved = 0;
421 opt->nd_opt_rdnss_lifetime = htonl(
422 rdnss->lifetime_set
423 ? rdnss->lifetime
424 : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
425
426 len += sizeof(struct nd_opt_rdnss);
427
428 IPV6_ADDR_COPY(buf + len, &rdnss->addr);
429 len += sizeof(struct in6_addr);
430 }
431
432 /* DNS search list */
433 struct rtadv_dnssl *dnssl;
434
435 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
436 size_t opt_len = sizeof(struct nd_opt_dnssl)
437 + ((dnssl->encoded_len + 7) & ~7);
438
439 if (len + opt_len > max_len) {
440 zlog_warn(
441 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
442 ifp->name, ifp->ifindex);
443 goto no_more_opts;
444 }
445 struct nd_opt_dnssl *opt = (struct nd_opt_dnssl *)(buf + len);
446
447 opt->nd_opt_dnssl_type = ND_OPT_DNSSL;
448 opt->nd_opt_dnssl_len = opt_len / 8;
449 opt->nd_opt_dnssl_reserved = 0;
450 opt->nd_opt_dnssl_lifetime = htonl(
451 dnssl->lifetime_set
452 ? dnssl->lifetime
453 : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
454
455 len += sizeof(struct nd_opt_dnssl);
456
457 memcpy(buf + len, dnssl->encoded_name, dnssl->encoded_len);
458 len += dnssl->encoded_len;
459
460 /* Zero-pad to 8-octet boundary */
461 while (len % 8)
462 buf[len++] = '\0';
463 }
464
465 no_more_opts:
466
467 msg.msg_name = (void *)&addr;
468 msg.msg_namelen = sizeof(struct sockaddr_in6);
469 msg.msg_iov = &iov;
470 msg.msg_iovlen = 1;
471 msg.msg_control = (void *)adata;
472 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
473 msg.msg_flags = 0;
474 iov.iov_base = buf;
475 iov.iov_len = len;
476
477 cmsgptr = CMSG_FIRSTHDR(&msg);
478 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
479 cmsgptr->cmsg_level = IPPROTO_IPV6;
480 cmsgptr->cmsg_type = IPV6_PKTINFO;
481
482 pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
483 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
484 pkt->ipi6_ifindex = ifp->ifindex;
485
486 ret = sendmsg(sock, &msg, 0);
487 if (ret < 0) {
488 flog_err_sys(EC_LIB_SOCKET,
489 "%s(%u): Tx RA failed, socket %u error %d (%s)",
490 ifp->name, ifp->ifindex, sock, errno,
491 safe_strerror(errno));
492 } else
493 zif->ra_sent++;
494 }
495
496 static void rtadv_timer(struct thread *thread)
497 {
498 struct zebra_vrf *zvrf = THREAD_ARG(thread);
499 struct vrf *vrf;
500 struct interface *ifp;
501 struct zebra_if *zif;
502 int period;
503
504 zvrf->rtadv.ra_timer = NULL;
505 if (adv_if_list_count(&zvrf->rtadv.adv_msec_if) == 0) {
506 period = 1000; /* 1 s */
507 rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
508 } else {
509 period = 10; /* 10 ms */
510 rtadv_event(zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
511 }
512
513 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
514 FOR_ALL_INTERFACES (vrf, ifp) {
515 if (if_is_loopback(ifp) || !if_is_operative(ifp) ||
516 IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) ||
517 !connected_get_linklocal(ifp) ||
518 (vrf_is_backend_netns() &&
519 ifp->vrf->vrf_id != zvrf->vrf->vrf_id))
520 continue;
521
522 zif = ifp->info;
523
524 if (zif->rtadv.AdvSendAdvertisements) {
525 if (zif->rtadv.inFastRexmit
526 && zif->rtadv.UseFastRexmit) {
527 /* We assume we fast rexmit every sec so
528 * no
529 * additional vars */
530 if (--zif->rtadv.NumFastReXmitsRemain
531 <= 0)
532 zif->rtadv.inFastRexmit = 0;
533
534 if (IS_ZEBRA_DEBUG_SEND)
535 zlog_debug(
536 "Fast RA Rexmit on interface %s(%s:%u)",
537 ifp->name,
538 ifp->vrf->name,
539 ifp->ifindex);
540
541 rtadv_send_packet(zvrf->rtadv.sock, ifp,
542 RA_ENABLE);
543 } else {
544 zif->rtadv.AdvIntervalTimer -= period;
545 if (zif->rtadv.AdvIntervalTimer <= 0) {
546 /* FIXME: using
547 MaxRtrAdvInterval each
548 time isn't what section
549 6.2.4 of RFC4861 tells to do.
550 */
551 zif->rtadv.AdvIntervalTimer =
552 zif->rtadv
553 .MaxRtrAdvInterval;
554 rtadv_send_packet(
555 zvrf->rtadv.sock, ifp,
556 RA_ENABLE);
557 }
558 }
559 }
560 }
561 }
562
563 static void rtadv_process_solicit(struct interface *ifp)
564 {
565 struct zebra_vrf *zvrf;
566 struct zebra_if *zif;
567
568 zvrf = rtadv_interface_get_zvrf(ifp);
569 assert(zvrf);
570 zif = ifp->info;
571
572 /*
573 * If FastRetransmit is enabled, send the RA immediately.
574 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
575 * (3 seconds) since the last RA was sent, send it now and reset
576 * the timer to start at the max (configured) again.
577 * If not enabled and it is less than 3 seconds since the last
578 * RA packet was sent, set the timer for 3 seconds so the next
579 * one will be sent with a minimum of 3 seconds between RAs.
580 * RFC4861 sec 6.2.6
581 */
582 if ((zif->rtadv.UseFastRexmit)
583 || (zif->rtadv.AdvIntervalTimer <=
584 (zif->rtadv.MaxRtrAdvInterval - MIN_DELAY_BETWEEN_RAS))) {
585 rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_ENABLE);
586 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
587 } else
588 zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS;
589 }
590
591 /*
592 * This function processes optional attributes off of
593 * end of a RA packet received. At this point in
594 * time we only care about this in one situation
595 * which is when a interface does not have a LL
596 * v6 address. We still need to be able to install
597 * the mac address for v4 to v6 resolution
598 */
599 static void rtadv_process_optional(uint8_t *optional, unsigned int len,
600 struct interface *ifp,
601 struct sockaddr_in6 *addr)
602 {
603 char *mac;
604
605 while (len > 0) {
606 struct nd_opt_hdr *opt_hdr = (struct nd_opt_hdr *)optional;
607
608 switch(opt_hdr->nd_opt_type) {
609 case ND_OPT_SOURCE_LINKADDR:
610 mac = (char *)(optional+2);
611 if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac,
612 &addr->sin6_addr, 1);
613 break;
614 default:
615 break;
616 }
617
618 len -= 8 * opt_hdr->nd_opt_len;
619 optional += 8 * opt_hdr->nd_opt_len;
620 }
621 }
622
623 static void rtadv_process_advert(uint8_t *msg, unsigned int len,
624 struct interface *ifp,
625 struct sockaddr_in6 *addr)
626 {
627 struct nd_router_advert *radvert;
628 char addr_str[INET6_ADDRSTRLEN];
629 struct zebra_if *zif;
630 struct prefix p;
631
632 zif = ifp->info;
633
634 inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
635
636 if (len < sizeof(struct nd_router_advert)) {
637 if (IS_ZEBRA_DEBUG_PACKET)
638 zlog_debug(
639 "%s(%s:%u): Rx RA with invalid length %d from %s",
640 ifp->name, ifp->vrf->name, ifp->ifindex, len,
641 addr_str);
642 return;
643 }
644
645 if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
646 rtadv_process_optional(msg + sizeof(struct nd_router_advert),
647 len - sizeof(struct nd_router_advert),
648 ifp, addr);
649 if (IS_ZEBRA_DEBUG_PACKET)
650 zlog_debug(
651 "%s(%s:%u): Rx RA with non-linklocal source address from %s",
652 ifp->name, ifp->vrf->name, ifp->ifindex,
653 addr_str);
654 return;
655 }
656
657 radvert = (struct nd_router_advert *)msg;
658
659 #define SIXHOUR2USEC (int64_t)6 * 60 * 60 * 1000000
660
661 if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) &&
662 (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit) &&
663 (monotime_since(&zif->rtadv.lastadvcurhoplimit, NULL) >
664 SIXHOUR2USEC ||
665 zif->rtadv.lastadvcurhoplimit.tv_sec == 0)) {
666 flog_warn(
667 EC_ZEBRA_RA_PARAM_MISMATCH,
668 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
669 ifp->name, ifp->ifindex, addr_str);
670 monotime(&zif->rtadv.lastadvcurhoplimit);
671 }
672
673 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) &&
674 !zif->rtadv.AdvManagedFlag &&
675 (monotime_since(&zif->rtadv.lastadvmanagedflag, NULL) >
676 SIXHOUR2USEC ||
677 zif->rtadv.lastadvmanagedflag.tv_sec == 0)) {
678 flog_warn(
679 EC_ZEBRA_RA_PARAM_MISMATCH,
680 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
681 ifp->name, ifp->ifindex, addr_str);
682 monotime(&zif->rtadv.lastadvmanagedflag);
683 }
684
685 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) &&
686 !zif->rtadv.AdvOtherConfigFlag &&
687 (monotime_since(&zif->rtadv.lastadvotherconfigflag, NULL) >
688 SIXHOUR2USEC ||
689 zif->rtadv.lastadvotherconfigflag.tv_sec == 0)) {
690 flog_warn(
691 EC_ZEBRA_RA_PARAM_MISMATCH,
692 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
693 ifp->name, ifp->ifindex, addr_str);
694 monotime(&zif->rtadv.lastadvotherconfigflag);
695 }
696
697 if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) &&
698 (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime) &&
699 (monotime_since(&zif->rtadv.lastadvreachabletime, NULL) >
700 SIXHOUR2USEC ||
701 zif->rtadv.lastadvreachabletime.tv_sec == 0)) {
702 flog_warn(
703 EC_ZEBRA_RA_PARAM_MISMATCH,
704 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
705 ifp->name, ifp->ifindex, addr_str);
706 monotime(&zif->rtadv.lastadvreachabletime);
707 }
708
709 if ((ntohl(radvert->nd_ra_retransmit) !=
710 (unsigned int)zif->rtadv.AdvRetransTimer) &&
711 (monotime_since(&zif->rtadv.lastadvretranstimer, NULL) >
712 SIXHOUR2USEC ||
713 zif->rtadv.lastadvretranstimer.tv_sec == 0)) {
714 flog_warn(
715 EC_ZEBRA_RA_PARAM_MISMATCH,
716 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
717 ifp->name, ifp->ifindex, addr_str);
718 monotime(&zif->rtadv.lastadvretranstimer);
719 }
720
721 /* Create entry for neighbor if not known. */
722 p.family = AF_INET6;
723 IPV6_ADDR_COPY(&p.u.prefix6, &addr->sin6_addr);
724 p.prefixlen = IPV6_MAX_BITLEN;
725
726 if (!nbr_connected_check(ifp, &p))
727 nbr_connected_add_ipv6(ifp, &addr->sin6_addr);
728 }
729
730
731 static void rtadv_process_packet(uint8_t *buf, unsigned int len,
732 ifindex_t ifindex, int hoplimit,
733 struct sockaddr_in6 *from,
734 struct zebra_vrf *zvrf)
735 {
736 struct icmp6_hdr *icmph;
737 struct interface *ifp;
738 struct zebra_if *zif;
739 char addr_str[INET6_ADDRSTRLEN];
740
741 inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
742
743 /* Interface search. */
744 ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
745 if (ifp == NULL) {
746 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
747 "RA/RS received on unknown IF %u from %s", ifindex,
748 addr_str);
749 return;
750 }
751
752 if (IS_ZEBRA_DEBUG_PACKET)
753 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp->name,
754 ifp->vrf->name, ifp->ifindex, len, addr_str);
755
756 if (if_is_loopback(ifp))
757 return;
758
759 /* Check interface configuration. */
760 zif = ifp->info;
761 if (!zif->rtadv.AdvSendAdvertisements)
762 return;
763
764 /* ICMP message length check. */
765 if (len < sizeof(struct icmp6_hdr)) {
766 zlog_debug(
767 "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
768 ifp->name, ifp->vrf->name, ifp->ifindex, len);
769 return;
770 }
771
772 icmph = (struct icmp6_hdr *)buf;
773
774 /* ICMP message type check. */
775 if (icmph->icmp6_type != ND_ROUTER_SOLICIT
776 && icmph->icmp6_type != ND_ROUTER_ADVERT) {
777 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
778 ifp->name, ifp->vrf->name, ifp->ifindex,
779 icmph->icmp6_type);
780 return;
781 }
782
783 /* Hoplimit check. */
784 if (hoplimit >= 0 && hoplimit != 255) {
785 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp->name,
786 ifp->vrf->name, ifp->ifindex, hoplimit);
787 return;
788 }
789
790 /* Check ICMP message type. */
791 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
792 rtadv_process_solicit(ifp);
793 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
794 rtadv_process_advert(buf, len, ifp, from);
795
796 return;
797 }
798
799 static void rtadv_read(struct thread *thread)
800 {
801 int sock;
802 int len;
803 uint8_t buf[RTADV_MSG_SIZE];
804 struct sockaddr_in6 from;
805 ifindex_t ifindex = 0;
806 int hoplimit = -1;
807 struct zebra_vrf *zvrf = THREAD_ARG(thread);
808
809 sock = THREAD_FD(thread);
810 zvrf->rtadv.ra_read = NULL;
811
812 /* Register myself. */
813 rtadv_event(zvrf, RTADV_READ, 0);
814
815 len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
816 &hoplimit);
817
818 if (len < 0) {
819 flog_err_sys(EC_LIB_SOCKET,
820 "RA/RS recv failed, socket %u error %s", sock,
821 safe_strerror(errno));
822 return;
823 }
824
825 rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf);
826 }
827
828 static int rtadv_make_socket(ns_id_t ns_id)
829 {
830 int sock = -1;
831 int ret = 0;
832 struct icmp6_filter filter;
833
834 frr_with_privs(&zserv_privs) {
835
836 sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
837
838 }
839
840 if (sock < 0) {
841 return -1;
842 }
843
844 ret = setsockopt_ipv6_pktinfo(sock, 1);
845 if (ret < 0) {
846 close(sock);
847 return ret;
848 }
849 ret = setsockopt_ipv6_multicast_loop(sock, 0);
850 if (ret < 0) {
851 close(sock);
852 return ret;
853 }
854 ret = setsockopt_ipv6_unicast_hops(sock, 255);
855 if (ret < 0) {
856 close(sock);
857 return ret;
858 }
859 ret = setsockopt_ipv6_multicast_hops(sock, 255);
860 if (ret < 0) {
861 close(sock);
862 return ret;
863 }
864 ret = setsockopt_ipv6_hoplimit(sock, 1);
865 if (ret < 0) {
866 close(sock);
867 return ret;
868 }
869
870 ICMP6_FILTER_SETBLOCKALL(&filter);
871 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
872 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
873
874 ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
875 sizeof(struct icmp6_filter));
876 if (ret < 0) {
877 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno));
878 close(sock);
879 return ret;
880 }
881
882 return sock;
883 }
884
885 static struct adv_if *adv_if_new(const char *name)
886 {
887 struct adv_if *new;
888
889 new = XCALLOC(MTYPE_ADV_IF, sizeof(struct adv_if));
890
891 strlcpy(new->name, name, sizeof(new->name));
892
893 return new;
894 }
895
896 static void adv_if_free(struct adv_if *adv_if)
897 {
898 XFREE(MTYPE_ADV_IF, adv_if);
899 }
900
901 static bool adv_if_is_empty_internal(const struct adv_if_list_head *adv_if_head)
902 {
903 return adv_if_list_count(adv_if_head) ? false : true;
904 }
905
906 static struct adv_if *adv_if_add_internal(struct adv_if_list_head *adv_if_head,
907 const char *name)
908 {
909 struct adv_if adv_if_lookup = {};
910 struct adv_if *adv_if = NULL;
911
912 strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
913 adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
914
915 if (adv_if != NULL)
916 return adv_if;
917
918 adv_if = adv_if_new(adv_if_lookup.name);
919 adv_if_list_add(adv_if_head, adv_if);
920
921 return NULL;
922 }
923
924 static struct adv_if *adv_if_del_internal(struct adv_if_list_head *adv_if_head,
925 const char *name)
926 {
927 struct adv_if adv_if_lookup = {};
928 struct adv_if *adv_if = NULL;
929
930 strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
931 adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
932
933 if (adv_if == NULL)
934 return NULL;
935
936 adv_if_list_del(adv_if_head, adv_if);
937
938 return adv_if;
939 }
940
941 static void adv_if_clean_internal(struct adv_if_list_head *adv_if_head)
942 {
943 struct adv_if *node = NULL;
944
945 if (!adv_if_is_empty_internal(adv_if_head)) {
946 frr_each_safe (adv_if_list, adv_if_head, node) {
947 adv_if_list_del(adv_if_head, node);
948 adv_if_free(node);
949 }
950 }
951
952 adv_if_list_fini(adv_if_head);
953 }
954
955
956 /*
957 * Add to list. On Success, return NULL, otherwise return already existing
958 * adv_if.
959 */
960 static struct adv_if *adv_if_add(struct zebra_vrf *zvrf, const char *name)
961 {
962 struct adv_if *adv_if = NULL;
963
964 adv_if = adv_if_add_internal(&zvrf->rtadv.adv_if, name);
965
966 if (adv_if != NULL)
967 return adv_if;
968
969 if (IS_ZEBRA_DEBUG_EVENT) {
970 struct vrf *vrf = zvrf->vrf;
971
972 zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
973 VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
974 adv_if_list_count(&zvrf->rtadv.adv_if));
975 }
976
977 return NULL;
978 }
979
980 /*
981 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
982 * frees.
983 */
984 static struct adv_if *adv_if_del(struct zebra_vrf *zvrf, const char *name)
985 {
986 struct adv_if *adv_if = NULL;
987
988 adv_if = adv_if_del_internal(&zvrf->rtadv.adv_if, name);
989
990 if (adv_if == NULL)
991 return NULL;
992
993 if (IS_ZEBRA_DEBUG_EVENT) {
994 struct vrf *vrf = zvrf->vrf;
995
996 zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
997 VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
998 adv_if_list_count(&zvrf->rtadv.adv_if));
999 }
1000
1001 return adv_if;
1002 }
1003
1004 /*
1005 * Add to list. On Success, return NULL, otherwise return already existing
1006 * adv_if.
1007 */
1008 static struct adv_if *adv_msec_if_add(struct zebra_vrf *zvrf, const char *name)
1009 {
1010 struct adv_if *adv_if = NULL;
1011
1012 adv_if = adv_if_add_internal(&zvrf->rtadv.adv_msec_if, name);
1013
1014 if (adv_if != NULL)
1015 return adv_if;
1016
1017 if (IS_ZEBRA_DEBUG_EVENT) {
1018 struct vrf *vrf = zvrf->vrf;
1019
1020 zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
1021 VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
1022 adv_if_list_count(&zvrf->rtadv.adv_msec_if));
1023 }
1024
1025 return NULL;
1026 }
1027
1028 /*
1029 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1030 * frees.
1031 */
1032 static struct adv_if *adv_msec_if_del(struct zebra_vrf *zvrf, const char *name)
1033 {
1034 struct adv_if *adv_if = NULL;
1035
1036 adv_if = adv_if_del_internal(&zvrf->rtadv.adv_msec_if, name);
1037
1038 if (adv_if == NULL)
1039 return NULL;
1040
1041 if (IS_ZEBRA_DEBUG_EVENT) {
1042 struct vrf *vrf = zvrf->vrf;
1043
1044 zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
1045 VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
1046 adv_if_list_count(&zvrf->rtadv.adv_msec_if));
1047 }
1048
1049 return adv_if;
1050 }
1051
1052 /* Clean adv_if list, called on vrf terminate */
1053 static void adv_if_clean(struct zebra_vrf *zvrf)
1054 {
1055 if (IS_ZEBRA_DEBUG_EVENT) {
1056 struct vrf *vrf = zvrf->vrf;
1057
1058 zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
1059 VRF_LOGNAME(vrf), zvrf_id(zvrf),
1060 adv_if_list_count(&zvrf->rtadv.adv_if));
1061 }
1062
1063 adv_if_clean_internal(&zvrf->rtadv.adv_if);
1064 }
1065
1066 /* Clean adv_msec_if list, called on vrf terminate */
1067 static void adv_msec_if_clean(struct zebra_vrf *zvrf)
1068 {
1069 if (IS_ZEBRA_DEBUG_EVENT) {
1070 struct vrf *vrf = zvrf->vrf;
1071
1072 zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
1073 VRF_LOGNAME(vrf), zvrf_id(zvrf),
1074 adv_if_list_count(&zvrf->rtadv.adv_msec_if));
1075 }
1076
1077 adv_if_clean_internal(&zvrf->rtadv.adv_msec_if);
1078 }
1079
1080 static struct rtadv_prefix *rtadv_prefix_new(void)
1081 {
1082 return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix));
1083 }
1084
1085 static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix)
1086 {
1087 XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix);
1088 }
1089
1090 static struct rtadv_prefix *rtadv_prefix_get(struct rtadv_prefixes_head *list,
1091 struct prefix_ipv6 *p)
1092 {
1093 struct rtadv_prefix *rprefix, ref;
1094
1095 ref.prefix = *p;
1096
1097 rprefix = rtadv_prefixes_find(list, &ref);
1098 if (rprefix)
1099 return rprefix;
1100
1101 rprefix = rtadv_prefix_new();
1102 memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6));
1103 rtadv_prefixes_add(list, rprefix);
1104
1105 return rprefix;
1106 }
1107
1108 static void rtadv_prefix_set_defaults(struct rtadv_prefix *rp)
1109 {
1110 rp->AdvAutonomousFlag = 1;
1111 rp->AdvOnLinkFlag = 1;
1112 rp->AdvRouterAddressFlag = 0;
1113 rp->AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1114 rp->AdvValidLifetime = RTADV_VALID_LIFETIME;
1115 }
1116
1117 static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
1118 {
1119 struct rtadv_prefix *rprefix;
1120
1121 rprefix = rtadv_prefix_get(zif->rtadv.prefixes, &rp->prefix);
1122
1123 /*
1124 * Set parameters based on where the prefix is created.
1125 * If auto-created based on kernel address addition, set the
1126 * default values. If created from a manual "ipv6 nd prefix"
1127 * command, take the parameters from the manual command. Note
1128 * that if the manual command exists, the default values will
1129 * not overwrite the manual values.
1130 */
1131 if (rp->AdvPrefixCreate == PREFIX_SRC_MANUAL) {
1132 if (rprefix->AdvPrefixCreate == PREFIX_SRC_AUTO)
1133 rprefix->AdvPrefixCreate = PREFIX_SRC_BOTH;
1134 else
1135 rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
1136
1137 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
1138 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
1139 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
1140 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
1141 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
1142 } else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
1143 if (rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
1144 rprefix->AdvPrefixCreate = PREFIX_SRC_BOTH;
1145 else {
1146 rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
1147 rtadv_prefix_set_defaults(rprefix);
1148 }
1149 }
1150 }
1151
1152 static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
1153 {
1154 struct rtadv_prefix *rprefix;
1155
1156 rprefix = rtadv_prefixes_find(zif->rtadv.prefixes, rp);
1157 if (rprefix != NULL) {
1158
1159 /*
1160 * When deleting an address from the list, need to take care
1161 * it wasn't defined both automatically via kernel
1162 * address addition as well as manually by vtysh cli. If both,
1163 * we don't actually delete but may change the parameters
1164 * back to default if a manually defined entry is deleted.
1165 */
1166 if (rp->AdvPrefixCreate == PREFIX_SRC_MANUAL) {
1167 if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
1168 rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
1169 rtadv_prefix_set_defaults(rprefix);
1170 return 1;
1171 }
1172 } else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
1173 if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
1174 rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
1175 return 1;
1176 }
1177 }
1178
1179 rtadv_prefixes_del(zif->rtadv.prefixes, rprefix);
1180 rtadv_prefix_free(rprefix);
1181 return 1;
1182 } else
1183 return 0;
1184 }
1185
1186 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
1187 void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p)
1188 {
1189 struct rtadv_prefix rp;
1190
1191 rp.prefix = *p;
1192 apply_mask_ipv6(&rp.prefix);
1193 rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
1194 rtadv_prefix_set(zif, &rp);
1195 }
1196
1197 /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
1198 void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
1199 {
1200 struct rtadv_prefix rp;
1201
1202 rp.prefix = *((struct prefix_ipv6 *)p);
1203 apply_mask_ipv6(&rp.prefix);
1204 rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
1205 rtadv_prefix_reset(zif, &rp);
1206 }
1207
1208 static void rtadv_start_interface_events(struct zebra_vrf *zvrf,
1209 struct zebra_if *zif)
1210 {
1211 struct adv_if *adv_if = NULL;
1212
1213 if (zif->ifp->ifindex == IFINDEX_INTERNAL) {
1214 if (IS_ZEBRA_DEBUG_EVENT)
1215 zlog_debug(
1216 "%s(%s) has not configured an ifindex yet, delaying until we have one",
1217 zif->ifp->name, zvrf->vrf->name);
1218 return;
1219 }
1220
1221 adv_if = adv_if_add(zvrf, zif->ifp->name);
1222 if (adv_if != NULL)
1223 return; /* Already added */
1224
1225 if_join_all_router(zvrf->rtadv.sock, zif->ifp);
1226
1227 if (adv_if_list_count(&zvrf->rtadv.adv_if) == 1)
1228 rtadv_event(zvrf, RTADV_START, 0);
1229 }
1230
1231 static void ipv6_nd_suppress_ra_set(struct interface *ifp,
1232 enum ipv6_nd_suppress_ra_status status)
1233 {
1234 struct zebra_if *zif;
1235 struct zebra_vrf *zvrf;
1236 struct adv_if *adv_if = NULL;
1237
1238 zif = ifp->info;
1239
1240 zvrf = rtadv_interface_get_zvrf(ifp);
1241
1242 if (status == RA_SUPPRESS) {
1243 /* RA is currently enabled */
1244 if (zif->rtadv.AdvSendAdvertisements) {
1245 rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
1246 zif->rtadv.AdvSendAdvertisements = 0;
1247 zif->rtadv.AdvIntervalTimer = 0;
1248
1249 adv_if = adv_if_del(zvrf, ifp->name);
1250 if (adv_if == NULL)
1251 return; /* Nothing to delete */
1252
1253 adv_if_free(adv_if);
1254
1255 if_leave_all_router(zvrf->rtadv.sock, ifp);
1256
1257 if (adv_if_list_count(&zvrf->rtadv.adv_if) == 0)
1258 rtadv_event(zvrf, RTADV_STOP, 0);
1259 }
1260 } else {
1261 if (!zif->rtadv.AdvSendAdvertisements) {
1262 zif->rtadv.AdvSendAdvertisements = 1;
1263 zif->rtadv.AdvIntervalTimer = 0;
1264 if ((zif->rtadv.MaxRtrAdvInterval >= 1000)
1265 && zif->rtadv.UseFastRexmit) {
1266 /*
1267 * Enable Fast RA only when RA interval is in
1268 * secs and Fast RA retransmit is enabled
1269 */
1270 zif->rtadv.inFastRexmit = 1;
1271 zif->rtadv.NumFastReXmitsRemain =
1272 RTADV_NUM_FAST_REXMITS;
1273 }
1274
1275 rtadv_start_interface_events(zvrf, zif);
1276 }
1277 }
1278 }
1279
1280 /*
1281 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1282 * Note that while the client could request RA on an interface on which the
1283 * operator has not enabled RA, RA won't be disabled upon client request
1284 * if the operator has explicitly enabled RA. The enable request can also
1285 * specify a RA interval (in seconds).
1286 */
1287 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
1288 {
1289 struct stream *s;
1290 ifindex_t ifindex;
1291 struct interface *ifp;
1292 struct zebra_if *zif;
1293 uint32_t ra_interval;
1294
1295 s = msg;
1296
1297 /* Get interface index and RA interval. */
1298 STREAM_GETL(s, ifindex);
1299 STREAM_GETL(s, ra_interval);
1300
1301 if (IS_ZEBRA_DEBUG_EVENT) {
1302 struct vrf *vrf = zvrf->vrf;
1303
1304 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1305 VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
1306 enable ? "enable" : "disable",
1307 zebra_route_string(client->proto), ra_interval);
1308 }
1309
1310 /* Locate interface and check VRF match. */
1311 ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
1312 if (!ifp) {
1313 struct vrf *vrf = zvrf->vrf;
1314
1315 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
1316 "%s:%u: IF %u RA %s client %s - interface unknown",
1317 VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
1318 enable ? "enable" : "disable",
1319 zebra_route_string(client->proto));
1320 return;
1321 }
1322 if (vrf_is_backend_netns() && ifp->vrf->vrf_id != zvrf_id(zvrf)) {
1323 zlog_debug(
1324 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1325 ifp->vrf->name, zvrf_id(zvrf), ifindex,
1326 enable ? "enable" : "disable",
1327 zebra_route_string(client->proto), ifp->vrf->vrf_id);
1328 return;
1329 }
1330
1331 zif = ifp->info;
1332 if (enable) {
1333 if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1334 interfaces_configured_for_ra_from_bgp++;
1335
1336 SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
1337 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
1338 if (ra_interval
1339 && (ra_interval * 1000) < (unsigned int) zif->rtadv.MaxRtrAdvInterval
1340 && !CHECK_FLAG(zif->rtadv.ra_configured,
1341 VTY_RA_INTERVAL_CONFIGURED))
1342 zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
1343 } else {
1344 if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1345 interfaces_configured_for_ra_from_bgp--;
1346
1347 UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
1348 if (!CHECK_FLAG(zif->rtadv.ra_configured,
1349 VTY_RA_INTERVAL_CONFIGURED))
1350 zif->rtadv.MaxRtrAdvInterval =
1351 RTADV_MAX_RTR_ADV_INTERVAL;
1352 if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
1353 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
1354 }
1355 stream_failure:
1356 return;
1357 }
1358
1359 /*
1360 * send router lifetime value of zero in RAs on this interface since we're
1361 * ceasing to advertise and want to let our neighbors know.
1362 * RFC 4861 secion 6.2.5
1363 */
1364 void rtadv_stop_ra(struct interface *ifp)
1365 {
1366 struct zebra_if *zif;
1367 struct zebra_vrf *zvrf;
1368
1369 zif = ifp->info;
1370 zvrf = rtadv_interface_get_zvrf(ifp);
1371
1372 if (zif->rtadv.AdvSendAdvertisements)
1373 rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
1374 }
1375
1376 /*
1377 * Send router lifetime value of zero in RAs on all interfaces since we're
1378 * ceasing to advertise globally and want to let all of our neighbors know
1379 * RFC 4861 secion 6.2.5
1380 *
1381 * Delete all ipv6 global prefixes added to the router advertisement prefix
1382 * lists prior to ceasing.
1383 */
1384 void rtadv_stop_ra_all(void)
1385 {
1386 struct vrf *vrf;
1387 struct interface *ifp;
1388 struct zebra_if *zif;
1389 struct rtadv_prefix *rprefix;
1390
1391 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1392 FOR_ALL_INTERFACES (vrf, ifp) {
1393 zif = ifp->info;
1394
1395 frr_each_safe (rtadv_prefixes, zif->rtadv.prefixes,
1396 rprefix)
1397 rtadv_prefix_reset(zif, rprefix);
1398
1399 rtadv_stop_ra(ifp);
1400 }
1401 }
1402
1403 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
1404 {
1405 zebra_interface_radv_set(client, hdr, msg, zvrf, 0);
1406 }
1407 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
1408 {
1409 zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
1410 }
1411
1412 static void show_zvrf_rtadv_adv_if_helper(struct vty *vty,
1413 struct adv_if_list_head *adv_if_head)
1414 {
1415 struct adv_if *node = NULL;
1416
1417 if (!adv_if_is_empty_internal(adv_if_head)) {
1418 frr_each (adv_if_list, adv_if_head, node) {
1419 vty_out(vty, " %s\n", node->name);
1420 }
1421 }
1422
1423 vty_out(vty, "\n");
1424 }
1425
1426 static void show_zvrf_rtadv_helper(struct vty *vty, struct zebra_vrf *zvrf)
1427 {
1428 vty_out(vty, "VRF: %s\n", zvrf_name(zvrf));
1429 vty_out(vty, " Interfaces:\n");
1430 show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_if);
1431
1432 vty_out(vty, " Interfaces(msec):\n");
1433 show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_msec_if);
1434 }
1435
1436 DEFPY(show_ipv6_nd_ra_if, show_ipv6_nd_ra_if_cmd,
1437 "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
1438 SHOW_STR IP6_STR
1439 "Neighbor discovery\n"
1440 "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR)
1441 {
1442 struct zebra_vrf *zvrf = NULL;
1443
1444 if (!vrf_is_backend_netns() && (vrf_name || vrf_all)) {
1445 vty_out(vty,
1446 "%% VRF subcommand only applicable for netns-based vrfs.\n");
1447 return CMD_WARNING;
1448 }
1449
1450 if (vrf_all) {
1451 struct vrf *vrf;
1452
1453 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1454 struct zebra_vrf *zvrf;
1455
1456 zvrf = vrf->info;
1457 if (!zvrf)
1458 continue;
1459
1460 show_zvrf_rtadv_helper(vty, zvrf);
1461 }
1462
1463 return CMD_SUCCESS;
1464 }
1465
1466 if (vrf_name)
1467 zvrf = zebra_vrf_lookup_by_name(vrf_name);
1468 else
1469 zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
1470
1471 if (!zvrf) {
1472 vty_out(vty, "%% VRF '%s' specified does not exist\n",
1473 vrf_name);
1474 return CMD_WARNING;
1475 }
1476
1477 show_zvrf_rtadv_helper(vty, zvrf);
1478
1479 return CMD_SUCCESS;
1480 }
1481
1482 DEFUN (ipv6_nd_ra_fast_retrans,
1483 ipv6_nd_ra_fast_retrans_cmd,
1484 "ipv6 nd ra-fast-retrans",
1485 "Interface IPv6 config commands\n"
1486 "Neighbor discovery\n"
1487 "Fast retransmit of RA packets\n")
1488 {
1489 VTY_DECLVAR_CONTEXT(interface, ifp);
1490 struct zebra_if *zif = ifp->info;
1491
1492 if (if_is_loopback(ifp)) {
1493 vty_out(vty,
1494 "Cannot configure IPv6 Router Advertisements on this interface\n");
1495 return CMD_WARNING_CONFIG_FAILED;
1496 }
1497
1498 zif->rtadv.UseFastRexmit = true;
1499
1500 return CMD_SUCCESS;
1501 }
1502
1503 DEFUN (no_ipv6_nd_ra_fast_retrans,
1504 no_ipv6_nd_ra_fast_retrans_cmd,
1505 "no ipv6 nd ra-fast-retrans",
1506 NO_STR
1507 "Interface IPv6 config commands\n"
1508 "Neighbor discovery\n"
1509 "Fast retransmit of RA packets\n")
1510 {
1511 VTY_DECLVAR_CONTEXT(interface, ifp);
1512 struct zebra_if *zif = ifp->info;
1513
1514 if (if_is_loopback(ifp)) {
1515 vty_out(vty,
1516 "Cannot configure IPv6 Router Advertisements on this interface\n");
1517 return CMD_WARNING_CONFIG_FAILED;
1518 }
1519
1520 zif->rtadv.UseFastRexmit = false;
1521
1522 return CMD_SUCCESS;
1523 }
1524
1525 DEFPY (ipv6_nd_ra_hop_limit,
1526 ipv6_nd_ra_hop_limit_cmd,
1527 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1528 "Interface IPv6 config commands\n"
1529 "Neighbor discovery\n"
1530 "Advertisement Hop Limit\n"
1531 "Advertisement Hop Limit in hops (default:64)\n")
1532 {
1533 VTY_DECLVAR_CONTEXT(interface, ifp);
1534 struct zebra_if *zif = ifp->info;
1535
1536 if (if_is_loopback(ifp)) {
1537 vty_out(vty,
1538 "Cannot configure IPv6 Router Advertisements on this interface\n");
1539 return CMD_WARNING_CONFIG_FAILED;
1540 }
1541
1542 zif->rtadv.AdvCurHopLimit = hopcount;
1543
1544 return CMD_SUCCESS;
1545 }
1546
1547 DEFPY (no_ipv6_nd_ra_hop_limit,
1548 no_ipv6_nd_ra_hop_limit_cmd,
1549 "no ipv6 nd ra-hop-limit [(0-255)]",
1550 NO_STR
1551 "Interface IPv6 config commands\n"
1552 "Neighbor discovery\n"
1553 "Advertisement Hop Limit\n"
1554 "Advertisement Hop Limit in hops\n")
1555 {
1556 VTY_DECLVAR_CONTEXT(interface, ifp);
1557 struct zebra_if *zif = ifp->info;
1558
1559 if (if_is_loopback(ifp)) {
1560 vty_out(vty,
1561 "Cannot configure IPv6 Router Advertisements on this interface\n");
1562 return CMD_WARNING_CONFIG_FAILED;
1563 }
1564
1565 zif->rtadv.AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
1566
1567 return CMD_SUCCESS;
1568 }
1569
1570 DEFPY (ipv6_nd_ra_retrans_interval,
1571 ipv6_nd_ra_retrans_interval_cmd,
1572 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1573 "Interface IPv6 config commands\n"
1574 "Neighbor discovery\n"
1575 "Advertisement Retransmit Interval\n"
1576 "Advertisement Retransmit Interval in msec\n")
1577 {
1578 VTY_DECLVAR_CONTEXT(interface, ifp);
1579 struct zebra_if *zif = ifp->info;
1580
1581 if (if_is_loopback(ifp)) {
1582 vty_out(vty,
1583 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1584 return CMD_WARNING_CONFIG_FAILED;
1585 }
1586
1587 zif->rtadv.AdvRetransTimer = interval;
1588
1589 return CMD_SUCCESS;
1590 }
1591
1592 DEFPY (no_ipv6_nd_ra_retrans_interval,
1593 no_ipv6_nd_ra_retrans_interval_cmd,
1594 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1595 NO_STR
1596 "Interface IPv6 config commands\n"
1597 "Neighbor discovery\n"
1598 "Advertisement Retransmit Interval\n"
1599 "Advertisement Retransmit Interval in msec\n")
1600 {
1601 VTY_DECLVAR_CONTEXT(interface, ifp);
1602 struct zebra_if *zif = ifp->info;
1603
1604 if (if_is_loopback(ifp)) {
1605 vty_out(vty,
1606 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1607 return CMD_WARNING_CONFIG_FAILED;
1608 }
1609
1610 zif->rtadv.AdvRetransTimer = 0;
1611
1612 return CMD_SUCCESS;
1613 }
1614
1615 DEFUN (ipv6_nd_suppress_ra,
1616 ipv6_nd_suppress_ra_cmd,
1617 "ipv6 nd suppress-ra",
1618 "Interface IPv6 config commands\n"
1619 "Neighbor discovery\n"
1620 "Suppress Router Advertisement\n")
1621 {
1622 VTY_DECLVAR_CONTEXT(interface, ifp);
1623 struct zebra_if *zif = ifp->info;
1624
1625 if (if_is_loopback(ifp)) {
1626 vty_out(vty,
1627 "Cannot configure IPv6 Router Advertisements on this interface\n");
1628 return CMD_WARNING_CONFIG_FAILED;
1629 }
1630
1631 if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1632 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
1633
1634 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
1635 return CMD_SUCCESS;
1636 }
1637
1638 DEFUN (no_ipv6_nd_suppress_ra,
1639 no_ipv6_nd_suppress_ra_cmd,
1640 "no ipv6 nd suppress-ra",
1641 NO_STR
1642 "Interface IPv6 config commands\n"
1643 "Neighbor discovery\n"
1644 "Suppress Router Advertisement\n")
1645 {
1646 VTY_DECLVAR_CONTEXT(interface, ifp);
1647 struct zebra_if *zif = ifp->info;
1648
1649 if (if_is_loopback(ifp)) {
1650 vty_out(vty,
1651 "Cannot configure IPv6 Router Advertisements on this interface\n");
1652 return CMD_WARNING_CONFIG_FAILED;
1653 }
1654
1655 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
1656 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
1657 return CMD_SUCCESS;
1658 }
1659
1660 DEFUN (ipv6_nd_ra_interval_msec,
1661 ipv6_nd_ra_interval_msec_cmd,
1662 "ipv6 nd ra-interval msec (70-1800000)",
1663 "Interface IPv6 config commands\n"
1664 "Neighbor discovery\n"
1665 "Router Advertisement interval\n"
1666 "Router Advertisement interval in milliseconds\n"
1667 "Router Advertisement interval in milliseconds\n")
1668 {
1669 int idx_number = 4;
1670 VTY_DECLVAR_CONTEXT(interface, ifp);
1671 unsigned interval;
1672 struct zebra_if *zif = ifp->info;
1673 struct zebra_vrf *zvrf;
1674 struct adv_if *adv_if;
1675
1676 zvrf = rtadv_interface_get_zvrf(ifp);
1677
1678 interval = strtoul(argv[idx_number]->arg, NULL, 10);
1679 if ((zif->rtadv.AdvDefaultLifetime != -1
1680 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
1681 vty_out(vty,
1682 "This ra-interval would conflict with configured ra-lifetime!\n");
1683 return CMD_WARNING_CONFIG_FAILED;
1684 }
1685
1686 if (zif->rtadv.MaxRtrAdvInterval % 1000) {
1687 adv_if = adv_msec_if_del(zvrf, ifp->name);
1688 if (adv_if != NULL)
1689 adv_if_free(adv_if);
1690 }
1691
1692 if (interval % 1000)
1693 (void)adv_msec_if_add(zvrf, ifp->name);
1694
1695 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1696 zif->rtadv.MaxRtrAdvInterval = interval;
1697 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1698 zif->rtadv.AdvIntervalTimer = 0;
1699
1700 return CMD_SUCCESS;
1701 }
1702
1703 DEFUN (ipv6_nd_ra_interval,
1704 ipv6_nd_ra_interval_cmd,
1705 "ipv6 nd ra-interval (1-1800)",
1706 "Interface IPv6 config commands\n"
1707 "Neighbor discovery\n"
1708 "Router Advertisement interval\n"
1709 "Router Advertisement interval in seconds\n")
1710 {
1711 int idx_number = 3;
1712 VTY_DECLVAR_CONTEXT(interface, ifp);
1713 unsigned interval;
1714 struct zebra_if *zif = ifp->info;
1715 struct zebra_vrf *zvrf;
1716 struct adv_if *adv_if;
1717
1718 zvrf = rtadv_interface_get_zvrf(ifp);
1719
1720 interval = strtoul(argv[idx_number]->arg, NULL, 10);
1721 if ((zif->rtadv.AdvDefaultLifetime != -1
1722 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
1723 vty_out(vty,
1724 "This ra-interval would conflict with configured ra-lifetime!\n");
1725 return CMD_WARNING_CONFIG_FAILED;
1726 }
1727
1728 if (zif->rtadv.MaxRtrAdvInterval % 1000) {
1729 adv_if = adv_msec_if_del(zvrf, ifp->name);
1730 if (adv_if != NULL)
1731 adv_if_free(adv_if);
1732 }
1733
1734 /* convert to milliseconds */
1735 interval = interval * 1000;
1736
1737 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1738 zif->rtadv.MaxRtrAdvInterval = interval;
1739 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1740 zif->rtadv.AdvIntervalTimer = 0;
1741
1742 return CMD_SUCCESS;
1743 }
1744
1745 DEFUN (no_ipv6_nd_ra_interval,
1746 no_ipv6_nd_ra_interval_cmd,
1747 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1748 NO_STR
1749 "Interface IPv6 config commands\n"
1750 "Neighbor discovery\n"
1751 "Router Advertisement interval\n"
1752 "Router Advertisement interval in seconds\n"
1753 "Specify millisecond router advertisement interval\n"
1754 "Router Advertisement interval in milliseconds\n")
1755 {
1756 VTY_DECLVAR_CONTEXT(interface, ifp);
1757 struct zebra_if *zif = ifp->info;
1758 struct zebra_vrf *zvrf = NULL;
1759 struct adv_if *adv_if;
1760
1761 zvrf = rtadv_interface_get_zvrf(ifp);
1762
1763 if (zif->rtadv.MaxRtrAdvInterval % 1000) {
1764 adv_if = adv_msec_if_del(zvrf, ifp->name);
1765 if (adv_if != NULL)
1766 adv_if_free(adv_if);
1767 }
1768
1769 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1770
1771 if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1772 zif->rtadv.MaxRtrAdvInterval = 10000;
1773 else
1774 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
1775
1776 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
1777 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
1778
1779 return CMD_SUCCESS;
1780 }
1781
1782 DEFUN (ipv6_nd_ra_lifetime,
1783 ipv6_nd_ra_lifetime_cmd,
1784 "ipv6 nd ra-lifetime (0-9000)",
1785 "Interface IPv6 config commands\n"
1786 "Neighbor discovery\n"
1787 "Router lifetime\n"
1788 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1789 {
1790 int idx_number = 3;
1791 VTY_DECLVAR_CONTEXT(interface, ifp);
1792 struct zebra_if *zif = ifp->info;
1793 int lifetime;
1794
1795 lifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1796
1797 /* The value to be placed in the Router Lifetime field
1798 * of Router Advertisements sent from the interface,
1799 * in seconds. MUST be either zero or between
1800 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1801 if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) {
1802 vty_out(vty,
1803 "This ra-lifetime would conflict with configured ra-interval\n");
1804 return CMD_WARNING_CONFIG_FAILED;
1805 }
1806
1807 zif->rtadv.AdvDefaultLifetime = lifetime;
1808
1809 return CMD_SUCCESS;
1810 }
1811
1812 DEFUN (no_ipv6_nd_ra_lifetime,
1813 no_ipv6_nd_ra_lifetime_cmd,
1814 "no ipv6 nd ra-lifetime [(0-9000)]",
1815 NO_STR
1816 "Interface IPv6 config commands\n"
1817 "Neighbor discovery\n"
1818 "Router lifetime\n"
1819 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1820 {
1821 VTY_DECLVAR_CONTEXT(interface, ifp);
1822 struct zebra_if *zif = ifp->info;
1823
1824 zif->rtadv.AdvDefaultLifetime = -1;
1825
1826 return CMD_SUCCESS;
1827 }
1828
1829 DEFUN (ipv6_nd_reachable_time,
1830 ipv6_nd_reachable_time_cmd,
1831 "ipv6 nd reachable-time (1-3600000)",
1832 "Interface IPv6 config commands\n"
1833 "Neighbor discovery\n"
1834 "Reachable time\n"
1835 "Reachable time in milliseconds\n")
1836 {
1837 int idx_number = 3;
1838 VTY_DECLVAR_CONTEXT(interface, ifp);
1839 struct zebra_if *zif = ifp->info;
1840 zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10);
1841 return CMD_SUCCESS;
1842 }
1843
1844 DEFUN (no_ipv6_nd_reachable_time,
1845 no_ipv6_nd_reachable_time_cmd,
1846 "no ipv6 nd reachable-time [(1-3600000)]",
1847 NO_STR
1848 "Interface IPv6 config commands\n"
1849 "Neighbor discovery\n"
1850 "Reachable time\n"
1851 "Reachable time in milliseconds\n")
1852 {
1853 VTY_DECLVAR_CONTEXT(interface, ifp);
1854 struct zebra_if *zif = ifp->info;
1855
1856 zif->rtadv.AdvReachableTime = 0;
1857
1858 return CMD_SUCCESS;
1859 }
1860
1861 DEFUN (ipv6_nd_homeagent_preference,
1862 ipv6_nd_homeagent_preference_cmd,
1863 "ipv6 nd home-agent-preference (0-65535)",
1864 "Interface IPv6 config commands\n"
1865 "Neighbor discovery\n"
1866 "Home Agent preference\n"
1867 "preference value (default is 0, least preferred)\n")
1868 {
1869 int idx_number = 3;
1870 VTY_DECLVAR_CONTEXT(interface, ifp);
1871 struct zebra_if *zif = ifp->info;
1872 zif->rtadv.HomeAgentPreference =
1873 strtoul(argv[idx_number]->arg, NULL, 10);
1874 return CMD_SUCCESS;
1875 }
1876
1877 DEFUN (no_ipv6_nd_homeagent_preference,
1878 no_ipv6_nd_homeagent_preference_cmd,
1879 "no ipv6 nd home-agent-preference [(0-65535)]",
1880 NO_STR
1881 "Interface IPv6 config commands\n"
1882 "Neighbor discovery\n"
1883 "Home Agent preference\n"
1884 "preference value (default is 0, least preferred)\n")
1885 {
1886 VTY_DECLVAR_CONTEXT(interface, ifp);
1887 struct zebra_if *zif = ifp->info;
1888
1889 zif->rtadv.HomeAgentPreference = 0;
1890
1891 return CMD_SUCCESS;
1892 }
1893
1894 DEFUN (ipv6_nd_homeagent_lifetime,
1895 ipv6_nd_homeagent_lifetime_cmd,
1896 "ipv6 nd home-agent-lifetime (0-65520)",
1897 "Interface IPv6 config commands\n"
1898 "Neighbor discovery\n"
1899 "Home Agent lifetime\n"
1900 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1901 {
1902 int idx_number = 3;
1903 VTY_DECLVAR_CONTEXT(interface, ifp);
1904 struct zebra_if *zif = ifp->info;
1905 zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1906 return CMD_SUCCESS;
1907 }
1908
1909 DEFUN (no_ipv6_nd_homeagent_lifetime,
1910 no_ipv6_nd_homeagent_lifetime_cmd,
1911 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1912 NO_STR
1913 "Interface IPv6 config commands\n"
1914 "Neighbor discovery\n"
1915 "Home Agent lifetime\n"
1916 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1917 {
1918 VTY_DECLVAR_CONTEXT(interface, ifp);
1919 struct zebra_if *zif = ifp->info;
1920
1921 zif->rtadv.HomeAgentLifetime = -1;
1922
1923 return CMD_SUCCESS;
1924 }
1925
1926 DEFUN (ipv6_nd_managed_config_flag,
1927 ipv6_nd_managed_config_flag_cmd,
1928 "ipv6 nd managed-config-flag",
1929 "Interface IPv6 config commands\n"
1930 "Neighbor discovery\n"
1931 "Managed address configuration flag\n")
1932 {
1933 VTY_DECLVAR_CONTEXT(interface, ifp);
1934 struct zebra_if *zif = ifp->info;
1935
1936 zif->rtadv.AdvManagedFlag = 1;
1937
1938 return CMD_SUCCESS;
1939 }
1940
1941 DEFUN (no_ipv6_nd_managed_config_flag,
1942 no_ipv6_nd_managed_config_flag_cmd,
1943 "no ipv6 nd managed-config-flag",
1944 NO_STR
1945 "Interface IPv6 config commands\n"
1946 "Neighbor discovery\n"
1947 "Managed address configuration flag\n")
1948 {
1949 VTY_DECLVAR_CONTEXT(interface, ifp);
1950 struct zebra_if *zif = ifp->info;
1951
1952 zif->rtadv.AdvManagedFlag = 0;
1953
1954 return CMD_SUCCESS;
1955 }
1956
1957 DEFUN (ipv6_nd_homeagent_config_flag,
1958 ipv6_nd_homeagent_config_flag_cmd,
1959 "ipv6 nd home-agent-config-flag",
1960 "Interface IPv6 config commands\n"
1961 "Neighbor discovery\n"
1962 "Home Agent configuration flag\n")
1963 {
1964 VTY_DECLVAR_CONTEXT(interface, ifp);
1965 struct zebra_if *zif = ifp->info;
1966
1967 zif->rtadv.AdvHomeAgentFlag = 1;
1968
1969 return CMD_SUCCESS;
1970 }
1971
1972 DEFUN (no_ipv6_nd_homeagent_config_flag,
1973 no_ipv6_nd_homeagent_config_flag_cmd,
1974 "no ipv6 nd home-agent-config-flag",
1975 NO_STR
1976 "Interface IPv6 config commands\n"
1977 "Neighbor discovery\n"
1978 "Home Agent configuration flag\n")
1979 {
1980 VTY_DECLVAR_CONTEXT(interface, ifp);
1981 struct zebra_if *zif = ifp->info;
1982
1983 zif->rtadv.AdvHomeAgentFlag = 0;
1984
1985 return CMD_SUCCESS;
1986 }
1987
1988 DEFUN (ipv6_nd_adv_interval_config_option,
1989 ipv6_nd_adv_interval_config_option_cmd,
1990 "ipv6 nd adv-interval-option",
1991 "Interface IPv6 config commands\n"
1992 "Neighbor discovery\n"
1993 "Advertisement Interval Option\n")
1994 {
1995 VTY_DECLVAR_CONTEXT(interface, ifp);
1996 struct zebra_if *zif = ifp->info;
1997
1998 zif->rtadv.AdvIntervalOption = 1;
1999
2000 return CMD_SUCCESS;
2001 }
2002
2003 DEFUN (no_ipv6_nd_adv_interval_config_option,
2004 no_ipv6_nd_adv_interval_config_option_cmd,
2005 "no ipv6 nd adv-interval-option",
2006 NO_STR
2007 "Interface IPv6 config commands\n"
2008 "Neighbor discovery\n"
2009 "Advertisement Interval Option\n")
2010 {
2011 VTY_DECLVAR_CONTEXT(interface, ifp);
2012 struct zebra_if *zif = ifp->info;
2013
2014 zif->rtadv.AdvIntervalOption = 0;
2015
2016 return CMD_SUCCESS;
2017 }
2018
2019 DEFUN (ipv6_nd_other_config_flag,
2020 ipv6_nd_other_config_flag_cmd,
2021 "ipv6 nd other-config-flag",
2022 "Interface IPv6 config commands\n"
2023 "Neighbor discovery\n"
2024 "Other statefull configuration flag\n")
2025 {
2026 VTY_DECLVAR_CONTEXT(interface, ifp);
2027 struct zebra_if *zif = ifp->info;
2028
2029 zif->rtadv.AdvOtherConfigFlag = 1;
2030
2031 return CMD_SUCCESS;
2032 }
2033
2034 DEFUN (no_ipv6_nd_other_config_flag,
2035 no_ipv6_nd_other_config_flag_cmd,
2036 "no ipv6 nd other-config-flag",
2037 NO_STR
2038 "Interface IPv6 config commands\n"
2039 "Neighbor discovery\n"
2040 "Other statefull configuration flag\n")
2041 {
2042 VTY_DECLVAR_CONTEXT(interface, ifp);
2043 struct zebra_if *zif = ifp->info;
2044
2045 zif->rtadv.AdvOtherConfigFlag = 0;
2046
2047 return CMD_SUCCESS;
2048 }
2049
2050 DEFUN (ipv6_nd_prefix,
2051 ipv6_nd_prefix_cmd,
2052 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2053 "Interface IPv6 config commands\n"
2054 "Neighbor discovery\n"
2055 "Prefix information\n"
2056 "IPv6 prefix\n"
2057 "Valid lifetime in seconds\n"
2058 "Infinite valid lifetime\n"
2059 "Preferred lifetime in seconds\n"
2060 "Infinite preferred lifetime\n"
2061 "Set Router Address flag\n"
2062 "Do not use prefix for onlink determination\n"
2063 "Do not use prefix for autoconfiguration\n"
2064 "Do not use prefix for autoconfiguration\n"
2065 "Do not use prefix for onlink determination\n")
2066 {
2067 /* prelude */
2068 char *prefix = argv[3]->arg;
2069 int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
2070 || strmatch(argv[4]->text, "infinite"));
2071 int routeropts = lifetimes ? argc > 6 : argc > 4;
2072
2073 int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
2074
2075 char *lifetime = NULL, *preflifetime = NULL;
2076 int routeraddr = 0, offlink = 0, noautoconf = 0;
2077 if (lifetimes) {
2078 lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
2079 : argv[4]->text;
2080 preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg
2081 : argv[5]->text;
2082 }
2083 if (routeropts) {
2084 routeraddr =
2085 strmatch(argv[idx_routeropts]->text, "router-address");
2086 if (!routeraddr) {
2087 offlink = (argc > idx_routeropts + 1
2088 || strmatch(argv[idx_routeropts]->text,
2089 "off-link"));
2090 noautoconf = (argc > idx_routeropts + 1
2091 || strmatch(argv[idx_routeropts]->text,
2092 "no-autoconfig"));
2093 }
2094 }
2095
2096 /* business */
2097 VTY_DECLVAR_CONTEXT(interface, ifp);
2098 struct zebra_if *zebra_if = ifp->info;
2099 int ret;
2100 struct rtadv_prefix rp;
2101
2102 ret = str2prefix_ipv6(prefix, &rp.prefix);
2103 if (!ret) {
2104 vty_out(vty, "Malformed IPv6 prefix\n");
2105 return CMD_WARNING_CONFIG_FAILED;
2106 }
2107 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
2108 rp.AdvOnLinkFlag = !offlink;
2109 rp.AdvAutonomousFlag = !noautoconf;
2110 rp.AdvRouterAddressFlag = routeraddr;
2111 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
2112 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
2113 rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
2114
2115 if (lifetimes) {
2116 rp.AdvValidLifetime = strmatch(lifetime, "infinite")
2117 ? UINT32_MAX
2118 : strtoll(lifetime, NULL, 10);
2119 rp.AdvPreferredLifetime =
2120 strmatch(preflifetime, "infinite")
2121 ? UINT32_MAX
2122 : strtoll(preflifetime, NULL, 10);
2123 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) {
2124 vty_out(vty, "Invalid preferred lifetime\n");
2125 return CMD_WARNING_CONFIG_FAILED;
2126 }
2127 }
2128
2129 rtadv_prefix_set(zebra_if, &rp);
2130
2131 return CMD_SUCCESS;
2132 }
2133
2134 DEFUN (no_ipv6_nd_prefix,
2135 no_ipv6_nd_prefix_cmd,
2136 "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]>]",
2137 NO_STR
2138 "Interface IPv6 config commands\n"
2139 "Neighbor discovery\n"
2140 "Prefix information\n"
2141 "IPv6 prefix\n"
2142 "Valid lifetime in seconds\n"
2143 "Infinite valid lifetime\n"
2144 "Preferred lifetime in seconds\n"
2145 "Infinite preferred lifetime\n"
2146 "Set Router Address flag\n"
2147 "Do not use prefix for onlink determination\n"
2148 "Do not use prefix for autoconfiguration\n"
2149 "Do not use prefix for autoconfiguration\n"
2150 "Do not use prefix for onlink determination\n")
2151 {
2152 VTY_DECLVAR_CONTEXT(interface, ifp);
2153 struct zebra_if *zebra_if = ifp->info;
2154 int ret;
2155 struct rtadv_prefix rp;
2156 char *prefix = argv[4]->arg;
2157
2158 ret = str2prefix_ipv6(prefix, &rp.prefix);
2159 if (!ret) {
2160 vty_out(vty, "Malformed IPv6 prefix\n");
2161 return CMD_WARNING_CONFIG_FAILED;
2162 }
2163 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
2164 rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
2165
2166 ret = rtadv_prefix_reset(zebra_if, &rp);
2167 if (!ret) {
2168 vty_out(vty, "Non-existant IPv6 prefix\n");
2169 return CMD_WARNING_CONFIG_FAILED;
2170 }
2171
2172 return CMD_SUCCESS;
2173 }
2174
2175 DEFUN (ipv6_nd_router_preference,
2176 ipv6_nd_router_preference_cmd,
2177 "ipv6 nd router-preference <high|medium|low>",
2178 "Interface IPv6 config commands\n"
2179 "Neighbor discovery\n"
2180 "Default router preference\n"
2181 "High default router preference\n"
2182 "Medium default router preference (default)\n"
2183 "Low default router preference\n")
2184 {
2185 int idx_high_medium_low = 3;
2186 VTY_DECLVAR_CONTEXT(interface, ifp);
2187 struct zebra_if *zif = ifp->info;
2188 int i = 0;
2189
2190 while (0 != rtadv_pref_strs[i]) {
2191 if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i],
2192 1)
2193 == 0) {
2194 zif->rtadv.DefaultPreference = i;
2195 return CMD_SUCCESS;
2196 }
2197 i++;
2198 }
2199
2200 return CMD_ERR_NO_MATCH;
2201 }
2202
2203 DEFUN (no_ipv6_nd_router_preference,
2204 no_ipv6_nd_router_preference_cmd,
2205 "no ipv6 nd router-preference [<high|medium|low>]",
2206 NO_STR
2207 "Interface IPv6 config commands\n"
2208 "Neighbor discovery\n"
2209 "Default router preference\n"
2210 "High default router preference\n"
2211 "Medium default router preference (default)\n"
2212 "Low default router preference\n")
2213 {
2214 VTY_DECLVAR_CONTEXT(interface, ifp);
2215 struct zebra_if *zif = ifp->info;
2216
2217 zif->rtadv.DefaultPreference =
2218 RTADV_PREF_MEDIUM; /* Default per RFC4191. */
2219
2220 return CMD_SUCCESS;
2221 }
2222
2223 DEFUN (ipv6_nd_mtu,
2224 ipv6_nd_mtu_cmd,
2225 "ipv6 nd mtu (1-65535)",
2226 "Interface IPv6 config commands\n"
2227 "Neighbor discovery\n"
2228 "Advertised MTU\n"
2229 "MTU in bytes\n")
2230 {
2231 int idx_number = 3;
2232 VTY_DECLVAR_CONTEXT(interface, ifp);
2233 struct zebra_if *zif = ifp->info;
2234 zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10);
2235 return CMD_SUCCESS;
2236 }
2237
2238 DEFUN (no_ipv6_nd_mtu,
2239 no_ipv6_nd_mtu_cmd,
2240 "no ipv6 nd mtu [(1-65535)]",
2241 NO_STR
2242 "Interface IPv6 config commands\n"
2243 "Neighbor discovery\n"
2244 "Advertised MTU\n"
2245 "MTU in bytes\n")
2246 {
2247 VTY_DECLVAR_CONTEXT(interface, ifp);
2248 struct zebra_if *zif = ifp->info;
2249 zif->rtadv.AdvLinkMTU = 0;
2250 return CMD_SUCCESS;
2251 }
2252
2253 static struct rtadv_rdnss *rtadv_rdnss_new(void)
2254 {
2255 return XCALLOC(MTYPE_RTADV_RDNSS, sizeof(struct rtadv_rdnss));
2256 }
2257
2258 static void rtadv_rdnss_free(struct rtadv_rdnss *rdnss)
2259 {
2260 XFREE(MTYPE_RTADV_RDNSS, rdnss);
2261 }
2262
2263 static struct rtadv_rdnss *rtadv_rdnss_lookup(struct list *list,
2264 struct rtadv_rdnss *rdnss)
2265 {
2266 struct listnode *node;
2267 struct rtadv_rdnss *p;
2268
2269 for (ALL_LIST_ELEMENTS_RO(list, node, p))
2270 if (IPV6_ADDR_SAME(&p->addr, &rdnss->addr))
2271 return p;
2272 return NULL;
2273 }
2274
2275 static struct rtadv_rdnss *rtadv_rdnss_get(struct list *list,
2276 struct rtadv_rdnss *rdnss)
2277 {
2278 struct rtadv_rdnss *p;
2279
2280 p = rtadv_rdnss_lookup(list, rdnss);
2281 if (p)
2282 return p;
2283
2284 p = rtadv_rdnss_new();
2285 memcpy(p, rdnss, sizeof(struct rtadv_rdnss));
2286 listnode_add(list, p);
2287
2288 return p;
2289 }
2290
2291 static void rtadv_rdnss_set(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
2292 {
2293 struct rtadv_rdnss *p;
2294
2295 p = rtadv_rdnss_get(zif->rtadv.AdvRDNSSList, rdnss);
2296 p->lifetime = rdnss->lifetime;
2297 p->lifetime_set = rdnss->lifetime_set;
2298 }
2299
2300 static int rtadv_rdnss_reset(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
2301 {
2302 struct rtadv_rdnss *p;
2303
2304 p = rtadv_rdnss_lookup(zif->rtadv.AdvRDNSSList, rdnss);
2305 if (p) {
2306 listnode_delete(zif->rtadv.AdvRDNSSList, p);
2307 rtadv_rdnss_free(p);
2308 return 1;
2309 }
2310
2311 return 0;
2312 }
2313
2314 static struct rtadv_dnssl *rtadv_dnssl_new(void)
2315 {
2316 return XCALLOC(MTYPE_RTADV_DNSSL, sizeof(struct rtadv_dnssl));
2317 }
2318
2319 static void rtadv_dnssl_free(struct rtadv_dnssl *dnssl)
2320 {
2321 XFREE(MTYPE_RTADV_DNSSL, dnssl);
2322 }
2323
2324 static struct rtadv_dnssl *rtadv_dnssl_lookup(struct list *list,
2325 struct rtadv_dnssl *dnssl)
2326 {
2327 struct listnode *node;
2328 struct rtadv_dnssl *p;
2329
2330 for (ALL_LIST_ELEMENTS_RO(list, node, p))
2331 if (!strcasecmp(p->name, dnssl->name))
2332 return p;
2333 return NULL;
2334 }
2335
2336 static struct rtadv_dnssl *rtadv_dnssl_get(struct list *list,
2337 struct rtadv_dnssl *dnssl)
2338 {
2339 struct rtadv_dnssl *p;
2340
2341 p = rtadv_dnssl_lookup(list, dnssl);
2342 if (p)
2343 return p;
2344
2345 p = rtadv_dnssl_new();
2346 memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
2347 listnode_add(list, p);
2348
2349 return p;
2350 }
2351
2352 static void rtadv_dnssl_set(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
2353 {
2354 struct rtadv_dnssl *p;
2355
2356 p = rtadv_dnssl_get(zif->rtadv.AdvDNSSLList, dnssl);
2357 memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
2358 }
2359
2360 static int rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
2361 {
2362 struct rtadv_dnssl *p;
2363
2364 p = rtadv_dnssl_lookup(zif->rtadv.AdvDNSSLList, dnssl);
2365 if (p) {
2366 listnode_delete(zif->rtadv.AdvDNSSLList, p);
2367 rtadv_dnssl_free(p);
2368 return 1;
2369 }
2370
2371 return 0;
2372 }
2373
2374 /*
2375 * Convert dotted domain name (with or without trailing root zone dot) to
2376 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2377 * to strlen(in) + 2 octets to out.
2378 *
2379 * Returns the number of octets written to out or -1 if in does not constitute
2380 * a valid domain name.
2381 */
2382 static int rtadv_dnssl_encode(uint8_t *out, const char *in)
2383 {
2384 const char *label_start, *label_end;
2385 size_t outp;
2386
2387 outp = 0;
2388 label_start = in;
2389
2390 while (*label_start) {
2391 size_t label_len;
2392
2393 label_end = strchr(label_start, '.');
2394 if (label_end == NULL)
2395 label_end = label_start + strlen(label_start);
2396
2397 label_len = label_end - label_start;
2398 if (label_len >= 64)
2399 return -1; /* labels must be 63 octets or less */
2400
2401 out[outp++] = (uint8_t)label_len;
2402 memcpy(out + outp, label_start, label_len);
2403 outp += label_len;
2404 label_start += label_len;
2405 if (*label_start == '.')
2406 label_start++;
2407 }
2408
2409 out[outp++] = '\0';
2410 return outp;
2411 }
2412
2413 DEFUN(ipv6_nd_rdnss,
2414 ipv6_nd_rdnss_cmd,
2415 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2416 "Interface IPv6 config commands\n"
2417 "Neighbor discovery\n"
2418 "Recursive DNS server information\n"
2419 "IPv6 address\n"
2420 "Valid lifetime in seconds\n"
2421 "Infinite valid lifetime\n")
2422 {
2423 VTY_DECLVAR_CONTEXT(interface, ifp);
2424 struct zebra_if *zif = ifp->info;
2425 struct rtadv_rdnss rdnss = {};
2426
2427 if (inet_pton(AF_INET6, argv[3]->arg, &rdnss.addr) != 1) {
2428 vty_out(vty, "Malformed IPv6 address\n");
2429 return CMD_WARNING_CONFIG_FAILED;
2430 }
2431 if (argc > 4) {
2432 char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
2433 : argv[4]->text;
2434 rdnss.lifetime = strmatch(lifetime, "infinite")
2435 ? UINT32_MAX
2436 : strtoll(lifetime, NULL, 10);
2437 rdnss.lifetime_set = 1;
2438 }
2439
2440 rtadv_rdnss_set(zif, &rdnss);
2441
2442 return CMD_SUCCESS;
2443 }
2444
2445 DEFUN(no_ipv6_nd_rdnss,
2446 no_ipv6_nd_rdnss_cmd,
2447 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2448 NO_STR
2449 "Interface IPv6 config commands\n"
2450 "Neighbor discovery\n"
2451 "Recursive DNS server information\n"
2452 "IPv6 address\n"
2453 "Valid lifetime in seconds\n"
2454 "Infinite valid lifetime\n")
2455 {
2456 VTY_DECLVAR_CONTEXT(interface, ifp);
2457 struct zebra_if *zif = ifp->info;
2458 struct rtadv_rdnss rdnss = {};
2459
2460 if (inet_pton(AF_INET6, argv[4]->arg, &rdnss.addr) != 1) {
2461 vty_out(vty, "Malformed IPv6 address\n");
2462 return CMD_WARNING_CONFIG_FAILED;
2463 }
2464 if (rtadv_rdnss_reset(zif, &rdnss) != 1) {
2465 vty_out(vty, "Non-existant RDNSS address\n");
2466 return CMD_WARNING_CONFIG_FAILED;
2467 }
2468
2469 return CMD_SUCCESS;
2470 }
2471
2472 DEFUN(ipv6_nd_dnssl,
2473 ipv6_nd_dnssl_cmd,
2474 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2475 "Interface IPv6 config commands\n"
2476 "Neighbor discovery\n"
2477 "DNS search list information\n"
2478 "Domain name suffix\n"
2479 "Valid lifetime in seconds\n"
2480 "Infinite valid lifetime\n")
2481 {
2482 VTY_DECLVAR_CONTEXT(interface, ifp);
2483 struct zebra_if *zif = ifp->info;
2484 struct rtadv_dnssl dnssl = {};
2485 size_t len;
2486 int ret;
2487
2488 len = strlcpy(dnssl.name, argv[3]->arg, sizeof(dnssl.name));
2489 if (len == 0 || len >= sizeof(dnssl.name)) {
2490 vty_out(vty, "Malformed DNS search domain\n");
2491 return CMD_WARNING_CONFIG_FAILED;
2492 }
2493 if (dnssl.name[len - 1] == '.') {
2494 /*
2495 * Allow, but don't require, a trailing dot signifying the root
2496 * zone. Canonicalize by cutting it off if present.
2497 */
2498 dnssl.name[len - 1] = '\0';
2499 len--;
2500 }
2501 if (argc > 4) {
2502 char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
2503 : argv[4]->text;
2504 dnssl.lifetime = strmatch(lifetime, "infinite")
2505 ? UINT32_MAX
2506 : strtoll(lifetime, NULL, 10);
2507 dnssl.lifetime_set = 1;
2508 }
2509
2510 ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
2511 if (ret < 0) {
2512 vty_out(vty, "Malformed DNS search domain\n");
2513 return CMD_WARNING_CONFIG_FAILED;
2514 }
2515 dnssl.encoded_len = ret;
2516 rtadv_dnssl_set(zif, &dnssl);
2517
2518 return CMD_SUCCESS;
2519 }
2520
2521 DEFUN(no_ipv6_nd_dnssl,
2522 no_ipv6_nd_dnssl_cmd,
2523 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2524 NO_STR
2525 "Interface IPv6 config commands\n"
2526 "Neighbor discovery\n"
2527 "DNS search list information\n"
2528 "Domain name suffix\n"
2529 "Valid lifetime in seconds\n"
2530 "Infinite valid lifetime\n")
2531 {
2532 VTY_DECLVAR_CONTEXT(interface, ifp);
2533 struct zebra_if *zif = ifp->info;
2534 struct rtadv_dnssl dnssl = {};
2535 size_t len;
2536
2537 len = strlcpy(dnssl.name, argv[4]->arg, sizeof(dnssl.name));
2538 if (len == 0 || len >= sizeof(dnssl.name)) {
2539 vty_out(vty, "Malformed DNS search domain\n");
2540 return CMD_WARNING_CONFIG_FAILED;
2541 }
2542 if (dnssl.name[len - 1] == '.') {
2543 dnssl.name[len - 1] = '\0';
2544 len--;
2545 }
2546 if (rtadv_dnssl_reset(zif, &dnssl) != 1) {
2547 vty_out(vty, "Non-existant DNS search domain\n");
2548 return CMD_WARNING_CONFIG_FAILED;
2549 }
2550
2551 return CMD_SUCCESS;
2552 }
2553
2554
2555 /* Dump interface ND information to vty. */
2556 static int nd_dump_vty(struct vty *vty, struct interface *ifp)
2557 {
2558 struct zebra_if *zif;
2559 struct rtadvconf *rtadv;
2560 int interval;
2561
2562 zif = (struct zebra_if *)ifp->info;
2563 rtadv = &zif->rtadv;
2564
2565 if (rtadv->AdvSendAdvertisements) {
2566 vty_out(vty,
2567 " ND advertised reachable time is %d milliseconds\n",
2568 rtadv->AdvReachableTime);
2569 vty_out(vty,
2570 " ND advertised retransmit interval is %u milliseconds\n",
2571 rtadv->AdvRetransTimer);
2572 vty_out(vty, " ND advertised hop-count limit is %d hops\n",
2573 rtadv->AdvCurHopLimit);
2574 vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n",
2575 zif->ra_sent, zif->ra_rcvd);
2576 interval = rtadv->MaxRtrAdvInterval;
2577 if (interval % 1000)
2578 vty_out(vty,
2579 " ND router advertisements are sent every %d milliseconds\n",
2580 interval);
2581 else
2582 vty_out(vty,
2583 " ND router advertisements are sent every %d seconds\n",
2584 interval / 1000);
2585 if (!rtadv->UseFastRexmit)
2586 vty_out(vty,
2587 " ND router advertisements do not use fast retransmit\n");
2588
2589 if (rtadv->AdvDefaultLifetime != -1)
2590 vty_out(vty,
2591 " ND router advertisements live for %d seconds\n",
2592 rtadv->AdvDefaultLifetime);
2593 else
2594 vty_out(vty,
2595 " ND router advertisements lifetime tracks ra-interval\n");
2596 vty_out(vty,
2597 " ND router advertisement default router preference is %s\n",
2598 rtadv_pref_strs[rtadv->DefaultPreference]);
2599 if (rtadv->AdvManagedFlag)
2600 vty_out(vty,
2601 " Hosts use DHCP to obtain routable addresses.\n");
2602 else
2603 vty_out(vty,
2604 " Hosts use stateless autoconfig for addresses.\n");
2605 if (rtadv->AdvHomeAgentFlag) {
2606 vty_out(vty,
2607 " ND router advertisements with Home Agent flag bit set.\n");
2608 if (rtadv->HomeAgentLifetime != -1)
2609 vty_out(vty,
2610 " Home Agent lifetime is %u seconds\n",
2611 rtadv->HomeAgentLifetime);
2612 else
2613 vty_out(vty,
2614 " Home Agent lifetime tracks ra-lifetime\n");
2615 vty_out(vty, " Home Agent preference is %u\n",
2616 rtadv->HomeAgentPreference);
2617 }
2618 if (rtadv->AdvIntervalOption)
2619 vty_out(vty,
2620 " ND router advertisements with Adv. Interval option.\n");
2621 }
2622 return 0;
2623 }
2624
2625
2626 /* Write configuration about router advertisement. */
2627 static int rtadv_config_write(struct vty *vty, struct interface *ifp)
2628 {
2629 struct zebra_if *zif;
2630 struct listnode *node;
2631 struct rtadv_prefix *rprefix;
2632 struct rtadv_rdnss *rdnss;
2633 struct rtadv_dnssl *dnssl;
2634 int interval;
2635
2636 zif = ifp->info;
2637
2638 if (!if_is_loopback(ifp)) {
2639 if (zif->rtadv.AdvSendAdvertisements
2640 && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
2641 vty_out(vty, " no ipv6 nd suppress-ra\n");
2642 }
2643
2644 interval = zif->rtadv.MaxRtrAdvInterval;
2645 if (CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) {
2646 if (interval % 1000)
2647 vty_out(vty, " ipv6 nd ra-interval msec %d\n",
2648 interval);
2649 else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
2650 vty_out(vty, " ipv6 nd ra-interval %d\n",
2651 interval / 1000);
2652 }
2653
2654 if (zif->rtadv.AdvIntervalOption)
2655 vty_out(vty, " ipv6 nd adv-interval-option\n");
2656
2657 if (!zif->rtadv.UseFastRexmit)
2658 vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
2659
2660 if (zif->rtadv.AdvRetransTimer != 0)
2661 vty_out(vty, " ipv6 nd ra-retrans-interval %u\n",
2662 zif->rtadv.AdvRetransTimer);
2663
2664 if (zif->rtadv.AdvCurHopLimit != RTADV_DEFAULT_HOPLIMIT)
2665 vty_out(vty, " ipv6 nd ra-hop-limit %d\n",
2666 zif->rtadv.AdvCurHopLimit);
2667
2668 if (zif->rtadv.AdvDefaultLifetime != -1)
2669 vty_out(vty, " ipv6 nd ra-lifetime %d\n",
2670 zif->rtadv.AdvDefaultLifetime);
2671
2672 if (zif->rtadv.HomeAgentPreference)
2673 vty_out(vty, " ipv6 nd home-agent-preference %u\n",
2674 zif->rtadv.HomeAgentPreference);
2675
2676 if (zif->rtadv.HomeAgentLifetime != -1)
2677 vty_out(vty, " ipv6 nd home-agent-lifetime %u\n",
2678 zif->rtadv.HomeAgentLifetime);
2679
2680 if (zif->rtadv.AdvHomeAgentFlag)
2681 vty_out(vty, " ipv6 nd home-agent-config-flag\n");
2682
2683 if (zif->rtadv.AdvReachableTime)
2684 vty_out(vty, " ipv6 nd reachable-time %d\n",
2685 zif->rtadv.AdvReachableTime);
2686
2687 if (zif->rtadv.AdvManagedFlag)
2688 vty_out(vty, " ipv6 nd managed-config-flag\n");
2689
2690 if (zif->rtadv.AdvOtherConfigFlag)
2691 vty_out(vty, " ipv6 nd other-config-flag\n");
2692
2693 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
2694 vty_out(vty, " ipv6 nd router-preference %s\n",
2695 rtadv_pref_strs[zif->rtadv.DefaultPreference]);
2696
2697 if (zif->rtadv.AdvLinkMTU)
2698 vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU);
2699
2700 frr_each (rtadv_prefixes, zif->rtadv.prefixes, rprefix) {
2701 if ((rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
2702 || (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH)) {
2703 vty_out(vty, " ipv6 nd prefix %pFX", &rprefix->prefix);
2704 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME)
2705 || (rprefix->AdvPreferredLifetime
2706 != RTADV_PREFERRED_LIFETIME)) {
2707 if (rprefix->AdvValidLifetime == UINT32_MAX)
2708 vty_out(vty, " infinite");
2709 else
2710 vty_out(vty, " %u",
2711 rprefix->AdvValidLifetime);
2712 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
2713 vty_out(vty, " infinite");
2714 else
2715 vty_out(vty, " %u",
2716 rprefix->AdvPreferredLifetime);
2717 }
2718 if (!rprefix->AdvOnLinkFlag)
2719 vty_out(vty, " off-link");
2720 if (!rprefix->AdvAutonomousFlag)
2721 vty_out(vty, " no-autoconfig");
2722 if (rprefix->AdvRouterAddressFlag)
2723 vty_out(vty, " router-address");
2724 vty_out(vty, "\n");
2725 }
2726 }
2727
2728 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
2729 char buf[INET6_ADDRSTRLEN];
2730
2731 vty_out(vty, " ipv6 nd rdnss %s",
2732 inet_ntop(AF_INET6, &rdnss->addr, buf, sizeof(buf)));
2733 if (rdnss->lifetime_set) {
2734 if (rdnss->lifetime == UINT32_MAX)
2735 vty_out(vty, " infinite");
2736 else
2737 vty_out(vty, " %u", rdnss->lifetime);
2738 }
2739 vty_out(vty, "\n");
2740 }
2741 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
2742 vty_out(vty, " ipv6 nd dnssl %s", dnssl->name);
2743 if (dnssl->lifetime_set) {
2744 if (dnssl->lifetime == UINT32_MAX)
2745 vty_out(vty, " infinite");
2746 else
2747 vty_out(vty, " %u", dnssl->lifetime);
2748 }
2749 vty_out(vty, "\n");
2750 }
2751 return 0;
2752 }
2753
2754
2755 static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
2756 {
2757 struct rtadv *rtadv;
2758
2759 if (IS_ZEBRA_DEBUG_EVENT) {
2760 struct vrf *vrf = zvrf->vrf;
2761
2762 zlog_debug("%s(%s) with event: %d and val: %d", __func__,
2763 VRF_LOGNAME(vrf), event, val);
2764 }
2765
2766 rtadv = &zvrf->rtadv;
2767
2768 switch (event) {
2769 case RTADV_START:
2770 thread_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
2771 &rtadv->ra_read);
2772 thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
2773 &rtadv->ra_timer);
2774 break;
2775 case RTADV_STOP:
2776 THREAD_OFF(rtadv->ra_timer);
2777 THREAD_OFF(rtadv->ra_read);
2778 break;
2779 case RTADV_TIMER:
2780 thread_add_timer(zrouter.master, rtadv_timer, zvrf, val,
2781 &rtadv->ra_timer);
2782 break;
2783 case RTADV_TIMER_MSEC:
2784 thread_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val,
2785 &rtadv->ra_timer);
2786 break;
2787 case RTADV_READ:
2788 thread_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
2789 &rtadv->ra_read);
2790 break;
2791 default:
2792 break;
2793 }
2794 return;
2795 }
2796
2797 void rtadv_if_up(struct zebra_if *zif)
2798 {
2799 struct zebra_vrf *zvrf = rtadv_interface_get_zvrf(zif->ifp);
2800
2801 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
2802 if (zif->rtadv.AdvSendAdvertisements &&
2803 (zif->rtadv.MaxRtrAdvInterval >= 1000) &&
2804 zif->rtadv.UseFastRexmit) {
2805 zif->rtadv.inFastRexmit = 1;
2806 zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
2807 }
2808
2809 /*
2810 * startup the state machine, if it hasn't been already
2811 * due to a delayed ifindex on startup ordering
2812 */
2813 if (zif->rtadv.AdvSendAdvertisements)
2814 rtadv_start_interface_events(zvrf, zif);
2815 }
2816
2817 void rtadv_if_init(struct zebra_if *zif)
2818 {
2819 /* Set default router advertise values. */
2820 struct rtadvconf *rtadv;
2821
2822 rtadv = &zif->rtadv;
2823
2824 rtadv->AdvSendAdvertisements = 0;
2825 rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
2826 rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
2827 rtadv->AdvIntervalTimer = 0;
2828 rtadv->AdvManagedFlag = 0;
2829 rtadv->AdvOtherConfigFlag = 0;
2830 rtadv->AdvHomeAgentFlag = 0;
2831 rtadv->AdvLinkMTU = 0;
2832 rtadv->AdvReachableTime = 0;
2833 rtadv->AdvRetransTimer = 0;
2834 rtadv->AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
2835 memset(&rtadv->lastadvcurhoplimit, 0,
2836 sizeof(rtadv->lastadvcurhoplimit));
2837 memset(&rtadv->lastadvmanagedflag, 0,
2838 sizeof(rtadv->lastadvmanagedflag));
2839 memset(&rtadv->lastadvotherconfigflag, 0,
2840 sizeof(rtadv->lastadvotherconfigflag));
2841 memset(&rtadv->lastadvreachabletime, 0,
2842 sizeof(rtadv->lastadvreachabletime));
2843 memset(&rtadv->lastadvretranstimer, 0,
2844 sizeof(rtadv->lastadvretranstimer));
2845 rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */
2846 rtadv->HomeAgentPreference = 0;
2847 rtadv->HomeAgentLifetime = -1; /* derive from AdvDefaultLifetime */
2848 rtadv->AdvIntervalOption = 0;
2849 rtadv->UseFastRexmit = true;
2850 rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
2851
2852 rtadv_prefixes_init(rtadv->prefixes);
2853
2854 rtadv->AdvRDNSSList = list_new();
2855 rtadv->AdvDNSSLList = list_new();
2856 }
2857
2858 void rtadv_if_fini(struct zebra_if *zif)
2859 {
2860 struct rtadvconf *rtadv;
2861 struct rtadv_prefix *rp;
2862
2863 rtadv = &zif->rtadv;
2864
2865 while ((rp = rtadv_prefixes_pop(rtadv->prefixes)))
2866 rtadv_prefix_free(rp);
2867
2868 list_delete(&rtadv->AdvRDNSSList);
2869 list_delete(&rtadv->AdvDNSSLList);
2870 }
2871
2872 void rtadv_vrf_init(struct zebra_vrf *zvrf)
2873 {
2874 if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
2875 return;
2876
2877 zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
2878 }
2879
2880 void rtadv_vrf_terminate(struct zebra_vrf *zvrf)
2881 {
2882 if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
2883 return;
2884
2885 rtadv_event(zvrf, RTADV_STOP, 0);
2886 if (zvrf->rtadv.sock >= 0) {
2887 close(zvrf->rtadv.sock);
2888 zvrf->rtadv.sock = -1;
2889 }
2890
2891 adv_if_clean(zvrf);
2892 adv_msec_if_clean(zvrf);
2893 }
2894
2895 void rtadv_cmd_init(void)
2896 {
2897 interfaces_configured_for_ra_from_bgp = 0;
2898
2899 hook_register(zebra_if_extra_info, nd_dump_vty);
2900 hook_register(zebra_if_config_wr, rtadv_config_write);
2901
2902 install_element(VIEW_NODE, &show_ipv6_nd_ra_if_cmd);
2903
2904 install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
2905 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
2906 install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
2907 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_retrans_interval_cmd);
2908 install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd);
2909 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_hop_limit_cmd);
2910 install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
2911 install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
2912 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
2913 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
2914 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
2915 install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
2916 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
2917 install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
2918 install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
2919 install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
2920 install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
2921 install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
2922 install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
2923 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
2924 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
2925 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
2926 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
2927 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
2928 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
2929 install_element(INTERFACE_NODE,
2930 &ipv6_nd_adv_interval_config_option_cmd);
2931 install_element(INTERFACE_NODE,
2932 &no_ipv6_nd_adv_interval_config_option_cmd);
2933 install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
2934 install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
2935 install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
2936 install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
2937 install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
2938 install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
2939 install_element(INTERFACE_NODE, &ipv6_nd_rdnss_cmd);
2940 install_element(INTERFACE_NODE, &no_ipv6_nd_rdnss_cmd);
2941 install_element(INTERFACE_NODE, &ipv6_nd_dnssl_cmd);
2942 install_element(INTERFACE_NODE, &no_ipv6_nd_dnssl_cmd);
2943 }
2944
2945 static int if_join_all_router(int sock, struct interface *ifp)
2946 {
2947 int ret;
2948
2949 struct ipv6_mreq mreq;
2950
2951 memset(&mreq, 0, sizeof(mreq));
2952 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2953 mreq.ipv6mr_interface = ifp->ifindex;
2954
2955 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq,
2956 sizeof(mreq));
2957 if (ret < 0)
2958 flog_err_sys(EC_LIB_SOCKET,
2959 "%s(%u): Failed to join group, socket %u error %s",
2960 ifp->name, ifp->ifindex, sock,
2961 safe_strerror(errno));
2962
2963 if (IS_ZEBRA_DEBUG_EVENT)
2964 zlog_debug(
2965 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2966 ifp->name, ifp->vrf->name, ifp->ifindex, sock);
2967
2968 return 0;
2969 }
2970
2971 static int if_leave_all_router(int sock, struct interface *ifp)
2972 {
2973 int ret;
2974
2975 struct ipv6_mreq mreq;
2976
2977 memset(&mreq, 0, sizeof(mreq));
2978 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2979 mreq.ipv6mr_interface = ifp->ifindex;
2980
2981 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
2982 sizeof(mreq));
2983 if (ret < 0)
2984 flog_err_sys(
2985 EC_LIB_SOCKET,
2986 "%s(%s:%u): Failed to leave group, socket %u error %s",
2987 ifp->name, ifp->vrf->name, ifp->ifindex, sock,
2988 safe_strerror(errno));
2989
2990 if (IS_ZEBRA_DEBUG_EVENT)
2991 zlog_debug(
2992 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
2993 ifp->name, ifp->vrf->name, ifp->ifindex, sock);
2994
2995 return 0;
2996 }
2997
2998 bool rtadv_compiled_in(void)
2999 {
3000 return true;
3001 }
3002
3003 #else /* !HAVE_RTADV */
3004 /*
3005 * If the end user does not have RADV enabled we should
3006 * handle this better
3007 */
3008 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
3009 {
3010 if (IS_ZEBRA_DEBUG_PACKET)
3011 zlog_debug(
3012 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3013 zserv_command_string(hdr->command));
3014
3015 return;
3016 }
3017
3018 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
3019 {
3020 if (IS_ZEBRA_DEBUG_PACKET)
3021 zlog_debug(
3022 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3023 zserv_command_string(hdr->command));
3024
3025 return;
3026 }
3027
3028 bool rtadv_compiled_in(void)
3029 {
3030 return false;
3031 }
3032
3033 #endif /* HAVE_RTADV */
3034
3035 uint32_t rtadv_get_interfaces_configured_from_bgp(void)
3036 {
3037 return interfaces_configured_for_ra_from_bgp;
3038 }