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