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