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