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