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