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