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