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