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