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