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