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