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