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