]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rtadv.c
61b4caa0b7f64bd484af1faa31cce2579821c673
[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 = CMSG_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_debug(
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 = CMSG_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_debug("%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_debug(
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 flog_warn(
487 ZEBRA_ERR_RA_PARAM_MISMATCH,
488 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
489 ifp->name, ifp->ifindex, addr_str);
490 }
491
492 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
493 && !zif->rtadv.AdvManagedFlag) {
494 flog_warn(
495 ZEBRA_ERR_RA_PARAM_MISMATCH,
496 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
497 ifp->name, ifp->ifindex, addr_str);
498 }
499
500 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
501 && !zif->rtadv.AdvOtherConfigFlag) {
502 flog_warn(
503 ZEBRA_ERR_RA_PARAM_MISMATCH,
504 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
505 ifp->name, ifp->ifindex, addr_str);
506 }
507
508 if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime)
509 && (ntohl(radvert->nd_ra_reachable)
510 != zif->rtadv.AdvReachableTime)) {
511 flog_warn(
512 ZEBRA_ERR_RA_PARAM_MISMATCH,
513 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
514 ifp->name, ifp->ifindex, addr_str);
515 }
516
517 if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer)
518 && (ntohl(radvert->nd_ra_retransmit)
519 != (unsigned int)zif->rtadv.AdvRetransTimer)) {
520 flog_warn(
521 ZEBRA_ERR_RA_PARAM_MISMATCH,
522 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
523 ifp->name, ifp->ifindex, addr_str);
524 }
525
526 /* Create entry for neighbor if not known. */
527 p.family = AF_INET6;
528 IPV6_ADDR_COPY(&p.u.prefix6, &addr->sin6_addr);
529 p.prefixlen = IPV6_MAX_PREFIXLEN;
530
531 if (!nbr_connected_check(ifp, &p))
532 nbr_connected_add_ipv6(ifp, &addr->sin6_addr);
533 }
534
535
536 static void rtadv_process_packet(uint8_t *buf, unsigned int len,
537 ifindex_t ifindex, int hoplimit,
538 struct sockaddr_in6 *from,
539 struct zebra_ns *zns)
540 {
541 struct icmp6_hdr *icmph;
542 struct interface *ifp;
543 struct zebra_if *zif;
544 char addr_str[INET6_ADDRSTRLEN];
545
546 inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
547
548 /* Interface search. */
549 ifp = if_lookup_by_index_per_ns(zns, ifindex);
550 if (ifp == NULL) {
551 flog_warn(ZEBRA_ERR_UNKNOWN_INTERFACE,
552 "RA/RS received on unknown IF %u from %s", ifindex,
553 addr_str);
554 return;
555 }
556
557 if (IS_ZEBRA_DEBUG_PACKET)
558 zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp->name,
559 ifp->ifindex, len, addr_str);
560
561 if (if_is_loopback(ifp)
562 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
563 return;
564
565 /* Check interface configuration. */
566 zif = ifp->info;
567 if (!zif->rtadv.AdvSendAdvertisements)
568 return;
569
570 /* ICMP message length check. */
571 if (len < sizeof(struct icmp6_hdr)) {
572 zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
573 ifp->name, ifp->ifindex, len);
574 return;
575 }
576
577 icmph = (struct icmp6_hdr *)buf;
578
579 /* ICMP message type check. */
580 if (icmph->icmp6_type != ND_ROUTER_SOLICIT
581 && icmph->icmp6_type != ND_ROUTER_ADVERT) {
582 zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
583 ifp->name, ifp->ifindex, icmph->icmp6_type);
584 return;
585 }
586
587 /* Hoplimit check. */
588 if (hoplimit >= 0 && hoplimit != 255) {
589 zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp->name,
590 ifp->ifindex, hoplimit);
591 return;
592 }
593
594 /* Check ICMP message type. */
595 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
596 rtadv_process_solicit(ifp);
597 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
598 rtadv_process_advert(buf, len, ifp, from);
599
600 return;
601 }
602
603 static int rtadv_read(struct thread *thread)
604 {
605 int sock;
606 int len;
607 uint8_t buf[RTADV_MSG_SIZE];
608 struct sockaddr_in6 from;
609 ifindex_t ifindex = 0;
610 int hoplimit = -1;
611 struct zebra_ns *zns = THREAD_ARG(thread);
612
613 sock = THREAD_FD(thread);
614 zns->rtadv.ra_read = NULL;
615
616 /* Register myself. */
617 rtadv_event(zns, RTADV_READ, sock);
618
619 len = rtadv_recv_packet(zns, sock, buf, sizeof(buf), &from, &ifindex,
620 &hoplimit);
621
622 if (len < 0) {
623 flog_err_sys(LIB_ERR_SOCKET,
624 "RA/RS recv failed, socket %u error %s", sock,
625 safe_strerror(errno));
626 return len;
627 }
628
629 rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zns);
630
631 return 0;
632 }
633
634 static int rtadv_make_socket(ns_id_t ns_id)
635 {
636 int sock = -1;
637 int ret = 0;
638 struct icmp6_filter filter;
639
640 frr_elevate_privs(&zserv_privs) {
641
642 sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
643
644 }
645
646 if (sock < 0) {
647 return -1;
648 }
649
650 ret = setsockopt_ipv6_pktinfo(sock, 1);
651 if (ret < 0) {
652 close(sock);
653 return ret;
654 }
655 ret = setsockopt_ipv6_multicast_loop(sock, 0);
656 if (ret < 0) {
657 close(sock);
658 return ret;
659 }
660 ret = setsockopt_ipv6_unicast_hops(sock, 255);
661 if (ret < 0) {
662 close(sock);
663 return ret;
664 }
665 ret = setsockopt_ipv6_multicast_hops(sock, 255);
666 if (ret < 0) {
667 close(sock);
668 return ret;
669 }
670 ret = setsockopt_ipv6_hoplimit(sock, 1);
671 if (ret < 0) {
672 close(sock);
673 return ret;
674 }
675
676 ICMP6_FILTER_SETBLOCKALL(&filter);
677 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
678 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
679
680 ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
681 sizeof(struct icmp6_filter));
682 if (ret < 0) {
683 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno));
684 close(sock);
685 return ret;
686 }
687
688 return sock;
689 }
690
691 static struct rtadv_prefix *rtadv_prefix_new(void)
692 {
693 return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix));
694 }
695
696 static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix)
697 {
698 XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix);
699 }
700
701 static struct rtadv_prefix *rtadv_prefix_lookup(struct list *rplist,
702 struct prefix_ipv6 *p)
703 {
704 struct listnode *node;
705 struct rtadv_prefix *rprefix;
706
707 for (ALL_LIST_ELEMENTS_RO(rplist, node, rprefix))
708 if (prefix_same((struct prefix *)&rprefix->prefix,
709 (struct prefix *)p))
710 return rprefix;
711 return NULL;
712 }
713
714 static struct rtadv_prefix *rtadv_prefix_get(struct list *rplist,
715 struct prefix_ipv6 *p)
716 {
717 struct rtadv_prefix *rprefix;
718
719 rprefix = rtadv_prefix_lookup(rplist, p);
720 if (rprefix)
721 return rprefix;
722
723 rprefix = rtadv_prefix_new();
724 memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6));
725 listnode_add(rplist, rprefix);
726
727 return rprefix;
728 }
729
730 static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
731 {
732 struct rtadv_prefix *rprefix;
733
734 rprefix = rtadv_prefix_get(zif->rtadv.AdvPrefixList, &rp->prefix);
735
736 /* Set parameters. */
737 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
738 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
739 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
740 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
741 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
742 }
743
744 static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
745 {
746 struct rtadv_prefix *rprefix;
747
748 rprefix = rtadv_prefix_lookup(zif->rtadv.AdvPrefixList, &rp->prefix);
749 if (rprefix != NULL) {
750 listnode_delete(zif->rtadv.AdvPrefixList, (void *)rprefix);
751 rtadv_prefix_free(rprefix);
752 return 1;
753 } else
754 return 0;
755 }
756
757 static void ipv6_nd_suppress_ra_set(struct interface *ifp,
758 ipv6_nd_suppress_ra_status status)
759 {
760 struct zebra_if *zif;
761 struct zebra_vrf *zvrf;
762 struct zebra_ns *zns;
763
764 zif = ifp->info;
765 zvrf = vrf_info_lookup(ifp->vrf_id);
766 zns = zvrf->zns;
767
768 if (status == RA_SUPPRESS) {
769 /* RA is currently enabled */
770 if (zif->rtadv.AdvSendAdvertisements) {
771 zif->rtadv.AdvSendAdvertisements = 0;
772 zif->rtadv.AdvIntervalTimer = 0;
773 zns->rtadv.adv_if_count--;
774
775 if_leave_all_router(zns->rtadv.sock, ifp);
776
777 if (zns->rtadv.adv_if_count == 0)
778 rtadv_event(zns, RTADV_STOP, 0);
779 }
780 } else {
781 if (!zif->rtadv.AdvSendAdvertisements) {
782 zif->rtadv.AdvSendAdvertisements = 1;
783 zif->rtadv.AdvIntervalTimer = 0;
784 zns->rtadv.adv_if_count++;
785
786 if (zif->rtadv.MaxRtrAdvInterval >= 1000) {
787 /* Enable Fast RA only when RA interval is in
788 * secs */
789 zif->rtadv.inFastRexmit = 1;
790 zif->rtadv.NumFastReXmitsRemain =
791 RTADV_NUM_FAST_REXMITS;
792 }
793
794 if_join_all_router(zns->rtadv.sock, ifp);
795
796 if (zns->rtadv.adv_if_count == 1)
797 rtadv_event(zns, RTADV_START, zns->rtadv.sock);
798 }
799 }
800 }
801
802 /*
803 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
804 * Note that while the client could request RA on an interface on which the
805 * operator has not enabled RA, RA won't be disabled upon client request
806 * if the operator has explicitly enabled RA. The enable request can also
807 * specify a RA interval (in seconds).
808 */
809 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
810 {
811 struct stream *s;
812 ifindex_t ifindex;
813 struct interface *ifp;
814 struct zebra_if *zif;
815 int ra_interval;
816
817 s = msg;
818
819 /* Get interface index and RA interval. */
820 STREAM_GETL(s, ifindex);
821 STREAM_GETL(s, ra_interval);
822
823 if (IS_ZEBRA_DEBUG_EVENT)
824 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
825 zvrf_id(zvrf), ifindex,
826 enable ? "enable" : "disable",
827 zebra_route_string(client->proto), ra_interval);
828
829 /* Locate interface and check VRF match. */
830 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex);
831 if (!ifp) {
832 flog_warn(ZEBRA_ERR_UNKNOWN_INTERFACE,
833 "%u: IF %u RA %s client %s - interface unknown",
834 zvrf_id(zvrf), ifindex, enable ? "enable" : "disable",
835 zebra_route_string(client->proto));
836 return;
837 }
838 if (ifp->vrf_id != zvrf_id(zvrf)) {
839 zlog_debug(
840 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
841 zvrf_id(zvrf), ifindex, enable ? "enable" : "disable",
842 zebra_route_string(client->proto), ifp->vrf_id);
843 return;
844 }
845
846 zif = ifp->info;
847 if (enable) {
848 SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
849 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
850 if (ra_interval
851 && (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval
852 && !CHECK_FLAG(zif->rtadv.ra_configured,
853 VTY_RA_INTERVAL_CONFIGURED))
854 zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
855 } else {
856 UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
857 if (!CHECK_FLAG(zif->rtadv.ra_configured,
858 VTY_RA_INTERVAL_CONFIGURED))
859 zif->rtadv.MaxRtrAdvInterval =
860 RTADV_MAX_RTR_ADV_INTERVAL;
861 if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
862 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
863 }
864 stream_failure:
865 return;
866 }
867
868 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
869 {
870 zebra_interface_radv_set(client, hdr, msg, zvrf, 0);
871 }
872 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
873 {
874 zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
875 }
876
877 DEFUN (ipv6_nd_suppress_ra,
878 ipv6_nd_suppress_ra_cmd,
879 "ipv6 nd suppress-ra",
880 "Interface IPv6 config commands\n"
881 "Neighbor discovery\n"
882 "Suppress Router Advertisement\n")
883 {
884 VTY_DECLVAR_CONTEXT(interface, ifp);
885 struct zebra_if *zif = ifp->info;
886
887 if (if_is_loopback(ifp)
888 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
889 vty_out(vty,
890 "Cannot configure IPv6 Router Advertisements on this interface\n");
891 return CMD_WARNING_CONFIG_FAILED;
892 }
893
894 if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
895 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
896
897 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
898 return CMD_SUCCESS;
899 }
900
901 DEFUN (no_ipv6_nd_suppress_ra,
902 no_ipv6_nd_suppress_ra_cmd,
903 "no ipv6 nd suppress-ra",
904 NO_STR
905 "Interface IPv6 config commands\n"
906 "Neighbor discovery\n"
907 "Suppress Router Advertisement\n")
908 {
909 VTY_DECLVAR_CONTEXT(interface, ifp);
910 struct zebra_if *zif = ifp->info;
911
912 if (if_is_loopback(ifp)
913 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
914 vty_out(vty,
915 "Cannot configure IPv6 Router Advertisements on this interface\n");
916 return CMD_WARNING_CONFIG_FAILED;
917 }
918
919 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
920 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
921 return CMD_SUCCESS;
922 }
923
924 DEFUN (ipv6_nd_ra_interval_msec,
925 ipv6_nd_ra_interval_msec_cmd,
926 "ipv6 nd ra-interval msec (70-1800000)",
927 "Interface IPv6 config commands\n"
928 "Neighbor discovery\n"
929 "Router Advertisement interval\n"
930 "Router Advertisement interval in milliseconds\n"
931 "Router Advertisement interval in milliseconds\n")
932 {
933 int idx_number = 4;
934 VTY_DECLVAR_CONTEXT(interface, ifp);
935 unsigned interval;
936 struct zebra_if *zif = ifp->info;
937 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
938 struct zebra_ns *zns;
939
940 zns = zvrf->zns;
941 interval = strtoul(argv[idx_number]->arg, NULL, 10);
942 if ((zif->rtadv.AdvDefaultLifetime != -1
943 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
944 vty_out(vty,
945 "This ra-interval would conflict with configured ra-lifetime!\n");
946 return CMD_WARNING_CONFIG_FAILED;
947 }
948
949 if (zif->rtadv.MaxRtrAdvInterval % 1000)
950 zns->rtadv.adv_msec_if_count--;
951
952 if (interval % 1000)
953 zns->rtadv.adv_msec_if_count++;
954
955 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
956 zif->rtadv.MaxRtrAdvInterval = interval;
957 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
958 zif->rtadv.AdvIntervalTimer = 0;
959
960 return CMD_SUCCESS;
961 }
962
963 DEFUN (ipv6_nd_ra_interval,
964 ipv6_nd_ra_interval_cmd,
965 "ipv6 nd ra-interval (1-1800)",
966 "Interface IPv6 config commands\n"
967 "Neighbor discovery\n"
968 "Router Advertisement interval\n"
969 "Router Advertisement interval in seconds\n")
970 {
971 int idx_number = 3;
972 VTY_DECLVAR_CONTEXT(interface, ifp);
973 unsigned interval;
974 struct zebra_if *zif = ifp->info;
975 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
976 struct zebra_ns *zns;
977
978 zns = zvrf->zns;
979 interval = strtoul(argv[idx_number]->arg, NULL, 10);
980 if ((zif->rtadv.AdvDefaultLifetime != -1
981 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
982 vty_out(vty,
983 "This ra-interval would conflict with configured ra-lifetime!\n");
984 return CMD_WARNING_CONFIG_FAILED;
985 }
986
987 if (zif->rtadv.MaxRtrAdvInterval % 1000)
988 zns->rtadv.adv_msec_if_count--;
989
990 /* convert to milliseconds */
991 interval = interval * 1000;
992
993 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
994 zif->rtadv.MaxRtrAdvInterval = interval;
995 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
996 zif->rtadv.AdvIntervalTimer = 0;
997
998 return CMD_SUCCESS;
999 }
1000
1001 DEFUN (no_ipv6_nd_ra_interval,
1002 no_ipv6_nd_ra_interval_cmd,
1003 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1004 NO_STR
1005 "Interface IPv6 config commands\n"
1006 "Neighbor discovery\n"
1007 "Router Advertisement interval\n"
1008 "Router Advertisement interval in seconds\n"
1009 "Specify millisecond router advertisement interval\n"
1010 "Router Advertisement interval in milliseconds\n")
1011 {
1012 VTY_DECLVAR_CONTEXT(interface, ifp);
1013 struct zebra_if *zif = ifp->info;
1014 struct zebra_vrf *zvrf;
1015 struct zebra_ns *zns;
1016
1017 zvrf = vrf_info_lookup(ifp->vrf_id);
1018 zns = zvrf->zns;
1019
1020 if (zif->rtadv.MaxRtrAdvInterval % 1000)
1021 zns->rtadv.adv_msec_if_count--;
1022
1023 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1024
1025 if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1026 zif->rtadv.MaxRtrAdvInterval = 10000;
1027 else
1028 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
1029
1030 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
1031 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
1032
1033 return CMD_SUCCESS;
1034 }
1035
1036 DEFUN (ipv6_nd_ra_lifetime,
1037 ipv6_nd_ra_lifetime_cmd,
1038 "ipv6 nd ra-lifetime (0-9000)",
1039 "Interface IPv6 config commands\n"
1040 "Neighbor discovery\n"
1041 "Router lifetime\n"
1042 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1043 {
1044 int idx_number = 3;
1045 VTY_DECLVAR_CONTEXT(interface, ifp);
1046 struct zebra_if *zif = ifp->info;
1047 int lifetime;
1048
1049 lifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1050
1051 /* The value to be placed in the Router Lifetime field
1052 * of Router Advertisements sent from the interface,
1053 * in seconds. MUST be either zero or between
1054 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1055 if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) {
1056 vty_out(vty,
1057 "This ra-lifetime would conflict with configured ra-interval\n");
1058 return CMD_WARNING_CONFIG_FAILED;
1059 }
1060
1061 zif->rtadv.AdvDefaultLifetime = lifetime;
1062
1063 return CMD_SUCCESS;
1064 }
1065
1066 DEFUN (no_ipv6_nd_ra_lifetime,
1067 no_ipv6_nd_ra_lifetime_cmd,
1068 "no ipv6 nd ra-lifetime [(0-9000)]",
1069 NO_STR
1070 "Interface IPv6 config commands\n"
1071 "Neighbor discovery\n"
1072 "Router lifetime\n"
1073 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1074 {
1075 VTY_DECLVAR_CONTEXT(interface, ifp);
1076 struct zebra_if *zif = ifp->info;
1077
1078 zif->rtadv.AdvDefaultLifetime = -1;
1079
1080 return CMD_SUCCESS;
1081 }
1082
1083 DEFUN (ipv6_nd_reachable_time,
1084 ipv6_nd_reachable_time_cmd,
1085 "ipv6 nd reachable-time (1-3600000)",
1086 "Interface IPv6 config commands\n"
1087 "Neighbor discovery\n"
1088 "Reachable time\n"
1089 "Reachable time in milliseconds\n")
1090 {
1091 int idx_number = 3;
1092 VTY_DECLVAR_CONTEXT(interface, ifp);
1093 struct zebra_if *zif = ifp->info;
1094 zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10);
1095 return CMD_SUCCESS;
1096 }
1097
1098 DEFUN (no_ipv6_nd_reachable_time,
1099 no_ipv6_nd_reachable_time_cmd,
1100 "no ipv6 nd reachable-time [(1-3600000)]",
1101 NO_STR
1102 "Interface IPv6 config commands\n"
1103 "Neighbor discovery\n"
1104 "Reachable time\n"
1105 "Reachable time in milliseconds\n")
1106 {
1107 VTY_DECLVAR_CONTEXT(interface, ifp);
1108 struct zebra_if *zif = ifp->info;
1109
1110 zif->rtadv.AdvReachableTime = 0;
1111
1112 return CMD_SUCCESS;
1113 }
1114
1115 DEFUN (ipv6_nd_homeagent_preference,
1116 ipv6_nd_homeagent_preference_cmd,
1117 "ipv6 nd home-agent-preference (0-65535)",
1118 "Interface IPv6 config commands\n"
1119 "Neighbor discovery\n"
1120 "Home Agent preference\n"
1121 "preference value (default is 0, least preferred)\n")
1122 {
1123 int idx_number = 3;
1124 VTY_DECLVAR_CONTEXT(interface, ifp);
1125 struct zebra_if *zif = ifp->info;
1126 zif->rtadv.HomeAgentPreference =
1127 strtoul(argv[idx_number]->arg, NULL, 10);
1128 return CMD_SUCCESS;
1129 }
1130
1131 DEFUN (no_ipv6_nd_homeagent_preference,
1132 no_ipv6_nd_homeagent_preference_cmd,
1133 "no ipv6 nd home-agent-preference [(0-65535)]",
1134 NO_STR
1135 "Interface IPv6 config commands\n"
1136 "Neighbor discovery\n"
1137 "Home Agent preference\n"
1138 "preference value (default is 0, least preferred)\n")
1139 {
1140 VTY_DECLVAR_CONTEXT(interface, ifp);
1141 struct zebra_if *zif = ifp->info;
1142
1143 zif->rtadv.HomeAgentPreference = 0;
1144
1145 return CMD_SUCCESS;
1146 }
1147
1148 DEFUN (ipv6_nd_homeagent_lifetime,
1149 ipv6_nd_homeagent_lifetime_cmd,
1150 "ipv6 nd home-agent-lifetime (0-65520)",
1151 "Interface IPv6 config commands\n"
1152 "Neighbor discovery\n"
1153 "Home Agent lifetime\n"
1154 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1155 {
1156 int idx_number = 3;
1157 VTY_DECLVAR_CONTEXT(interface, ifp);
1158 struct zebra_if *zif = ifp->info;
1159 zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1160 return CMD_SUCCESS;
1161 }
1162
1163 DEFUN (no_ipv6_nd_homeagent_lifetime,
1164 no_ipv6_nd_homeagent_lifetime_cmd,
1165 "no ipv6 nd home-agent-lifetime [(0-65520)]",
1166 NO_STR
1167 "Interface IPv6 config commands\n"
1168 "Neighbor discovery\n"
1169 "Home Agent lifetime\n"
1170 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1171 {
1172 VTY_DECLVAR_CONTEXT(interface, ifp);
1173 struct zebra_if *zif = ifp->info;
1174
1175 zif->rtadv.HomeAgentLifetime = -1;
1176
1177 return CMD_SUCCESS;
1178 }
1179
1180 DEFUN (ipv6_nd_managed_config_flag,
1181 ipv6_nd_managed_config_flag_cmd,
1182 "ipv6 nd managed-config-flag",
1183 "Interface IPv6 config commands\n"
1184 "Neighbor discovery\n"
1185 "Managed address configuration flag\n")
1186 {
1187 VTY_DECLVAR_CONTEXT(interface, ifp);
1188 struct zebra_if *zif = ifp->info;
1189
1190 zif->rtadv.AdvManagedFlag = 1;
1191
1192 return CMD_SUCCESS;
1193 }
1194
1195 DEFUN (no_ipv6_nd_managed_config_flag,
1196 no_ipv6_nd_managed_config_flag_cmd,
1197 "no ipv6 nd managed-config-flag",
1198 NO_STR
1199 "Interface IPv6 config commands\n"
1200 "Neighbor discovery\n"
1201 "Managed address configuration flag\n")
1202 {
1203 VTY_DECLVAR_CONTEXT(interface, ifp);
1204 struct zebra_if *zif = ifp->info;
1205
1206 zif->rtadv.AdvManagedFlag = 0;
1207
1208 return CMD_SUCCESS;
1209 }
1210
1211 DEFUN (ipv6_nd_homeagent_config_flag,
1212 ipv6_nd_homeagent_config_flag_cmd,
1213 "ipv6 nd home-agent-config-flag",
1214 "Interface IPv6 config commands\n"
1215 "Neighbor discovery\n"
1216 "Home Agent configuration flag\n")
1217 {
1218 VTY_DECLVAR_CONTEXT(interface, ifp);
1219 struct zebra_if *zif = ifp->info;
1220
1221 zif->rtadv.AdvHomeAgentFlag = 1;
1222
1223 return CMD_SUCCESS;
1224 }
1225
1226 DEFUN (no_ipv6_nd_homeagent_config_flag,
1227 no_ipv6_nd_homeagent_config_flag_cmd,
1228 "no ipv6 nd home-agent-config-flag",
1229 NO_STR
1230 "Interface IPv6 config commands\n"
1231 "Neighbor discovery\n"
1232 "Home Agent configuration flag\n")
1233 {
1234 VTY_DECLVAR_CONTEXT(interface, ifp);
1235 struct zebra_if *zif = ifp->info;
1236
1237 zif->rtadv.AdvHomeAgentFlag = 0;
1238
1239 return CMD_SUCCESS;
1240 }
1241
1242 DEFUN (ipv6_nd_adv_interval_config_option,
1243 ipv6_nd_adv_interval_config_option_cmd,
1244 "ipv6 nd adv-interval-option",
1245 "Interface IPv6 config commands\n"
1246 "Neighbor discovery\n"
1247 "Advertisement Interval Option\n")
1248 {
1249 VTY_DECLVAR_CONTEXT(interface, ifp);
1250 struct zebra_if *zif = ifp->info;
1251
1252 zif->rtadv.AdvIntervalOption = 1;
1253
1254 return CMD_SUCCESS;
1255 }
1256
1257 DEFUN (no_ipv6_nd_adv_interval_config_option,
1258 no_ipv6_nd_adv_interval_config_option_cmd,
1259 "no ipv6 nd adv-interval-option",
1260 NO_STR
1261 "Interface IPv6 config commands\n"
1262 "Neighbor discovery\n"
1263 "Advertisement Interval Option\n")
1264 {
1265 VTY_DECLVAR_CONTEXT(interface, ifp);
1266 struct zebra_if *zif = ifp->info;
1267
1268 zif->rtadv.AdvIntervalOption = 0;
1269
1270 return CMD_SUCCESS;
1271 }
1272
1273 DEFUN (ipv6_nd_other_config_flag,
1274 ipv6_nd_other_config_flag_cmd,
1275 "ipv6 nd other-config-flag",
1276 "Interface IPv6 config commands\n"
1277 "Neighbor discovery\n"
1278 "Other statefull configuration flag\n")
1279 {
1280 VTY_DECLVAR_CONTEXT(interface, ifp);
1281 struct zebra_if *zif = ifp->info;
1282
1283 zif->rtadv.AdvOtherConfigFlag = 1;
1284
1285 return CMD_SUCCESS;
1286 }
1287
1288 DEFUN (no_ipv6_nd_other_config_flag,
1289 no_ipv6_nd_other_config_flag_cmd,
1290 "no ipv6 nd other-config-flag",
1291 NO_STR
1292 "Interface IPv6 config commands\n"
1293 "Neighbor discovery\n"
1294 "Other statefull configuration flag\n")
1295 {
1296 VTY_DECLVAR_CONTEXT(interface, ifp);
1297 struct zebra_if *zif = ifp->info;
1298
1299 zif->rtadv.AdvOtherConfigFlag = 0;
1300
1301 return CMD_SUCCESS;
1302 }
1303
1304 DEFUN (ipv6_nd_prefix,
1305 ipv6_nd_prefix_cmd,
1306 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1307 "Interface IPv6 config commands\n"
1308 "Neighbor discovery\n"
1309 "Prefix information\n"
1310 "IPv6 prefix\n"
1311 "Valid lifetime in seconds\n"
1312 "Infinite valid lifetime\n"
1313 "Preferred lifetime in seconds\n"
1314 "Infinite preferred lifetime\n"
1315 "Set Router Address flag\n"
1316 "Do not use prefix for onlink determination\n"
1317 "Do not use prefix for autoconfiguration\n"
1318 "Do not use prefix for autoconfiguration\n"
1319 "Do not use prefix for onlink determination\n")
1320 {
1321 /* prelude */
1322 char *prefix = argv[3]->arg;
1323 int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
1324 || strmatch(argv[4]->text, "infinite"));
1325 int routeropts = lifetimes ? argc > 6 : argc > 4;
1326
1327 int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
1328
1329 char *lifetime = NULL, *preflifetime = NULL;
1330 int routeraddr = 0, offlink = 0, noautoconf = 0;
1331 if (lifetimes) {
1332 lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
1333 : argv[4]->text;
1334 preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg
1335 : argv[5]->text;
1336 }
1337 if (routeropts) {
1338 routeraddr =
1339 strmatch(argv[idx_routeropts]->text, "router-address");
1340 if (!routeraddr) {
1341 offlink = (argc > idx_routeropts + 1
1342 || strmatch(argv[idx_routeropts]->text,
1343 "off-link"));
1344 noautoconf = (argc > idx_routeropts + 1
1345 || strmatch(argv[idx_routeropts]->text,
1346 "no-autoconfig"));
1347 }
1348 }
1349
1350 /* business */
1351 VTY_DECLVAR_CONTEXT(interface, ifp);
1352 struct zebra_if *zebra_if = ifp->info;
1353 int ret;
1354 struct rtadv_prefix rp;
1355
1356 ret = str2prefix_ipv6(prefix, &rp.prefix);
1357 if (!ret) {
1358 vty_out(vty, "Malformed IPv6 prefix\n");
1359 return CMD_WARNING_CONFIG_FAILED;
1360 }
1361 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
1362 rp.AdvOnLinkFlag = !offlink;
1363 rp.AdvAutonomousFlag = !noautoconf;
1364 rp.AdvRouterAddressFlag = routeraddr;
1365 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1366 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1367
1368 if (lifetimes) {
1369 rp.AdvValidLifetime = strmatch(lifetime, "infinite")
1370 ? UINT32_MAX
1371 : strtoll(lifetime, NULL, 10);
1372 rp.AdvPreferredLifetime =
1373 strmatch(preflifetime, "infinite")
1374 ? UINT32_MAX
1375 : strtoll(preflifetime, NULL, 10);
1376 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) {
1377 vty_out(vty, "Invalid preferred lifetime\n");
1378 return CMD_WARNING_CONFIG_FAILED;
1379 }
1380 }
1381
1382 rtadv_prefix_set(zebra_if, &rp);
1383
1384 return CMD_SUCCESS;
1385 }
1386
1387 DEFUN (no_ipv6_nd_prefix,
1388 no_ipv6_nd_prefix_cmd,
1389 "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]>]",
1390 NO_STR
1391 "Interface IPv6 config commands\n"
1392 "Neighbor discovery\n"
1393 "Prefix information\n"
1394 "IPv6 prefix\n"
1395 "Valid lifetime in seconds\n"
1396 "Infinite valid lifetime\n"
1397 "Preferred lifetime in seconds\n"
1398 "Infinite preferred lifetime\n"
1399 "Set Router Address flag\n"
1400 "Do not use prefix for onlink determination\n"
1401 "Do not use prefix for autoconfiguration\n"
1402 "Do not use prefix for autoconfiguration\n"
1403 "Do not use prefix for onlink determination\n")
1404 {
1405 VTY_DECLVAR_CONTEXT(interface, ifp);
1406 struct zebra_if *zebra_if = ifp->info;
1407 int ret;
1408 struct rtadv_prefix rp;
1409 char *prefix = argv[4]->arg;
1410
1411 ret = str2prefix_ipv6(prefix, &rp.prefix);
1412 if (!ret) {
1413 vty_out(vty, "Malformed IPv6 prefix\n");
1414 return CMD_WARNING_CONFIG_FAILED;
1415 }
1416 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
1417
1418 ret = rtadv_prefix_reset(zebra_if, &rp);
1419 if (!ret) {
1420 vty_out(vty, "Non-existant IPv6 prefix\n");
1421 return CMD_WARNING_CONFIG_FAILED;
1422 }
1423
1424 return CMD_SUCCESS;
1425 }
1426
1427 DEFUN (ipv6_nd_router_preference,
1428 ipv6_nd_router_preference_cmd,
1429 "ipv6 nd router-preference <high|medium|low>",
1430 "Interface IPv6 config commands\n"
1431 "Neighbor discovery\n"
1432 "Default router preference\n"
1433 "High default router preference\n"
1434 "Medium default router preference (default)\n"
1435 "Low default router preference\n")
1436 {
1437 int idx_high_medium_low = 3;
1438 VTY_DECLVAR_CONTEXT(interface, ifp);
1439 struct zebra_if *zif = ifp->info;
1440 int i = 0;
1441
1442 while (0 != rtadv_pref_strs[i]) {
1443 if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i],
1444 1)
1445 == 0) {
1446 zif->rtadv.DefaultPreference = i;
1447 return CMD_SUCCESS;
1448 }
1449 i++;
1450 }
1451
1452 return CMD_ERR_NO_MATCH;
1453 }
1454
1455 DEFUN (no_ipv6_nd_router_preference,
1456 no_ipv6_nd_router_preference_cmd,
1457 "no ipv6 nd router-preference [<high|medium|low>]",
1458 NO_STR
1459 "Interface IPv6 config commands\n"
1460 "Neighbor discovery\n"
1461 "Default router preference\n"
1462 "High default router preference\n"
1463 "Medium default router preference (default)\n"
1464 "Low default router preference\n")
1465 {
1466 VTY_DECLVAR_CONTEXT(interface, ifp);
1467 struct zebra_if *zif = ifp->info;
1468
1469 zif->rtadv.DefaultPreference =
1470 RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1471
1472 return CMD_SUCCESS;
1473 }
1474
1475 DEFUN (ipv6_nd_mtu,
1476 ipv6_nd_mtu_cmd,
1477 "ipv6 nd mtu (1-65535)",
1478 "Interface IPv6 config commands\n"
1479 "Neighbor discovery\n"
1480 "Advertised MTU\n"
1481 "MTU in bytes\n")
1482 {
1483 int idx_number = 3;
1484 VTY_DECLVAR_CONTEXT(interface, ifp);
1485 struct zebra_if *zif = ifp->info;
1486 zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10);
1487 return CMD_SUCCESS;
1488 }
1489
1490 DEFUN (no_ipv6_nd_mtu,
1491 no_ipv6_nd_mtu_cmd,
1492 "no ipv6 nd mtu [(1-65535)]",
1493 NO_STR
1494 "Interface IPv6 config commands\n"
1495 "Neighbor discovery\n"
1496 "Advertised MTU\n"
1497 "MTU in bytes\n")
1498 {
1499 VTY_DECLVAR_CONTEXT(interface, ifp);
1500 struct zebra_if *zif = ifp->info;
1501 zif->rtadv.AdvLinkMTU = 0;
1502 return CMD_SUCCESS;
1503 }
1504
1505 /* Dump interface ND information to vty. */
1506 static int nd_dump_vty(struct vty *vty, struct interface *ifp)
1507 {
1508 struct zebra_if *zif;
1509 struct rtadvconf *rtadv;
1510 int interval;
1511
1512 zif = (struct zebra_if *)ifp->info;
1513 rtadv = &zif->rtadv;
1514
1515 if (rtadv->AdvSendAdvertisements) {
1516 vty_out(vty,
1517 " ND advertised reachable time is %d milliseconds\n",
1518 rtadv->AdvReachableTime);
1519 vty_out(vty,
1520 " ND advertised retransmit interval is %d milliseconds\n",
1521 rtadv->AdvRetransTimer);
1522 vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n",
1523 zif->ra_sent, zif->ra_rcvd);
1524 interval = rtadv->MaxRtrAdvInterval;
1525 if (interval % 1000)
1526 vty_out(vty,
1527 " ND router advertisements are sent every "
1528 "%d milliseconds\n",
1529 interval);
1530 else
1531 vty_out(vty,
1532 " ND router advertisements are sent every "
1533 "%d seconds\n",
1534 interval / 1000);
1535 if (rtadv->AdvDefaultLifetime != -1)
1536 vty_out(vty,
1537 " ND router advertisements live for %d seconds\n",
1538 rtadv->AdvDefaultLifetime);
1539 else
1540 vty_out(vty,
1541 " ND router advertisements lifetime tracks ra-interval\n");
1542 vty_out(vty,
1543 " ND router advertisement default router preference is "
1544 "%s\n",
1545 rtadv_pref_strs[rtadv->DefaultPreference]);
1546 if (rtadv->AdvManagedFlag)
1547 vty_out(vty,
1548 " Hosts use DHCP to obtain routable addresses.\n");
1549 else
1550 vty_out(vty,
1551 " Hosts use stateless autoconfig for addresses.\n");
1552 if (rtadv->AdvHomeAgentFlag) {
1553 vty_out(vty,
1554 " ND router advertisements with Home Agent flag bit set.\n");
1555 if (rtadv->HomeAgentLifetime != -1)
1556 vty_out(vty,
1557 " Home Agent lifetime is %u seconds\n",
1558 rtadv->HomeAgentLifetime);
1559 else
1560 vty_out(vty,
1561 " Home Agent lifetime tracks ra-lifetime\n");
1562 vty_out(vty, " Home Agent preference is %u\n",
1563 rtadv->HomeAgentPreference);
1564 }
1565 if (rtadv->AdvIntervalOption)
1566 vty_out(vty,
1567 " ND router advertisements with Adv. Interval option.\n");
1568 }
1569 return 0;
1570 }
1571
1572
1573 /* Write configuration about router advertisement. */
1574 static int rtadv_config_write(struct vty *vty, struct interface *ifp)
1575 {
1576 struct zebra_if *zif;
1577 struct listnode *node;
1578 struct rtadv_prefix *rprefix;
1579 char buf[PREFIX_STRLEN];
1580 int interval;
1581
1582 zif = ifp->info;
1583
1584 if (!(if_is_loopback(ifp)
1585 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) {
1586 if (zif->rtadv.AdvSendAdvertisements
1587 && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
1588 vty_out(vty, " no ipv6 nd suppress-ra\n");
1589 }
1590
1591 interval = zif->rtadv.MaxRtrAdvInterval;
1592 if (CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) {
1593 if (interval % 1000)
1594 vty_out(vty, " ipv6 nd ra-interval msec %d\n",
1595 interval);
1596 else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1597 vty_out(vty, " ipv6 nd ra-interval %d\n",
1598 interval / 1000);
1599 }
1600
1601 if (zif->rtadv.AdvIntervalOption)
1602 vty_out(vty, " ipv6 nd adv-interval-option\n");
1603
1604 if (zif->rtadv.AdvDefaultLifetime != -1)
1605 vty_out(vty, " ipv6 nd ra-lifetime %d\n",
1606 zif->rtadv.AdvDefaultLifetime);
1607
1608 if (zif->rtadv.HomeAgentPreference)
1609 vty_out(vty, " ipv6 nd home-agent-preference %u\n",
1610 zif->rtadv.HomeAgentPreference);
1611
1612 if (zif->rtadv.HomeAgentLifetime != -1)
1613 vty_out(vty, " ipv6 nd home-agent-lifetime %u\n",
1614 zif->rtadv.HomeAgentLifetime);
1615
1616 if (zif->rtadv.AdvHomeAgentFlag)
1617 vty_out(vty, " ipv6 nd home-agent-config-flag\n");
1618
1619 if (zif->rtadv.AdvReachableTime)
1620 vty_out(vty, " ipv6 nd reachable-time %d\n",
1621 zif->rtadv.AdvReachableTime);
1622
1623 if (zif->rtadv.AdvManagedFlag)
1624 vty_out(vty, " ipv6 nd managed-config-flag\n");
1625
1626 if (zif->rtadv.AdvOtherConfigFlag)
1627 vty_out(vty, " ipv6 nd other-config-flag\n");
1628
1629 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1630 vty_out(vty, " ipv6 nd router-preference %s\n",
1631 rtadv_pref_strs[zif->rtadv.DefaultPreference]);
1632
1633 if (zif->rtadv.AdvLinkMTU)
1634 vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU);
1635
1636 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) {
1637 vty_out(vty, " ipv6 nd prefix %s",
1638 prefix2str(&rprefix->prefix, buf, sizeof(buf)));
1639 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME)
1640 || (rprefix->AdvPreferredLifetime
1641 != RTADV_PREFERRED_LIFETIME)) {
1642 if (rprefix->AdvValidLifetime == UINT32_MAX)
1643 vty_out(vty, " infinite");
1644 else
1645 vty_out(vty, " %u", rprefix->AdvValidLifetime);
1646 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1647 vty_out(vty, " infinite");
1648 else
1649 vty_out(vty, " %u",
1650 rprefix->AdvPreferredLifetime);
1651 }
1652 if (!rprefix->AdvOnLinkFlag)
1653 vty_out(vty, " off-link");
1654 if (!rprefix->AdvAutonomousFlag)
1655 vty_out(vty, " no-autoconfig");
1656 if (rprefix->AdvRouterAddressFlag)
1657 vty_out(vty, " router-address");
1658 vty_out(vty, "\n");
1659 }
1660 return 0;
1661 }
1662
1663
1664 static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
1665 {
1666 struct rtadv *rtadv = &zns->rtadv;
1667
1668 switch (event) {
1669 case RTADV_START:
1670 thread_add_read(zebrad.master, rtadv_read, zns, val,
1671 &rtadv->ra_read);
1672 thread_add_event(zebrad.master, rtadv_timer, zns, 0,
1673 &rtadv->ra_timer);
1674 break;
1675 case RTADV_STOP:
1676 if (rtadv->ra_timer) {
1677 thread_cancel(rtadv->ra_timer);
1678 rtadv->ra_timer = NULL;
1679 }
1680 if (rtadv->ra_read) {
1681 thread_cancel(rtadv->ra_read);
1682 rtadv->ra_read = NULL;
1683 }
1684 break;
1685 case RTADV_TIMER:
1686 thread_add_timer(zebrad.master, rtadv_timer, zns, val,
1687 &rtadv->ra_timer);
1688 break;
1689 case RTADV_TIMER_MSEC:
1690 thread_add_timer_msec(zebrad.master, rtadv_timer, zns, val,
1691 &rtadv->ra_timer);
1692 break;
1693 case RTADV_READ:
1694 thread_add_read(zebrad.master, rtadv_read, zns, val,
1695 &rtadv->ra_read);
1696 break;
1697 default:
1698 break;
1699 }
1700 return;
1701 }
1702
1703 void rtadv_init(struct zebra_ns *zns)
1704 {
1705 zns->rtadv.sock = rtadv_make_socket(zns->ns_id);
1706 }
1707
1708 void rtadv_terminate(struct zebra_ns *zns)
1709 {
1710 rtadv_event(zns, RTADV_STOP, 0);
1711 if (zns->rtadv.sock >= 0) {
1712 close(zns->rtadv.sock);
1713 zns->rtadv.sock = -1;
1714 }
1715
1716 zns->rtadv.adv_if_count = 0;
1717 zns->rtadv.adv_msec_if_count = 0;
1718 }
1719
1720 void rtadv_cmd_init(void)
1721 {
1722 hook_register(zebra_if_extra_info, nd_dump_vty);
1723 hook_register(zebra_if_config_wr, rtadv_config_write);
1724
1725 install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1726 install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
1727 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
1728 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
1729 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1730 install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1731 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1732 install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1733 install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1734 install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1735 install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1736 install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1737 install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
1738 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1739 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1740 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1741 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1742 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1743 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1744 install_element(INTERFACE_NODE,
1745 &ipv6_nd_adv_interval_config_option_cmd);
1746 install_element(INTERFACE_NODE,
1747 &no_ipv6_nd_adv_interval_config_option_cmd);
1748 install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
1749 install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
1750 install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1751 install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
1752 install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
1753 install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
1754 }
1755
1756 static int if_join_all_router(int sock, struct interface *ifp)
1757 {
1758 int ret;
1759
1760 struct ipv6_mreq mreq;
1761
1762 memset(&mreq, 0, sizeof(struct ipv6_mreq));
1763 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1764 mreq.ipv6mr_interface = ifp->ifindex;
1765
1766 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq,
1767 sizeof mreq);
1768 if (ret < 0)
1769 flog_err_sys(LIB_ERR_SOCKET,
1770 "%s(%u): Failed to join group, socket %u error %s",
1771 ifp->name, ifp->ifindex, sock,
1772 safe_strerror(errno));
1773
1774 if (IS_ZEBRA_DEBUG_EVENT)
1775 zlog_debug(
1776 "%s(%u): Join All-Routers multicast group, socket %u",
1777 ifp->name, ifp->ifindex, sock);
1778
1779 return 0;
1780 }
1781
1782 static int if_leave_all_router(int sock, struct interface *ifp)
1783 {
1784 int ret;
1785
1786 struct ipv6_mreq mreq;
1787
1788 memset(&mreq, 0, sizeof(struct ipv6_mreq));
1789 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1790 mreq.ipv6mr_interface = ifp->ifindex;
1791
1792 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
1793 sizeof mreq);
1794 if (ret < 0)
1795 flog_err_sys(
1796 LIB_ERR_SOCKET,
1797 "%s(%u): Failed to leave group, socket %u error %s",
1798 ifp->name, ifp->ifindex, sock, safe_strerror(errno));
1799
1800 if (IS_ZEBRA_DEBUG_EVENT)
1801 zlog_debug(
1802 "%s(%u): Leave All-Routers multicast group, socket %u",
1803 ifp->name, ifp->ifindex, sock);
1804
1805 return 0;
1806 }
1807
1808 #else
1809 void rtadv_init(struct zebra_ns *zns)
1810 {
1811 /* Empty.*/;
1812 }
1813 void rtadv_terminate(struct zebra_ns *zns)
1814 {
1815 /* Empty.*/;
1816 }
1817 void rtadv_cmd_init(void)
1818 {
1819 /* Empty.*/;
1820 }
1821 #endif /* HAVE_RTADV */