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