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