]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rtadv.c
5eebca163b5c1a275c563b0982570da06f3f65cc
[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
39 #include "zebra/interface.h"
40 #include "zebra/rtadv.h"
41 #include "zebra/debug.h"
42 #include "zebra/rib.h"
43 #include "zebra/zserv.h"
44 #include "zebra/zebra_ns.h"
45 #include "zebra/zebra_vrf.h"
46
47 extern struct zebra_privs_t zserv_privs;
48
49 #if defined(HAVE_RTADV)
50
51 #ifdef OPEN_BSD
52 #include <netinet/icmp6.h>
53 #endif
54
55 /* If RFC2133 definition is used. */
56 #ifndef IPV6_JOIN_GROUP
57 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
58 #endif
59 #ifndef IPV6_LEAVE_GROUP
60 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
61 #endif
62
63 #define ALLNODE "ff02::1"
64 #define ALLROUTER "ff02::2"
65
66 /* Order is intentional. Matches RFC4191. This array is also used for
67 command matching, so only modify with care. */
68 const char *rtadv_pref_strs[] = {"medium", "high", "INVALID", "low", 0};
69
70 enum rtadv_event {
71 RTADV_START,
72 RTADV_STOP,
73 RTADV_TIMER,
74 RTADV_TIMER_MSEC,
75 RTADV_READ
76 };
77
78 static void rtadv_event(struct zebra_ns *, enum rtadv_event, int);
79
80 static int if_join_all_router(int, struct interface *);
81 static int if_leave_all_router(int, struct interface *);
82
83 static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
84 {
85 int ret = -1;
86 struct interface *iface;
87 struct zebra_if *zif;
88
89 iface = if_lookup_by_index_per_ns(zns, *ifindex);
90 if (iface && iface->info) {
91 zif = iface->info;
92 zif->ra_rcvd++;
93 ret = 0;
94 }
95 return ret;
96 }
97
98 static int rtadv_recv_packet(struct zebra_ns *zns, int sock, u_char *buf,
99 int buflen, struct sockaddr_in6 *from,
100 ifindex_t *ifindex, int *hoplimit)
101 {
102 int ret;
103 struct msghdr msg;
104 struct iovec iov;
105 struct cmsghdr *cmsgptr;
106 struct in6_addr dst;
107
108 char adata[1024];
109
110 /* Fill in message and iovec. */
111 memset(&msg, 0, sizeof(msg));
112 msg.msg_name = (void *)from;
113 msg.msg_namelen = sizeof(struct sockaddr_in6);
114 msg.msg_iov = &iov;
115 msg.msg_iovlen = 1;
116 msg.msg_control = (void *)adata;
117 msg.msg_controllen = sizeof adata;
118 iov.iov_base = buf;
119 iov.iov_len = buflen;
120
121 /* If recvmsg fail return minus value. */
122 ret = recvmsg(sock, &msg, 0);
123 if (ret < 0)
124 return ret;
125
126 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
127 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
128 /* I want interface index which this packet comes from. */
129 if (cmsgptr->cmsg_level == IPPROTO_IPV6
130 && cmsgptr->cmsg_type == IPV6_PKTINFO) {
131 struct in6_pktinfo *ptr;
132
133 ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
134 *ifindex = ptr->ipi6_ifindex;
135 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
136 }
137
138 /* Incoming packet's hop limit. */
139 if (cmsgptr->cmsg_level == IPPROTO_IPV6
140 && cmsgptr->cmsg_type == IPV6_HOPLIMIT) {
141 int *hoptr = (int *)CMSG_DATA(cmsgptr);
142 *hoplimit = *hoptr;
143 }
144 }
145
146 rtadv_increment_received(zns, ifindex);
147 return ret;
148 }
149
150 #define RTADV_MSG_SIZE 4096
151
152 /* Send router advertisement packet. */
153 static void rtadv_send_packet(int sock, struct interface *ifp)
154 {
155 struct msghdr msg;
156 struct iovec iov;
157 struct cmsghdr *cmsgptr;
158 struct in6_pktinfo *pkt;
159 struct sockaddr_in6 addr;
160 static void *adata = NULL;
161 unsigned char buf[RTADV_MSG_SIZE];
162 struct nd_router_advert *rtadv;
163 int ret;
164 int len = 0;
165 struct zebra_if *zif;
166 struct rtadv_prefix *rprefix;
167 u_char all_nodes_addr[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
168 0, 0, 0, 0, 0, 0, 0, 1};
169 struct listnode *node;
170 u_int16_t pkt_RouterLifetime;
171
172 /*
173 * Allocate control message bufffer. This is dynamic because
174 * CMSG_SPACE is not guaranteed not to call a function. Note that
175 * the size will be different on different architectures due to
176 * differing alignment rules.
177 */
178 if (adata == NULL) {
179 /* XXX Free on shutdown. */
180 adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
181
182 if (adata == NULL) {
183 zlog_err(
184 "rtadv_send_packet: can't malloc control data");
185 exit(-1);
186 }
187 }
188
189 /* Logging of packet. */
190 if (IS_ZEBRA_DEBUG_PACKET)
191 zlog_debug("%s(%u): Tx RA, socket %u", ifp->name, ifp->ifindex,
192 sock);
193
194 /* Fill in sockaddr_in6. */
195 memset(&addr, 0, sizeof(struct sockaddr_in6));
196 addr.sin6_family = AF_INET6;
197 #ifdef SIN6_LEN
198 addr.sin6_len = sizeof(struct sockaddr_in6);
199 #endif /* SIN6_LEN */
200 addr.sin6_port = htons(IPPROTO_ICMPV6);
201 IPV6_ADDR_COPY(&addr.sin6_addr, all_nodes_addr);
202
203 /* Fetch interface information. */
204 zif = ifp->info;
205
206 /* Make router advertisement message. */
207 rtadv = (struct nd_router_advert *)buf;
208
209 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
210 rtadv->nd_ra_code = 0;
211 rtadv->nd_ra_cksum = 0;
212
213 rtadv->nd_ra_curhoplimit = 64;
214
215 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
216 rtadv->nd_ra_flags_reserved = zif->rtadv.AdvDefaultLifetime == 0
217 ? 0
218 : zif->rtadv.DefaultPreference;
219 rtadv->nd_ra_flags_reserved <<= 3;
220
221 if (zif->rtadv.AdvManagedFlag)
222 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
223 if (zif->rtadv.AdvOtherConfigFlag)
224 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
225 if (zif->rtadv.AdvHomeAgentFlag)
226 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
227 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
228 * AdvDefaultLifetime is by default based on the value of
229 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
230 * field of Router Advertisements. Given that this field is expressed
231 * in seconds, a small MaxRtrAdvInterval value can result in a zero
232 * value for this field. To prevent this, routers SHOULD keep
233 * AdvDefaultLifetime in at least one second, even if the use of
234 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
235 pkt_RouterLifetime =
236 zif->rtadv.AdvDefaultLifetime != -1
237 ? zif->rtadv.AdvDefaultLifetime
238 : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
239 rtadv->nd_ra_router_lifetime = htons(pkt_RouterLifetime);
240 rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime);
241 rtadv->nd_ra_retransmit = htonl(0);
242
243 len = sizeof(struct nd_router_advert);
244
245 /* If both the Home Agent Preference and Home Agent Lifetime are set to
246 * their default values specified above, this option SHOULD NOT be
247 * included in the Router Advertisement messages sent by this home
248 * agent. -- RFC6275, 7.4 */
249 if (zif->rtadv.AdvHomeAgentFlag
250 && (zif->rtadv.HomeAgentPreference
251 || zif->rtadv.HomeAgentLifetime != -1)) {
252 struct nd_opt_homeagent_info *ndopt_hai =
253 (struct nd_opt_homeagent_info *)(buf + len);
254 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
255 ndopt_hai->nd_opt_hai_len = 1;
256 ndopt_hai->nd_opt_hai_reserved = 0;
257 ndopt_hai->nd_opt_hai_preference =
258 htons(zif->rtadv.HomeAgentPreference);
259 /* 16-bit unsigned integer. The lifetime associated with the
260 * home
261 * agent in units of seconds. The default value is the same as
262 * the
263 * Router Lifetime, as specified in the main body of the Router
264 * Advertisement. The maximum value corresponds to 18.2 hours.
265 * A
266 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
267 ndopt_hai->nd_opt_hai_lifetime =
268 htons(zif->rtadv.HomeAgentLifetime != -1
269 ? zif->rtadv.HomeAgentLifetime
270 : MAX(1, pkt_RouterLifetime) /* 0 is OK
271 for RL,
272 but not
273 for HAL*/
274 );
275 len += sizeof(struct nd_opt_homeagent_info);
276 }
277
278 if (zif->rtadv.AdvIntervalOption) {
279 struct nd_opt_adv_interval *ndopt_adv =
280 (struct nd_opt_adv_interval *)(buf + len);
281 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
282 ndopt_adv->nd_opt_ai_len = 1;
283 ndopt_adv->nd_opt_ai_reserved = 0;
284 ndopt_adv->nd_opt_ai_interval =
285 htonl(zif->rtadv.MaxRtrAdvInterval);
286 len += sizeof(struct nd_opt_adv_interval);
287 }
288
289 /* Fill in prefix. */
290 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) {
291 struct nd_opt_prefix_info *pinfo;
292
293 pinfo = (struct nd_opt_prefix_info *)(buf + len);
294
295 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
296 pinfo->nd_opt_pi_len = 4;
297 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
298
299 pinfo->nd_opt_pi_flags_reserved = 0;
300 if (rprefix->AdvOnLinkFlag)
301 pinfo->nd_opt_pi_flags_reserved |=
302 ND_OPT_PI_FLAG_ONLINK;
303 if (rprefix->AdvAutonomousFlag)
304 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
305 if (rprefix->AdvRouterAddressFlag)
306 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
307
308 pinfo->nd_opt_pi_valid_time = htonl(rprefix->AdvValidLifetime);
309 pinfo->nd_opt_pi_preferred_time =
310 htonl(rprefix->AdvPreferredLifetime);
311 pinfo->nd_opt_pi_reserved2 = 0;
312
313 IPV6_ADDR_COPY(&pinfo->nd_opt_pi_prefix,
314 &rprefix->prefix.prefix);
315
316 #ifdef DEBUG
317 {
318 u_char buf[INET6_ADDRSTRLEN];
319
320 zlog_debug("DEBUG %s",
321 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
322 buf, INET6_ADDRSTRLEN));
323 }
324 #endif /* DEBUG */
325
326 len += sizeof(struct nd_opt_prefix_info);
327 }
328
329 /* Hardware address. */
330 if (ifp->hw_addr_len != 0) {
331 buf[len++] = ND_OPT_SOURCE_LINKADDR;
332
333 /* Option length should be rounded up to next octet if
334 the link address does not end on an octet boundary. */
335 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
336
337 memcpy(buf + len, ifp->hw_addr, ifp->hw_addr_len);
338 len += ifp->hw_addr_len;
339
340 /* Pad option to end on an octet boundary. */
341 memset(buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
342 len += -(ifp->hw_addr_len + 2) & 0x7;
343 }
344
345 /* MTU */
346 if (zif->rtadv.AdvLinkMTU) {
347 struct nd_opt_mtu *opt = (struct nd_opt_mtu *)(buf + len);
348 opt->nd_opt_mtu_type = ND_OPT_MTU;
349 opt->nd_opt_mtu_len = 1;
350 opt->nd_opt_mtu_reserved = 0;
351 opt->nd_opt_mtu_mtu = htonl(zif->rtadv.AdvLinkMTU);
352 len += sizeof(struct nd_opt_mtu);
353 }
354
355 msg.msg_name = (void *)&addr;
356 msg.msg_namelen = sizeof(struct sockaddr_in6);
357 msg.msg_iov = &iov;
358 msg.msg_iovlen = 1;
359 msg.msg_control = (void *)adata;
360 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
361 msg.msg_flags = 0;
362 iov.iov_base = buf;
363 iov.iov_len = len;
364
365 cmsgptr = ZCMSG_FIRSTHDR(&msg);
366 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
367 cmsgptr->cmsg_level = IPPROTO_IPV6;
368 cmsgptr->cmsg_type = IPV6_PKTINFO;
369
370 pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
371 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
372 pkt->ipi6_ifindex = ifp->ifindex;
373
374 ret = sendmsg(sock, &msg, 0);
375 if (ret < 0) {
376 zlog_err("%s(%u): Tx RA failed, socket %u error %d (%s)",
377 ifp->name, ifp->ifindex, sock, errno,
378 safe_strerror(errno));
379 } else
380 zif->ra_sent++;
381 }
382
383 static int rtadv_timer(struct thread *thread)
384 {
385 struct zebra_ns *zns = THREAD_ARG(thread);
386 struct vrf *vrf;
387 struct interface *ifp;
388 struct zebra_if *zif;
389 int period;
390
391 zns->rtadv.ra_timer = NULL;
392 if (zns->rtadv.adv_msec_if_count == 0) {
393 period = 1000; /* 1 s */
394 rtadv_event(zns, RTADV_TIMER, 1 /* 1 s */);
395 } else {
396 period = 10; /* 10 ms */
397 rtadv_event(zns, RTADV_TIMER_MSEC, 10 /* 10 ms */);
398 }
399
400 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
401 FOR_ALL_INTERFACES (vrf, ifp) {
402 if (if_is_loopback(ifp)
403 || CHECK_FLAG(ifp->status,
404 ZEBRA_INTERFACE_VRF_LOOPBACK)
405 || !if_is_operative(ifp))
406 continue;
407
408 zif = ifp->info;
409
410 if (zif->rtadv.AdvSendAdvertisements) {
411 if (zif->rtadv.inFastRexmit) {
412 /* We assume we fast rexmit every sec so
413 * no
414 * additional vars */
415 if (--zif->rtadv.NumFastReXmitsRemain
416 <= 0)
417 zif->rtadv.inFastRexmit = 0;
418
419 if (IS_ZEBRA_DEBUG_SEND)
420 zlog_debug(
421 "Fast RA Rexmit on interface %s",
422 ifp->name);
423
424 rtadv_send_packet(zns->rtadv.sock, ifp);
425 } else {
426 zif->rtadv.AdvIntervalTimer -= period;
427 if (zif->rtadv.AdvIntervalTimer <= 0) {
428 /* FIXME: using
429 MaxRtrAdvInterval each
430 time isn't what section
431 6.2.4 of RFC4861 tells to do.
432 */
433 zif->rtadv.AdvIntervalTimer =
434 zif->rtadv
435 .MaxRtrAdvInterval;
436 rtadv_send_packet(
437 zns->rtadv.sock, ifp);
438 }
439 }
440 }
441 }
442
443 return 0;
444 }
445
446 static void rtadv_process_solicit(struct interface *ifp)
447 {
448 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
449 struct zebra_ns *zns = zvrf->zns;
450
451 assert(zns);
452 rtadv_send_packet(zns->rtadv.sock, ifp);
453 }
454
455 static void rtadv_process_advert(u_char *msg, unsigned int len,
456 struct interface *ifp,
457 struct sockaddr_in6 *addr)
458 {
459 struct nd_router_advert *radvert;
460 char addr_str[INET6_ADDRSTRLEN];
461 struct zebra_if *zif;
462 struct prefix p;
463
464 zif = ifp->info;
465
466 inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
467
468 if (len < sizeof(struct nd_router_advert)) {
469 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
470 ifp->name, ifp->ifindex, len, addr_str);
471 return;
472 }
473 if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
474 zlog_warn(
475 "%s(%u): Rx RA with non-linklocal source address from %s",
476 ifp->name, ifp->ifindex, addr_str);
477 return;
478 }
479
480 radvert = (struct nd_router_advert *)msg;
481
482 if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit)
483 && (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) {
484 zlog_warn(
485 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
486 ifp->name, ifp->ifindex, addr_str);
487 }
488
489 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
490 && !zif->rtadv.AdvManagedFlag) {
491 zlog_warn(
492 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
493 ifp->name, ifp->ifindex, addr_str);
494 }
495
496 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
497 && !zif->rtadv.AdvOtherConfigFlag) {
498 zlog_warn(
499 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
500 ifp->name, ifp->ifindex, addr_str);
501 }
502
503 if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime)
504 && (ntohl(radvert->nd_ra_reachable)
505 != zif->rtadv.AdvReachableTime)) {
506 zlog_warn(
507 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
508 ifp->name, ifp->ifindex, addr_str);
509 }
510
511 if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer)
512 && (ntohl(radvert->nd_ra_retransmit)
513 != (unsigned int)zif->rtadv.AdvRetransTimer)) {
514 zlog_warn(
515 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
516 ifp->name, ifp->ifindex, addr_str);
517 }
518
519 /* Create entry for neighbor if not known. */
520 p.family = AF_INET6;
521 IPV6_ADDR_COPY(&p.u.prefix, &addr->sin6_addr);
522 p.prefixlen = IPV6_MAX_PREFIXLEN;
523
524 if (!nbr_connected_check(ifp, &p))
525 nbr_connected_add_ipv6(ifp, &addr->sin6_addr);
526 }
527
528
529 static void rtadv_process_packet(u_char *buf, unsigned int len,
530 ifindex_t ifindex, int hoplimit,
531 struct sockaddr_in6 *from,
532 struct zebra_ns *zns)
533 {
534 struct icmp6_hdr *icmph;
535 struct interface *ifp;
536 struct zebra_if *zif;
537 char addr_str[INET6_ADDRSTRLEN];
538
539 inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
540
541 /* Interface search. */
542 ifp = if_lookup_by_index_per_ns(zns, ifindex);
543 if (ifp == NULL) {
544 zlog_warn("RA/RS received on unknown IF %u from %s", ifindex,
545 addr_str);
546 return;
547 }
548
549 if (IS_ZEBRA_DEBUG_PACKET)
550 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp->name,
551 ifp->ifindex, len, addr_str);
552
553 if (if_is_loopback(ifp)
554 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
555 return;
556
557 /* Check interface configuration. */
558 zif = ifp->info;
559 if (!zif->rtadv.AdvSendAdvertisements)
560 return;
561
562 /* ICMP message length check. */
563 if (len < sizeof(struct icmp6_hdr)) {
564 zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
565 ifp->name, ifp->ifindex, len);
566 return;
567 }
568
569 icmph = (struct icmp6_hdr *)buf;
570
571 /* ICMP message type check. */
572 if (icmph->icmp6_type != ND_ROUTER_SOLICIT
573 && icmph->icmp6_type != ND_ROUTER_ADVERT) {
574 zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
575 ifp->name, ifp->ifindex, icmph->icmp6_type);
576 return;
577 }
578
579 /* Hoplimit check. */
580 if (hoplimit >= 0 && hoplimit != 255) {
581 zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp->name,
582 ifp->ifindex, hoplimit);
583 return;
584 }
585
586 /* Check ICMP message type. */
587 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
588 rtadv_process_solicit(ifp);
589 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
590 rtadv_process_advert(buf, len, ifp, from);
591
592 return;
593 }
594
595 static int rtadv_read(struct thread *thread)
596 {
597 int sock;
598 int len;
599 u_char buf[RTADV_MSG_SIZE];
600 struct sockaddr_in6 from;
601 ifindex_t ifindex = 0;
602 int hoplimit = -1;
603 struct zebra_ns *zns = THREAD_ARG(thread);
604
605 sock = THREAD_FD(thread);
606 zns->rtadv.ra_read = NULL;
607
608 /* Register myself. */
609 rtadv_event(zns, RTADV_READ, sock);
610
611 len = rtadv_recv_packet(zns, sock, buf, sizeof(buf), &from, &ifindex,
612 &hoplimit);
613
614 if (len < 0) {
615 zlog_warn("RA/RS recv failed, socket %u error %s", sock,
616 safe_strerror(errno));
617 return len;
618 }
619
620 rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zns);
621
622 return 0;
623 }
624
625 static int rtadv_make_socket(ns_id_t ns_id)
626 {
627 int sock;
628 int ret = 0;
629 struct icmp6_filter filter;
630
631 if (zserv_privs.change(ZPRIVS_RAISE))
632 zlog_err("rtadv_make_socket: could not raise privs, %s",
633 safe_strerror(errno));
634
635 sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
636
637 if (zserv_privs.change(ZPRIVS_LOWER))
638 zlog_err("rtadv_make_socket: could not lower privs, %s",
639 safe_strerror(errno));
640
641 if (sock < 0) {
642 return -1;
643 }
644
645 ret = setsockopt_ipv6_pktinfo(sock, 1);
646 if (ret < 0) {
647 close(sock);
648 return ret;
649 }
650 ret = setsockopt_ipv6_multicast_loop(sock, 0);
651 if (ret < 0) {
652 close(sock);
653 return ret;
654 }
655 ret = setsockopt_ipv6_unicast_hops(sock, 255);
656 if (ret < 0) {
657 close(sock);
658 return ret;
659 }
660 ret = setsockopt_ipv6_multicast_hops(sock, 255);
661 if (ret < 0) {
662 close(sock);
663 return ret;
664 }
665 ret = setsockopt_ipv6_hoplimit(sock, 1);
666 if (ret < 0) {
667 close(sock);
668 return ret;
669 }
670
671 ICMP6_FILTER_SETBLOCKALL(&filter);
672 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
673 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
674
675 ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
676 sizeof(struct icmp6_filter));
677 if (ret < 0) {
678 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno));
679 close(sock);
680 return ret;
681 }
682
683 return sock;
684 }
685
686 static struct rtadv_prefix *rtadv_prefix_new(void)
687 {
688 return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix));
689 }
690
691 static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix)
692 {
693 XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix);
694 }
695
696 static struct rtadv_prefix *rtadv_prefix_lookup(struct list *rplist,
697 struct prefix_ipv6 *p)
698 {
699 struct listnode *node;
700 struct rtadv_prefix *rprefix;
701
702 for (ALL_LIST_ELEMENTS_RO(rplist, node, rprefix))
703 if (prefix_same((struct prefix *)&rprefix->prefix,
704 (struct prefix *)p))
705 return rprefix;
706 return NULL;
707 }
708
709 static struct rtadv_prefix *rtadv_prefix_get(struct list *rplist,
710 struct prefix_ipv6 *p)
711 {
712 struct rtadv_prefix *rprefix;
713
714 rprefix = rtadv_prefix_lookup(rplist, p);
715 if (rprefix)
716 return rprefix;
717
718 rprefix = rtadv_prefix_new();
719 memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6));
720 listnode_add(rplist, rprefix);
721
722 return rprefix;
723 }
724
725 static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
726 {
727 struct rtadv_prefix *rprefix;
728
729 rprefix = rtadv_prefix_get(zif->rtadv.AdvPrefixList, &rp->prefix);
730
731 /* Set parameters. */
732 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
733 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
734 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
735 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
736 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
737 }
738
739 static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
740 {
741 struct rtadv_prefix *rprefix;
742
743 rprefix = rtadv_prefix_lookup(zif->rtadv.AdvPrefixList, &rp->prefix);
744 if (rprefix != NULL) {
745 listnode_delete(zif->rtadv.AdvPrefixList, (void *)rprefix);
746 rtadv_prefix_free(rprefix);
747 return 1;
748 } else
749 return 0;
750 }
751
752 static void ipv6_nd_suppress_ra_set(struct interface *ifp,
753 ipv6_nd_suppress_ra_status status)
754 {
755 struct zebra_if *zif;
756 struct zebra_vrf *zvrf;
757 struct zebra_ns *zns;
758
759 zif = ifp->info;
760 zvrf = vrf_info_lookup(ifp->vrf_id);
761 zns = zvrf->zns;
762
763 if (status == RA_SUPPRESS) {
764 /* RA is currently enabled */
765 if (zif->rtadv.AdvSendAdvertisements) {
766 zif->rtadv.AdvSendAdvertisements = 0;
767 zif->rtadv.AdvIntervalTimer = 0;
768 zns->rtadv.adv_if_count--;
769
770 if_leave_all_router(zns->rtadv.sock, ifp);
771
772 if (zns->rtadv.adv_if_count == 0)
773 rtadv_event(zns, RTADV_STOP, 0);
774 }
775 } else {
776 if (!zif->rtadv.AdvSendAdvertisements) {
777 zif->rtadv.AdvSendAdvertisements = 1;
778 zif->rtadv.AdvIntervalTimer = 0;
779 zns->rtadv.adv_if_count++;
780
781 if (zif->rtadv.MaxRtrAdvInterval >= 1000) {
782 /* Enable Fast RA only when RA interval is in
783 * secs */
784 zif->rtadv.inFastRexmit = 1;
785 zif->rtadv.NumFastReXmitsRemain =
786 RTADV_NUM_FAST_REXMITS;
787 }
788
789 if_join_all_router(zns->rtadv.sock, ifp);
790
791 if (zns->rtadv.adv_if_count == 1)
792 rtadv_event(zns, RTADV_START, zns->rtadv.sock);
793 }
794 }
795 }
796
797 /*
798 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
799 * Note that while the client could request RA on an interface on which the
800 * operator has not enabled RA, RA won't be disabled upon client request
801 * if the operator has explicitly enabled RA. The enable request can also
802 * specify a RA interval (in seconds).
803 */
804 void zebra_interface_radv_set(struct zserv *client, u_short length,
805 struct zebra_vrf *zvrf, int enable)
806 {
807 struct stream *s;
808 ifindex_t ifindex;
809 struct interface *ifp;
810 struct zebra_if *zif;
811 int ra_interval;
812
813 s = client->ibuf;
814
815 /* Get interface index and RA interval. */
816 STREAM_GETL(s, ifindex);
817 STREAM_GETL(s, ra_interval);
818
819 if (IS_ZEBRA_DEBUG_EVENT)
820 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
821 zvrf_id(zvrf), ifindex,
822 enable ? "enable" : "disable",
823 zebra_route_string(client->proto), ra_interval);
824
825 /* Locate interface and check VRF match. */
826 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex);
827 if (!ifp) {
828 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
829 zvrf_id(zvrf), ifindex, enable ? "enable" : "disable",
830 zebra_route_string(client->proto));
831 return;
832 }
833 if (ifp->vrf_id != zvrf_id(zvrf)) {
834 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
835 zvrf_id(zvrf), ifindex, enable ? "enable" : "disable",
836 zebra_route_string(client->proto), ifp->vrf_id);
837 return;
838 }
839
840 zif = ifp->info;
841 if (enable) {
842 SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
843 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
844 if (ra_interval
845 && (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval
846 && !CHECK_FLAG(zif->rtadv.ra_configured,
847 VTY_RA_INTERVAL_CONFIGURED))
848 zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
849 } else {
850 UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
851 if (!CHECK_FLAG(zif->rtadv.ra_configured,
852 VTY_RA_INTERVAL_CONFIGURED))
853 zif->rtadv.MaxRtrAdvInterval =
854 RTADV_MAX_RTR_ADV_INTERVAL;
855 if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
856 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
857 }
858 stream_failure:
859 return;
860 }
861
862 DEFUN (ipv6_nd_suppress_ra,
863 ipv6_nd_suppress_ra_cmd,
864 "ipv6 nd suppress-ra",
865 "Interface IPv6 config commands\n"
866 "Neighbor discovery\n"
867 "Suppress Router Advertisement\n")
868 {
869 VTY_DECLVAR_CONTEXT(interface, ifp);
870 struct zebra_if *zif = ifp->info;
871
872 if (if_is_loopback(ifp)
873 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
874 vty_out(vty,
875 "Cannot configure IPv6 Router Advertisements on this interface\n");
876 return CMD_WARNING_CONFIG_FAILED;
877 }
878
879 if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
880 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
881
882 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
883 return CMD_SUCCESS;
884 }
885
886 DEFUN (no_ipv6_nd_suppress_ra,
887 no_ipv6_nd_suppress_ra_cmd,
888 "no ipv6 nd suppress-ra",
889 NO_STR
890 "Interface IPv6 config commands\n"
891 "Neighbor discovery\n"
892 "Suppress Router Advertisement\n")
893 {
894 VTY_DECLVAR_CONTEXT(interface, ifp);
895 struct zebra_if *zif = ifp->info;
896
897 if (if_is_loopback(ifp)
898 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
899 vty_out(vty,
900 "Cannot configure IPv6 Router Advertisements on this interface\n");
901 return CMD_WARNING_CONFIG_FAILED;
902 }
903
904 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
905 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
906 return CMD_SUCCESS;
907 }
908
909 DEFUN (ipv6_nd_ra_interval_msec,
910 ipv6_nd_ra_interval_msec_cmd,
911 "ipv6 nd ra-interval msec (70-1800000)",
912 "Interface IPv6 config commands\n"
913 "Neighbor discovery\n"
914 "Router Advertisement interval\n"
915 "Router Advertisement interval in milliseconds\n"
916 "Router Advertisement interval in milliseconds\n")
917 {
918 int idx_number = 4;
919 VTY_DECLVAR_CONTEXT(interface, ifp);
920 unsigned interval;
921 struct zebra_if *zif = ifp->info;
922 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
923 struct zebra_ns *zns;
924
925 zns = zvrf->zns;
926 interval = strtoul(argv[idx_number]->arg, NULL, 10);
927 if ((zif->rtadv.AdvDefaultLifetime != -1
928 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
929 vty_out(vty,
930 "This ra-interval would conflict with configured ra-lifetime!\n");
931 return CMD_WARNING_CONFIG_FAILED;
932 }
933
934 if (zif->rtadv.MaxRtrAdvInterval % 1000)
935 zns->rtadv.adv_msec_if_count--;
936
937 if (interval % 1000)
938 zns->rtadv.adv_msec_if_count++;
939
940 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
941 zif->rtadv.MaxRtrAdvInterval = interval;
942 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
943 zif->rtadv.AdvIntervalTimer = 0;
944
945 return CMD_SUCCESS;
946 }
947
948 DEFUN (ipv6_nd_ra_interval,
949 ipv6_nd_ra_interval_cmd,
950 "ipv6 nd ra-interval (1-1800)",
951 "Interface IPv6 config commands\n"
952 "Neighbor discovery\n"
953 "Router Advertisement interval\n"
954 "Router Advertisement interval in seconds\n")
955 {
956 int idx_number = 3;
957 VTY_DECLVAR_CONTEXT(interface, ifp);
958 unsigned interval;
959 struct zebra_if *zif = ifp->info;
960 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
961 struct zebra_ns *zns;
962
963 zns = zvrf->zns;
964 interval = strtoul(argv[idx_number]->arg, NULL, 10);
965 if ((zif->rtadv.AdvDefaultLifetime != -1
966 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
967 vty_out(vty,
968 "This ra-interval would conflict with configured ra-lifetime!\n");
969 return CMD_WARNING_CONFIG_FAILED;
970 }
971
972 if (zif->rtadv.MaxRtrAdvInterval % 1000)
973 zns->rtadv.adv_msec_if_count--;
974
975 /* convert to milliseconds */
976 interval = interval * 1000;
977
978 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
979 zif->rtadv.MaxRtrAdvInterval = interval;
980 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
981 zif->rtadv.AdvIntervalTimer = 0;
982
983 return CMD_SUCCESS;
984 }
985
986 DEFUN (no_ipv6_nd_ra_interval,
987 no_ipv6_nd_ra_interval_cmd,
988 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
989 NO_STR
990 "Interface IPv6 config commands\n"
991 "Neighbor discovery\n"
992 "Router Advertisement interval\n"
993 "Router Advertisement interval in seconds\n"
994 "Specify millisecond router advertisement interval\n"
995 "Router Advertisement interval in milliseconds\n")
996 {
997 VTY_DECLVAR_CONTEXT(interface, ifp);
998 struct zebra_if *zif = ifp->info;
999 struct zebra_vrf *zvrf;
1000 struct zebra_ns *zns;
1001
1002 zvrf = vrf_info_lookup(ifp->vrf_id);
1003 zns = zvrf->zns;
1004
1005 if (zif->rtadv.MaxRtrAdvInterval % 1000)
1006 zns->rtadv.adv_msec_if_count--;
1007
1008 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1009
1010 if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1011 zif->rtadv.MaxRtrAdvInterval = 10000;
1012 else
1013 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
1014
1015 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
1016 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
1017
1018 return CMD_SUCCESS;
1019 }
1020
1021 DEFUN (ipv6_nd_ra_lifetime,
1022 ipv6_nd_ra_lifetime_cmd,
1023 "ipv6 nd ra-lifetime (0-9000)",
1024 "Interface IPv6 config commands\n"
1025 "Neighbor discovery\n"
1026 "Router lifetime\n"
1027 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1028 {
1029 int idx_number = 3;
1030 VTY_DECLVAR_CONTEXT(interface, ifp);
1031 struct zebra_if *zif = ifp->info;
1032 int lifetime;
1033
1034 lifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1035
1036 /* The value to be placed in the Router Lifetime field
1037 * of Router Advertisements sent from the interface,
1038 * in seconds. MUST be either zero or between
1039 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1040 if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) {
1041 vty_out(vty,
1042 "This ra-lifetime would conflict with configured ra-interval\n");
1043 return CMD_WARNING_CONFIG_FAILED;
1044 }
1045
1046 zif->rtadv.AdvDefaultLifetime = lifetime;
1047
1048 return CMD_SUCCESS;
1049 }
1050
1051 DEFUN (no_ipv6_nd_ra_lifetime,
1052 no_ipv6_nd_ra_lifetime_cmd,
1053 "no ipv6 nd ra-lifetime [(0-9000)]",
1054 NO_STR
1055 "Interface IPv6 config commands\n"
1056 "Neighbor discovery\n"
1057 "Router lifetime\n"
1058 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1059 {
1060 VTY_DECLVAR_CONTEXT(interface, ifp);
1061 struct zebra_if *zif = ifp->info;
1062
1063 zif->rtadv.AdvDefaultLifetime = -1;
1064
1065 return CMD_SUCCESS;
1066 }
1067
1068 DEFUN (ipv6_nd_reachable_time,
1069 ipv6_nd_reachable_time_cmd,
1070 "ipv6 nd reachable-time (1-3600000)",
1071 "Interface IPv6 config commands\n"
1072 "Neighbor discovery\n"
1073 "Reachable time\n"
1074 "Reachable time in milliseconds\n")
1075 {
1076 int idx_number = 3;
1077 VTY_DECLVAR_CONTEXT(interface, ifp);
1078 struct zebra_if *zif = ifp->info;
1079 zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10);
1080 return CMD_SUCCESS;
1081 }
1082
1083 DEFUN (no_ipv6_nd_reachable_time,
1084 no_ipv6_nd_reachable_time_cmd,
1085 "no ipv6 nd reachable-time [(1-3600000)]",
1086 NO_STR
1087 "Interface IPv6 config commands\n"
1088 "Neighbor discovery\n"
1089 "Reachable time\n"
1090 "Reachable time in milliseconds\n")
1091 {
1092 VTY_DECLVAR_CONTEXT(interface, ifp);
1093 struct zebra_if *zif = ifp->info;
1094
1095 zif->rtadv.AdvReachableTime = 0;
1096
1097 return CMD_SUCCESS;
1098 }
1099
1100 DEFUN (ipv6_nd_homeagent_preference,
1101 ipv6_nd_homeagent_preference_cmd,
1102 "ipv6 nd home-agent-preference (0-65535)",
1103 "Interface IPv6 config commands\n"
1104 "Neighbor discovery\n"
1105 "Home Agent preference\n"
1106 "preference value (default is 0, least preferred)\n")
1107 {
1108 int idx_number = 3;
1109 VTY_DECLVAR_CONTEXT(interface, ifp);
1110 struct zebra_if *zif = ifp->info;
1111 zif->rtadv.HomeAgentPreference =
1112 strtoul(argv[idx_number]->arg, NULL, 10);
1113 return CMD_SUCCESS;
1114 }
1115
1116 DEFUN (no_ipv6_nd_homeagent_preference,
1117 no_ipv6_nd_homeagent_preference_cmd,
1118 "no ipv6 nd home-agent-preference [(0-65535)]",
1119 NO_STR
1120 "Interface IPv6 config commands\n"
1121 "Neighbor discovery\n"
1122 "Home Agent preference\n"
1123 "preference value (default is 0, least preferred)\n")
1124 {
1125 VTY_DECLVAR_CONTEXT(interface, ifp);
1126 struct zebra_if *zif = ifp->info;
1127
1128 zif->rtadv.HomeAgentPreference = 0;
1129
1130 return CMD_SUCCESS;
1131 }
1132
1133 DEFUN (ipv6_nd_homeagent_lifetime,
1134 ipv6_nd_homeagent_lifetime_cmd,
1135 "ipv6 nd home-agent-lifetime (0-65520)",
1136 "Interface IPv6 config commands\n"
1137 "Neighbor discovery\n"
1138 "Home Agent lifetime\n"
1139 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1140 {
1141 int idx_number = 3;
1142 VTY_DECLVAR_CONTEXT(interface, ifp);
1143 struct zebra_if *zif = ifp->info;
1144 zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1145 return CMD_SUCCESS;
1146 }
1147
1148 DEFUN (no_ipv6_nd_homeagent_lifetime,
1149 no_ipv6_nd_homeagent_lifetime_cmd,
1150 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1151 NO_STR
1152 "Interface IPv6 config commands\n"
1153 "Neighbor discovery\n"
1154 "Home Agent lifetime\n"
1155 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1156 {
1157 VTY_DECLVAR_CONTEXT(interface, ifp);
1158 struct zebra_if *zif = ifp->info;
1159
1160 zif->rtadv.HomeAgentLifetime = -1;
1161
1162 return CMD_SUCCESS;
1163 }
1164
1165 DEFUN (ipv6_nd_managed_config_flag,
1166 ipv6_nd_managed_config_flag_cmd,
1167 "ipv6 nd managed-config-flag",
1168 "Interface IPv6 config commands\n"
1169 "Neighbor discovery\n"
1170 "Managed address configuration flag\n")
1171 {
1172 VTY_DECLVAR_CONTEXT(interface, ifp);
1173 struct zebra_if *zif = ifp->info;
1174
1175 zif->rtadv.AdvManagedFlag = 1;
1176
1177 return CMD_SUCCESS;
1178 }
1179
1180 DEFUN (no_ipv6_nd_managed_config_flag,
1181 no_ipv6_nd_managed_config_flag_cmd,
1182 "no ipv6 nd managed-config-flag",
1183 NO_STR
1184 "Interface IPv6 config commands\n"
1185 "Neighbor discovery\n"
1186 "Managed address configuration flag\n")
1187 {
1188 VTY_DECLVAR_CONTEXT(interface, ifp);
1189 struct zebra_if *zif = ifp->info;
1190
1191 zif->rtadv.AdvManagedFlag = 0;
1192
1193 return CMD_SUCCESS;
1194 }
1195
1196 DEFUN (ipv6_nd_homeagent_config_flag,
1197 ipv6_nd_homeagent_config_flag_cmd,
1198 "ipv6 nd home-agent-config-flag",
1199 "Interface IPv6 config commands\n"
1200 "Neighbor discovery\n"
1201 "Home Agent configuration flag\n")
1202 {
1203 VTY_DECLVAR_CONTEXT(interface, ifp);
1204 struct zebra_if *zif = ifp->info;
1205
1206 zif->rtadv.AdvHomeAgentFlag = 1;
1207
1208 return CMD_SUCCESS;
1209 }
1210
1211 DEFUN (no_ipv6_nd_homeagent_config_flag,
1212 no_ipv6_nd_homeagent_config_flag_cmd,
1213 "no ipv6 nd home-agent-config-flag",
1214 NO_STR
1215 "Interface IPv6 config commands\n"
1216 "Neighbor discovery\n"
1217 "Home Agent configuration flag\n")
1218 {
1219 VTY_DECLVAR_CONTEXT(interface, ifp);
1220 struct zebra_if *zif = ifp->info;
1221
1222 zif->rtadv.AdvHomeAgentFlag = 0;
1223
1224 return CMD_SUCCESS;
1225 }
1226
1227 DEFUN (ipv6_nd_adv_interval_config_option,
1228 ipv6_nd_adv_interval_config_option_cmd,
1229 "ipv6 nd adv-interval-option",
1230 "Interface IPv6 config commands\n"
1231 "Neighbor discovery\n"
1232 "Advertisement Interval Option\n")
1233 {
1234 VTY_DECLVAR_CONTEXT(interface, ifp);
1235 struct zebra_if *zif = ifp->info;
1236
1237 zif->rtadv.AdvIntervalOption = 1;
1238
1239 return CMD_SUCCESS;
1240 }
1241
1242 DEFUN (no_ipv6_nd_adv_interval_config_option,
1243 no_ipv6_nd_adv_interval_config_option_cmd,
1244 "no ipv6 nd adv-interval-option",
1245 NO_STR
1246 "Interface IPv6 config commands\n"
1247 "Neighbor discovery\n"
1248 "Advertisement Interval Option\n")
1249 {
1250 VTY_DECLVAR_CONTEXT(interface, ifp);
1251 struct zebra_if *zif = ifp->info;
1252
1253 zif->rtadv.AdvIntervalOption = 0;
1254
1255 return CMD_SUCCESS;
1256 }
1257
1258 DEFUN (ipv6_nd_other_config_flag,
1259 ipv6_nd_other_config_flag_cmd,
1260 "ipv6 nd other-config-flag",
1261 "Interface IPv6 config commands\n"
1262 "Neighbor discovery\n"
1263 "Other statefull configuration flag\n")
1264 {
1265 VTY_DECLVAR_CONTEXT(interface, ifp);
1266 struct zebra_if *zif = ifp->info;
1267
1268 zif->rtadv.AdvOtherConfigFlag = 1;
1269
1270 return CMD_SUCCESS;
1271 }
1272
1273 DEFUN (no_ipv6_nd_other_config_flag,
1274 no_ipv6_nd_other_config_flag_cmd,
1275 "no ipv6 nd other-config-flag",
1276 NO_STR
1277 "Interface IPv6 config commands\n"
1278 "Neighbor discovery\n"
1279 "Other statefull configuration flag\n")
1280 {
1281 VTY_DECLVAR_CONTEXT(interface, ifp);
1282 struct zebra_if *zif = ifp->info;
1283
1284 zif->rtadv.AdvOtherConfigFlag = 0;
1285
1286 return CMD_SUCCESS;
1287 }
1288
1289 DEFUN (ipv6_nd_prefix,
1290 ipv6_nd_prefix_cmd,
1291 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1292 "Interface IPv6 config commands\n"
1293 "Neighbor discovery\n"
1294 "Prefix information\n"
1295 "IPv6 prefix\n"
1296 "Valid lifetime in seconds\n"
1297 "Infinite valid lifetime\n"
1298 "Preferred lifetime in seconds\n"
1299 "Infinite preferred lifetime\n"
1300 "Set Router Address flag\n"
1301 "Do not use prefix for onlink determination\n"
1302 "Do not use prefix for autoconfiguration\n"
1303 "Do not use prefix for autoconfiguration\n"
1304 "Do not use prefix for onlink determination\n")
1305 {
1306 /* prelude */
1307 char *prefix = argv[3]->arg;
1308 int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
1309 || strmatch(argv[4]->text, "infinite"));
1310 int routeropts = lifetimes ? argc > 6 : argc > 4;
1311
1312 int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
1313
1314 char *lifetime = NULL, *preflifetime = NULL;
1315 int routeraddr = 0, offlink = 0, noautoconf = 0;
1316 if (lifetimes) {
1317 lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
1318 : argv[4]->text;
1319 preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg
1320 : argv[5]->text;
1321 }
1322 if (routeropts) {
1323 routeraddr =
1324 strmatch(argv[idx_routeropts]->text, "router-address");
1325 if (!routeraddr) {
1326 offlink = (argc > idx_routeropts + 1
1327 || strmatch(argv[idx_routeropts]->text,
1328 "off-link"));
1329 noautoconf = (argc > idx_routeropts + 1
1330 || strmatch(argv[idx_routeropts]->text,
1331 "no-autoconfig"));
1332 }
1333 }
1334
1335 /* business */
1336 VTY_DECLVAR_CONTEXT(interface, ifp);
1337 struct zebra_if *zebra_if = ifp->info;
1338 int ret;
1339 struct rtadv_prefix rp;
1340
1341 ret = str2prefix_ipv6(prefix, &rp.prefix);
1342 if (!ret) {
1343 vty_out(vty, "Malformed IPv6 prefix\n");
1344 return CMD_WARNING_CONFIG_FAILED;
1345 }
1346 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
1347 rp.AdvOnLinkFlag = !offlink;
1348 rp.AdvAutonomousFlag = !noautoconf;
1349 rp.AdvRouterAddressFlag = routeraddr;
1350 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1351 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1352
1353 if (lifetimes) {
1354 rp.AdvValidLifetime = strmatch(lifetime, "infinite")
1355 ? UINT32_MAX
1356 : strtoll(lifetime, NULL, 10);
1357 rp.AdvPreferredLifetime =
1358 strmatch(preflifetime, "infinite")
1359 ? UINT32_MAX
1360 : strtoll(preflifetime, NULL, 10);
1361 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) {
1362 vty_out(vty, "Invalid preferred lifetime\n");
1363 return CMD_WARNING_CONFIG_FAILED;
1364 }
1365 }
1366
1367 rtadv_prefix_set(zebra_if, &rp);
1368
1369 return CMD_SUCCESS;
1370 }
1371
1372 DEFUN (no_ipv6_nd_prefix,
1373 no_ipv6_nd_prefix_cmd,
1374 "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]>]",
1375 NO_STR
1376 "Interface IPv6 config commands\n"
1377 "Neighbor discovery\n"
1378 "Prefix information\n"
1379 "IPv6 prefix\n"
1380 "Valid lifetime in seconds\n"
1381 "Infinite valid lifetime\n"
1382 "Preferred lifetime in seconds\n"
1383 "Infinite preferred lifetime\n"
1384 "Set Router Address flag\n"
1385 "Do not use prefix for onlink determination\n"
1386 "Do not use prefix for autoconfiguration\n"
1387 "Do not use prefix for autoconfiguration\n"
1388 "Do not use prefix for onlink determination\n")
1389 {
1390 VTY_DECLVAR_CONTEXT(interface, ifp);
1391 struct zebra_if *zebra_if = ifp->info;
1392 int ret;
1393 struct rtadv_prefix rp;
1394 char *prefix = argv[4]->arg;
1395
1396 ret = str2prefix_ipv6(prefix, &rp.prefix);
1397 if (!ret) {
1398 vty_out(vty, "Malformed IPv6 prefix\n");
1399 return CMD_WARNING_CONFIG_FAILED;
1400 }
1401 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
1402
1403 ret = rtadv_prefix_reset(zebra_if, &rp);
1404 if (!ret) {
1405 vty_out(vty, "Non-existant IPv6 prefix\n");
1406 return CMD_WARNING_CONFIG_FAILED;
1407 }
1408
1409 return CMD_SUCCESS;
1410 }
1411
1412 DEFUN (ipv6_nd_router_preference,
1413 ipv6_nd_router_preference_cmd,
1414 "ipv6 nd router-preference <high|medium|low>",
1415 "Interface IPv6 config commands\n"
1416 "Neighbor discovery\n"
1417 "Default router preference\n"
1418 "High default router preference\n"
1419 "Medium default router preference (default)\n"
1420 "Low default router preference\n")
1421 {
1422 int idx_high_medium_low = 3;
1423 VTY_DECLVAR_CONTEXT(interface, ifp);
1424 struct zebra_if *zif = ifp->info;
1425 int i = 0;
1426
1427 while (0 != rtadv_pref_strs[i]) {
1428 if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i],
1429 1)
1430 == 0) {
1431 zif->rtadv.DefaultPreference = i;
1432 return CMD_SUCCESS;
1433 }
1434 i++;
1435 }
1436
1437 return CMD_ERR_NO_MATCH;
1438 }
1439
1440 DEFUN (no_ipv6_nd_router_preference,
1441 no_ipv6_nd_router_preference_cmd,
1442 "no ipv6 nd router-preference [<high|medium|low>]",
1443 NO_STR
1444 "Interface IPv6 config commands\n"
1445 "Neighbor discovery\n"
1446 "Default router preference\n"
1447 "High default router preference\n"
1448 "Medium default router preference (default)\n"
1449 "Low default router preference\n")
1450 {
1451 VTY_DECLVAR_CONTEXT(interface, ifp);
1452 struct zebra_if *zif = ifp->info;
1453
1454 zif->rtadv.DefaultPreference =
1455 RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1456
1457 return CMD_SUCCESS;
1458 }
1459
1460 DEFUN (ipv6_nd_mtu,
1461 ipv6_nd_mtu_cmd,
1462 "ipv6 nd mtu (1-65535)",
1463 "Interface IPv6 config commands\n"
1464 "Neighbor discovery\n"
1465 "Advertised MTU\n"
1466 "MTU in bytes\n")
1467 {
1468 int idx_number = 3;
1469 VTY_DECLVAR_CONTEXT(interface, ifp);
1470 struct zebra_if *zif = ifp->info;
1471 zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10);
1472 return CMD_SUCCESS;
1473 }
1474
1475 DEFUN (no_ipv6_nd_mtu,
1476 no_ipv6_nd_mtu_cmd,
1477 "no ipv6 nd mtu [(1-65535)]",
1478 NO_STR
1479 "Interface IPv6 config commands\n"
1480 "Neighbor discovery\n"
1481 "Advertised MTU\n"
1482 "MTU in bytes\n")
1483 {
1484 VTY_DECLVAR_CONTEXT(interface, ifp);
1485 struct zebra_if *zif = ifp->info;
1486 zif->rtadv.AdvLinkMTU = 0;
1487 return CMD_SUCCESS;
1488 }
1489
1490 /* Dump interface ND information to vty. */
1491 static int nd_dump_vty(struct vty *vty, struct interface *ifp)
1492 {
1493 struct zebra_if *zif;
1494 struct rtadvconf *rtadv;
1495 int interval;
1496
1497 zif = (struct zebra_if *)ifp->info;
1498 rtadv = &zif->rtadv;
1499
1500 if (rtadv->AdvSendAdvertisements) {
1501 vty_out(vty,
1502 " ND advertised reachable time is %d milliseconds\n",
1503 rtadv->AdvReachableTime);
1504 vty_out(vty,
1505 " ND advertised retransmit interval is %d milliseconds\n",
1506 rtadv->AdvRetransTimer);
1507 vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n",
1508 zif->ra_sent, zif->ra_rcvd);
1509 interval = rtadv->MaxRtrAdvInterval;
1510 if (interval % 1000)
1511 vty_out(vty,
1512 " ND router advertisements are sent every "
1513 "%d milliseconds\n",
1514 interval);
1515 else
1516 vty_out(vty,
1517 " ND router advertisements are sent every "
1518 "%d seconds\n",
1519 interval / 1000);
1520 if (rtadv->AdvDefaultLifetime != -1)
1521 vty_out(vty,
1522 " ND router advertisements live for %d seconds\n",
1523 rtadv->AdvDefaultLifetime);
1524 else
1525 vty_out(vty,
1526 " ND router advertisements lifetime tracks ra-interval\n");
1527 vty_out(vty,
1528 " ND router advertisement default router preference is "
1529 "%s\n",
1530 rtadv_pref_strs[rtadv->DefaultPreference]);
1531 if (rtadv->AdvManagedFlag)
1532 vty_out(vty,
1533 " Hosts use DHCP to obtain routable addresses.\n");
1534 else
1535 vty_out(vty,
1536 " Hosts use stateless autoconfig for addresses.\n");
1537 if (rtadv->AdvHomeAgentFlag) {
1538 vty_out(vty,
1539 " ND router advertisements with Home Agent flag bit set.\n");
1540 if (rtadv->HomeAgentLifetime != -1)
1541 vty_out(vty,
1542 " Home Agent lifetime is %u seconds\n",
1543 rtadv->HomeAgentLifetime);
1544 else
1545 vty_out(vty,
1546 " Home Agent lifetime tracks ra-lifetime\n");
1547 vty_out(vty, " Home Agent preference is %u\n",
1548 rtadv->HomeAgentPreference);
1549 }
1550 if (rtadv->AdvIntervalOption)
1551 vty_out(vty,
1552 " ND router advertisements with Adv. Interval option.\n");
1553 }
1554 return 0;
1555 }
1556
1557
1558 /* Write configuration about router advertisement. */
1559 static int rtadv_config_write(struct vty *vty, struct interface *ifp)
1560 {
1561 struct zebra_if *zif;
1562 struct listnode *node;
1563 struct rtadv_prefix *rprefix;
1564 char buf[PREFIX_STRLEN];
1565 int interval;
1566
1567 zif = ifp->info;
1568
1569 if (!(if_is_loopback(ifp)
1570 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) {
1571 if (zif->rtadv.AdvSendAdvertisements
1572 && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
1573 vty_out(vty, " no ipv6 nd suppress-ra\n");
1574 }
1575
1576 interval = zif->rtadv.MaxRtrAdvInterval;
1577 if (CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) {
1578 if (interval % 1000)
1579 vty_out(vty, " ipv6 nd ra-interval msec %d\n",
1580 interval);
1581 else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1582 vty_out(vty, " ipv6 nd ra-interval %d\n",
1583 interval / 1000);
1584 }
1585
1586 if (zif->rtadv.AdvIntervalOption)
1587 vty_out(vty, " ipv6 nd adv-interval-option\n");
1588
1589 if (zif->rtadv.AdvDefaultLifetime != -1)
1590 vty_out(vty, " ipv6 nd ra-lifetime %d\n",
1591 zif->rtadv.AdvDefaultLifetime);
1592
1593 if (zif->rtadv.HomeAgentPreference)
1594 vty_out(vty, " ipv6 nd home-agent-preference %u\n",
1595 zif->rtadv.HomeAgentPreference);
1596
1597 if (zif->rtadv.HomeAgentLifetime != -1)
1598 vty_out(vty, " ipv6 nd home-agent-lifetime %u\n",
1599 zif->rtadv.HomeAgentLifetime);
1600
1601 if (zif->rtadv.AdvHomeAgentFlag)
1602 vty_out(vty, " ipv6 nd home-agent-config-flag\n");
1603
1604 if (zif->rtadv.AdvReachableTime)
1605 vty_out(vty, " ipv6 nd reachable-time %d\n",
1606 zif->rtadv.AdvReachableTime);
1607
1608 if (zif->rtadv.AdvManagedFlag)
1609 vty_out(vty, " ipv6 nd managed-config-flag\n");
1610
1611 if (zif->rtadv.AdvOtherConfigFlag)
1612 vty_out(vty, " ipv6 nd other-config-flag\n");
1613
1614 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1615 vty_out(vty, " ipv6 nd router-preference %s\n",
1616 rtadv_pref_strs[zif->rtadv.DefaultPreference]);
1617
1618 if (zif->rtadv.AdvLinkMTU)
1619 vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU);
1620
1621 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) {
1622 vty_out(vty, " ipv6 nd prefix %s",
1623 prefix2str(&rprefix->prefix, buf, sizeof(buf)));
1624 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME)
1625 || (rprefix->AdvPreferredLifetime
1626 != RTADV_PREFERRED_LIFETIME)) {
1627 if (rprefix->AdvValidLifetime == UINT32_MAX)
1628 vty_out(vty, " infinite");
1629 else
1630 vty_out(vty, " %u", rprefix->AdvValidLifetime);
1631 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1632 vty_out(vty, " infinite");
1633 else
1634 vty_out(vty, " %u",
1635 rprefix->AdvPreferredLifetime);
1636 }
1637 if (!rprefix->AdvOnLinkFlag)
1638 vty_out(vty, " off-link");
1639 if (!rprefix->AdvAutonomousFlag)
1640 vty_out(vty, " no-autoconfig");
1641 if (rprefix->AdvRouterAddressFlag)
1642 vty_out(vty, " router-address");
1643 vty_out(vty, "\n");
1644 }
1645 return 0;
1646 }
1647
1648
1649 static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
1650 {
1651 struct rtadv *rtadv = &zns->rtadv;
1652
1653 switch (event) {
1654 case RTADV_START:
1655 thread_add_read(zebrad.master, rtadv_read, zns, val,
1656 &rtadv->ra_read);
1657 thread_add_event(zebrad.master, rtadv_timer, zns, 0,
1658 &rtadv->ra_timer);
1659 break;
1660 case RTADV_STOP:
1661 if (rtadv->ra_timer) {
1662 thread_cancel(rtadv->ra_timer);
1663 rtadv->ra_timer = NULL;
1664 }
1665 if (rtadv->ra_read) {
1666 thread_cancel(rtadv->ra_read);
1667 rtadv->ra_read = NULL;
1668 }
1669 break;
1670 case RTADV_TIMER:
1671 thread_add_timer(zebrad.master, rtadv_timer, zns, val,
1672 &rtadv->ra_timer);
1673 break;
1674 case RTADV_TIMER_MSEC:
1675 thread_add_timer_msec(zebrad.master, rtadv_timer, zns, val,
1676 &rtadv->ra_timer);
1677 break;
1678 case RTADV_READ:
1679 thread_add_read(zebrad.master, rtadv_read, zns, val,
1680 &rtadv->ra_read);
1681 break;
1682 default:
1683 break;
1684 }
1685 return;
1686 }
1687
1688 void rtadv_init(struct zebra_ns *zns)
1689 {
1690 zns->rtadv.sock = rtadv_make_socket(zns->ns_id);
1691 }
1692
1693 void rtadv_terminate(struct zebra_ns *zns)
1694 {
1695 rtadv_event(zns, RTADV_STOP, 0);
1696 if (zns->rtadv.sock >= 0) {
1697 close(zns->rtadv.sock);
1698 zns->rtadv.sock = -1;
1699 }
1700
1701 zns->rtadv.adv_if_count = 0;
1702 zns->rtadv.adv_msec_if_count = 0;
1703 }
1704
1705 void rtadv_cmd_init(void)
1706 {
1707 hook_register(zebra_if_extra_info, nd_dump_vty);
1708 hook_register(zebra_if_config_wr, rtadv_config_write);
1709
1710 install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1711 install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
1712 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
1713 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
1714 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1715 install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1716 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1717 install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1718 install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1719 install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1720 install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1721 install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1722 install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
1723 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1724 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1725 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1726 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1727 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1728 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1729 install_element(INTERFACE_NODE,
1730 &ipv6_nd_adv_interval_config_option_cmd);
1731 install_element(INTERFACE_NODE,
1732 &no_ipv6_nd_adv_interval_config_option_cmd);
1733 install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
1734 install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
1735 install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1736 install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
1737 install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
1738 install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
1739 }
1740
1741 static int if_join_all_router(int sock, struct interface *ifp)
1742 {
1743 int ret;
1744
1745 struct ipv6_mreq mreq;
1746
1747 memset(&mreq, 0, sizeof(struct ipv6_mreq));
1748 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1749 mreq.ipv6mr_interface = ifp->ifindex;
1750
1751 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq,
1752 sizeof mreq);
1753 if (ret < 0)
1754 zlog_warn("%s(%u): Failed to join group, socket %u error %s",
1755 ifp->name, ifp->ifindex, sock, safe_strerror(errno));
1756
1757 if (IS_ZEBRA_DEBUG_EVENT)
1758 zlog_debug(
1759 "%s(%u): Join All-Routers multicast group, socket %u",
1760 ifp->name, ifp->ifindex, sock);
1761
1762 return 0;
1763 }
1764
1765 static int if_leave_all_router(int sock, struct interface *ifp)
1766 {
1767 int ret;
1768
1769 struct ipv6_mreq mreq;
1770
1771 memset(&mreq, 0, sizeof(struct ipv6_mreq));
1772 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1773 mreq.ipv6mr_interface = ifp->ifindex;
1774
1775 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
1776 sizeof mreq);
1777 if (ret < 0)
1778 zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
1779 ifp->name, ifp->ifindex, sock, safe_strerror(errno));
1780
1781 if (IS_ZEBRA_DEBUG_EVENT)
1782 zlog_debug(
1783 "%s(%u): Leave All-Routers multicast group, socket %u",
1784 ifp->name, ifp->ifindex, sock);
1785
1786 return 0;
1787 }
1788
1789 #else
1790 void rtadv_init(struct zebra_ns *zns)
1791 {
1792 /* Empty.*/;
1793 }
1794 void rtadv_terminate(struct zebra_ns *zns)
1795 {
1796 /* Empty.*/;
1797 }
1798 void rtadv_cmd_init(void)
1799 {
1800 /* Empty.*/;
1801 }
1802 #endif /* HAVE_RTADV */