]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rtadv.c
Include padding in control message length.
[mirror_frr.git] / zebra / rtadv.c
1 /* Router advertisement
2 * Copyright (C) 1999 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23
24 #include "memory.h"
25 #include "sockopt.h"
26 #include "thread.h"
27 #include "if.h"
28 #include "log.h"
29 #include "prefix.h"
30 #include "linklist.h"
31 #include "command.h"
32 #include "privs.h"
33
34 #include "zebra/interface.h"
35 #include "zebra/rtadv.h"
36 #include "zebra/debug.h"
37 #include "zebra/rib.h"
38 #include "zebra/zserv.h"
39
40 extern struct zebra_privs_t zserv_privs;
41
42 #if defined (HAVE_IPV6) && defined (RTADV)
43
44 #ifdef OPEN_BSD
45 #include <netinet/icmp6.h>
46 #endif
47
48 /* If RFC2133 definition is used. */
49 #ifndef IPV6_JOIN_GROUP
50 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
51 #endif
52 #ifndef IPV6_LEAVE_GROUP
53 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
54 #endif
55
56 #define ALLNODE "ff02::1"
57 #define ALLROUTER "ff02::2"
58
59 extern struct zebra_t zebrad;
60
61 enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, RTADV_READ};
62
63 void rtadv_event (enum rtadv_event, int);
64
65 int if_join_all_router (int, struct interface *);
66 int if_leave_all_router (int, struct interface *);
67 \f
68 /* Structure which hold status of router advertisement. */
69 struct rtadv
70 {
71 int sock;
72
73 int adv_if_count;
74
75 struct thread *ra_read;
76 struct thread *ra_timer;
77 };
78
79 struct rtadv *rtadv = NULL;
80 \f
81 struct rtadv *
82 rtadv_new ()
83 {
84 struct rtadv *new;
85 new = XMALLOC (MTYPE_TMP, sizeof (struct rtadv));
86 memset (new, 0, sizeof (struct rtadv));
87 return new;
88 }
89
90 void
91 rtadv_free (struct rtadv *rtadv)
92 {
93 XFREE (MTYPE_TMP, rtadv);
94 }
95
96 int
97 rtadv_recv_packet (int sock, u_char *buf, int buflen,
98 struct sockaddr_in6 *from, unsigned int *ifindex,
99 int *hoplimit)
100 {
101 int ret;
102 struct msghdr msg;
103 struct iovec iov;
104 struct cmsghdr *cmsgptr;
105 struct in6_addr dst;
106
107 char adata[1024];
108
109 /* Fill in message and iovec. */
110 msg.msg_name = (void *) from;
111 msg.msg_namelen = sizeof (struct sockaddr_in6);
112 msg.msg_iov = &iov;
113 msg.msg_iovlen = 1;
114 msg.msg_control = (void *) adata;
115 msg.msg_controllen = sizeof adata;
116 iov.iov_base = buf;
117 iov.iov_len = buflen;
118
119 /* If recvmsg fail return minus value. */
120 ret = recvmsg (sock, &msg, 0);
121 if (ret < 0)
122 return ret;
123
124 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
125 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
126 {
127 /* I want interface index which this packet comes from. */
128 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
129 cmsgptr->cmsg_type == IPV6_PKTINFO)
130 {
131 struct in6_pktinfo *ptr;
132
133 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
134 *ifindex = ptr->ipi6_ifindex;
135 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
136 }
137
138 /* Incoming packet's hop limit. */
139 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
140 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
141 *hoplimit = *((int *) CMSG_DATA (cmsgptr));
142 }
143 return ret;
144 }
145
146 #define RTADV_MSG_SIZE 4096
147
148 /* Send router advertisement packet. */
149 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 #ifdef HAVE_SOCKADDR_DL
158 struct sockaddr_dl *sdl;
159 #endif /* HAVE_SOCKADDR_DL */
160 static void *adata = NULL;
161 unsigned char buf[RTADV_MSG_SIZE];
162 struct nd_router_advert *rtadv;
163 int ret;
164 int len = 0;
165 struct zebra_if *zif;
166 u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
167 listnode node;
168
169 /*
170 * Allocate control message bufffer. This is dynamic because
171 * CMSG_SPACE is not guaranteed not to call a function. Note that
172 * the size will be different on different architectures due to
173 * differing alignment rules.
174 */
175 if (adata == NULL)
176 {
177 /* XXX Free on shutdown. */
178 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
179
180 if (adata == NULL)
181 zlog_err("rtadv_send_packet: can't malloc control data\n");
182 }
183
184 /* Logging of packet. */
185 if (IS_ZEBRA_DEBUG_PACKET)
186 zlog_info ("Router advertisement send to %s", ifp->name);
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 memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_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 rtadv->nd_ra_flags_reserved = 0;
209 if (zif->rtadv.AdvManagedFlag)
210 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
211 if (zif->rtadv.AdvOtherConfigFlag)
212 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
213 rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
214 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
215 rtadv->nd_ra_retransmit = htonl (0);
216
217 len = sizeof (struct nd_router_advert);
218
219 /* Fill in prefix. */
220 for (node = listhead (zif->rtadv.AdvPrefixList); node; node = nextnode (node))
221 {
222 struct nd_opt_prefix_info *pinfo;
223 struct rtadv_prefix *rprefix;
224
225 rprefix = getdata (node);
226
227 pinfo = (struct nd_opt_prefix_info *) (buf + len);
228
229 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
230 pinfo->nd_opt_pi_len = 4;
231 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
232
233 pinfo->nd_opt_pi_flags_reserved = 0;
234 if (rprefix->AdvOnLinkFlag)
235 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
236 if (rprefix->AdvAutonomousFlag)
237 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
238
239 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
240 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
241 pinfo->nd_opt_pi_reserved2 = 0;
242
243 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
244 sizeof (struct in6_addr));
245
246 #ifdef DEBUG
247 {
248 u_char buf[INET6_ADDRSTRLEN];
249
250 zlog_info ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
251 buf, INET6_ADDRSTRLEN));
252
253 }
254 #endif /* DEBUG */
255
256 len += sizeof (struct nd_opt_prefix_info);
257 }
258
259 /* Hardware address. */
260 #ifdef HAVE_SOCKADDR_DL
261 sdl = &ifp->sdl;
262 if (sdl != NULL && sdl->sdl_alen != 0)
263 {
264 buf[len++] = ND_OPT_SOURCE_LINKADDR;
265 buf[len++] = (sdl->sdl_alen + 2) >> 3;
266
267 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
268 len += sdl->sdl_alen;
269 }
270 #else
271 if (ifp->hw_addr_len != 0)
272 {
273 buf[len++] = ND_OPT_SOURCE_LINKADDR;
274 buf[len++] = (ifp->hw_addr_len + 2) >> 3;
275
276 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
277 len += ifp->hw_addr_len;
278 }
279 #endif /* HAVE_SOCKADDR_DL */
280
281 msg.msg_name = (void *) &addr;
282 msg.msg_namelen = sizeof (struct sockaddr_in6);
283 msg.msg_iov = &iov;
284 msg.msg_iovlen = 1;
285 msg.msg_control = (void *) adata;
286 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
287 msg.msg_flags = 0;
288 iov.iov_base = buf;
289 iov.iov_len = len;
290
291 cmsgptr = CMSG_FIRSTHDR(&msg);
292 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
293 cmsgptr->cmsg_level = IPPROTO_IPV6;
294 cmsgptr->cmsg_type = IPV6_PKTINFO;
295
296 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
297 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
298 pkt->ipi6_ifindex = ifp->ifindex;
299
300 ret = sendmsg (sock, &msg, 0);
301 if (ret < 0)
302 {
303 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
304 errno, strerror(errno));
305 }
306 }
307
308 int
309 rtadv_timer (struct thread *thread)
310 {
311 listnode node;
312 struct interface *ifp;
313 struct zebra_if *zif;
314
315 rtadv->ra_timer = NULL;
316 rtadv_event (RTADV_TIMER, 1);
317
318 for (node = listhead (iflist); node; nextnode (node))
319 {
320 ifp = getdata (node);
321
322 if (if_is_loopback (ifp))
323 continue;
324
325 zif = ifp->info;
326
327 if (zif->rtadv.AdvSendAdvertisements)
328 if (--zif->rtadv.AdvIntervalTimer <= 0)
329 {
330 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
331 rtadv_send_packet (rtadv->sock, ifp);
332 }
333 }
334 return 0;
335 }
336
337 void
338 rtadv_process_solicit (struct interface *ifp)
339 {
340 zlog_info ("Router solicitation received on %s", ifp->name);
341
342 rtadv_send_packet (rtadv->sock, ifp);
343 }
344
345 void
346 rtadv_process_advert ()
347 {
348 zlog_info ("Router advertisement received");
349 }
350
351 void
352 rtadv_process_packet (u_char *buf, int len, unsigned int ifindex, int hoplimit)
353 {
354 struct icmp6_hdr *icmph;
355 struct interface *ifp;
356 struct zebra_if *zif;
357
358 /* Interface search. */
359 ifp = if_lookup_by_index (ifindex);
360 if (ifp == NULL)
361 {
362 zlog_warn ("Unknown interface index: %d", ifindex);
363 return;
364 }
365
366 if (if_is_loopback (ifp))
367 return;
368
369 /* Check interface configuration. */
370 zif = ifp->info;
371 if (! zif->rtadv.AdvSendAdvertisements)
372 return;
373
374 /* ICMP message length check. */
375 if (len < sizeof (struct icmp6_hdr))
376 {
377 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
378 return;
379 }
380
381 icmph = (struct icmp6_hdr *) buf;
382
383 /* ICMP message type check. */
384 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
385 icmph->icmp6_type != ND_ROUTER_ADVERT)
386 {
387 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
388 return;
389 }
390
391 /* Hoplimit check. */
392 if (hoplimit >= 0 && hoplimit != 255)
393 {
394 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
395 hoplimit);
396 return;
397 }
398
399 /* Check ICMP message type. */
400 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
401 rtadv_process_solicit (ifp);
402 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
403 rtadv_process_advert ();
404
405 return;
406 }
407
408 int
409 rtadv_read (struct thread *thread)
410 {
411 int sock;
412 int len;
413 u_char buf[RTADV_MSG_SIZE];
414 struct sockaddr_in6 from;
415 unsigned int ifindex;
416 int hoplimit = -1;
417
418 sock = THREAD_FD (thread);
419 rtadv->ra_read = NULL;
420
421 /* Register myself. */
422 rtadv_event (RTADV_READ, sock);
423
424 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
425
426 if (len < 0)
427 {
428 zlog_warn ("router solicitation recv failed: %s.", strerror (errno));
429 return len;
430 }
431
432 rtadv_process_packet (buf, len, ifindex, hoplimit);
433
434 return 0;
435 }
436
437 int
438 rtadv_make_socket (void)
439 {
440 int sock;
441 int ret;
442 struct icmp6_filter filter;
443
444 if ( zserv_privs.change (ZPRIVS_RAISE) )
445 zlog_err ("rtadv_make_socket: could not raise privs, %s",
446 strerror (errno) );
447
448 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
449
450 if ( zserv_privs.change (ZPRIVS_LOWER) )
451 zlog_err ("rtadv_make_socket: could not lower privs, %s",
452 strerror (errno) );
453
454 /* When we can't make ICMPV6 socket simply back. Router
455 advertisement feature will not be supported. */
456 if (sock < 0)
457 return -1;
458
459 ret = setsockopt_ipv6_pktinfo (sock, 1);
460 if (ret < 0)
461 return ret;
462 ret = setsockopt_ipv6_multicast_loop (sock, 0);
463 if (ret < 0)
464 return ret;
465 ret = setsockopt_ipv6_unicast_hops (sock, 255);
466 if (ret < 0)
467 return ret;
468 ret = setsockopt_ipv6_multicast_hops (sock, 255);
469 if (ret < 0)
470 return ret;
471 ret = setsockopt_ipv6_hoplimit (sock, 1);
472 if (ret < 0)
473 return ret;
474
475 ICMP6_FILTER_SETBLOCKALL(&filter);
476 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
477 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
478
479 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
480 sizeof (struct icmp6_filter));
481 if (ret < 0)
482 {
483 zlog_info ("ICMP6_FILTER set fail: %s", strerror (errno));
484 return ret;
485 }
486
487 return sock;
488 }
489 \f
490 struct rtadv_prefix *
491 rtadv_prefix_new ()
492 {
493 struct rtadv_prefix *new;
494
495 new = XMALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
496 memset (new, 0, sizeof (struct rtadv_prefix));
497
498 return new;
499 }
500
501 void
502 rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
503 {
504 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
505 }
506
507 struct rtadv_prefix *
508 rtadv_prefix_lookup (list rplist, struct prefix *p)
509 {
510 listnode node;
511 struct rtadv_prefix *rprefix;
512
513 for (node = listhead (rplist); node; node = nextnode (node))
514 {
515 rprefix = getdata (node);
516 if (prefix_same (&rprefix->prefix, p))
517 return rprefix;
518 }
519 return NULL;
520 }
521
522 struct rtadv_prefix *
523 rtadv_prefix_get (list rplist, struct prefix *p)
524 {
525 struct rtadv_prefix *rprefix;
526
527 rprefix = rtadv_prefix_lookup (rplist, p);
528 if (rprefix)
529 return rprefix;
530
531 rprefix = rtadv_prefix_new ();
532 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
533 listnode_add (rplist, rprefix);
534
535 return rprefix;
536 }
537
538 void
539 rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
540 {
541 struct rtadv_prefix *rprefix;
542
543 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
544
545 /* Set parameters. */
546 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
547 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
548 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
549 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
550 }
551
552 int
553 rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
554 {
555 struct rtadv_prefix *rprefix;
556
557 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
558 if (rprefix != NULL)
559 {
560 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
561 rtadv_prefix_free (rprefix);
562 return 1;
563 }
564 else
565 return 0;
566 }
567
568 DEFUN (ipv6_nd_suppress_ra,
569 ipv6_nd_suppress_ra_cmd,
570 "ipv6 nd suppress-ra",
571 "Interface IPv6 config commands\n"
572 "Neighbor discovery\n"
573 "Suppress Router Advertisement\n")
574 {
575 struct interface *ifp;
576 struct zebra_if *zif;
577
578 ifp = vty->index;
579 zif = ifp->info;
580
581 if (if_is_loopback (ifp))
582 {
583 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
584 return CMD_WARNING;
585 }
586
587 if (zif->rtadv.AdvSendAdvertisements)
588 {
589 zif->rtadv.AdvSendAdvertisements = 0;
590 zif->rtadv.AdvIntervalTimer = 0;
591 rtadv->adv_if_count--;
592
593 if_leave_all_router (rtadv->sock, ifp);
594
595 if (rtadv->adv_if_count == 0)
596 rtadv_event (RTADV_STOP, 0);
597 }
598
599 return CMD_SUCCESS;
600 }
601
602 DEFUN (no_ipv6_nd_suppress_ra,
603 no_ipv6_nd_suppress_ra_cmd,
604 "no ipv6 nd suppress-ra",
605 NO_STR
606 "Interface IPv6 config commands\n"
607 "Neighbor discovery\n"
608 "Suppress Router Advertisement\n")
609 {
610 struct interface *ifp;
611 struct zebra_if *zif;
612
613 ifp = vty->index;
614 zif = ifp->info;
615
616 if (if_is_loopback (ifp))
617 {
618 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
619 return CMD_WARNING;
620 }
621
622 if (! zif->rtadv.AdvSendAdvertisements)
623 {
624 zif->rtadv.AdvSendAdvertisements = 1;
625 zif->rtadv.AdvIntervalTimer = 0;
626 rtadv->adv_if_count++;
627
628 if_join_all_router (rtadv->sock, ifp);
629
630 if (rtadv->adv_if_count == 1)
631 rtadv_event (RTADV_START, rtadv->sock);
632 }
633
634 return CMD_SUCCESS;
635 }
636
637 DEFUN (ipv6_nd_ra_interval,
638 ipv6_nd_ra_interval_cmd,
639 "ipv6 nd ra-interval SECONDS",
640 "Interface IPv6 config commands\n"
641 "Neighbor discovery\n"
642 "Router Advertisement interval\n"
643 "Router Advertisement interval in seconds\n")
644 {
645 int interval;
646 struct interface *ifp;
647 struct zebra_if *zif;
648
649 ifp = (struct interface *) vty->index;
650 zif = ifp->info;
651
652 interval = atoi (argv[0]);
653
654 if (interval < 0)
655 {
656 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
657 return CMD_WARNING;
658 }
659
660 zif->rtadv.MaxRtrAdvInterval = interval;
661 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
662 zif->rtadv.AdvIntervalTimer = 0;
663
664 return CMD_SUCCESS;
665 }
666
667 DEFUN (no_ipv6_nd_ra_interval,
668 no_ipv6_nd_ra_interval_cmd,
669 "no ipv6 nd ra-interval",
670 NO_STR
671 "Interface IPv6 config commands\n"
672 "Neighbor discovery\n"
673 "Router Advertisement interval\n")
674 {
675 struct interface *ifp;
676 struct zebra_if *zif;
677
678 ifp = (struct interface *) vty->index;
679 zif = ifp->info;
680
681 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
682 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
683 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
684
685 return CMD_SUCCESS;
686 }
687
688 DEFUN (ipv6_nd_ra_lifetime,
689 ipv6_nd_ra_lifetime_cmd,
690 "ipv6 nd ra-lifetime SECONDS",
691 "Interface IPv6 config commands\n"
692 "Neighbor discovery\n"
693 "Router lifetime\n"
694 "Router lifetime in seconds\n")
695 {
696 int lifetime;
697 struct interface *ifp;
698 struct zebra_if *zif;
699
700 ifp = (struct interface *) vty->index;
701 zif = ifp->info;
702
703 lifetime = atoi (argv[0]);
704
705 if (lifetime < 0 || lifetime > 0xffff)
706 {
707 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
708 return CMD_WARNING;
709 }
710
711 zif->rtadv.AdvDefaultLifetime = lifetime;
712
713 return CMD_SUCCESS;
714 }
715
716 DEFUN (no_ipv6_nd_ra_lifetime,
717 no_ipv6_nd_ra_lifetime_cmd,
718 "no ipv6 nd ra-lifetime",
719 NO_STR
720 "Interface IPv6 config commands\n"
721 "Neighbor discovery\n"
722 "Router lifetime\n")
723 {
724 struct interface *ifp;
725 struct zebra_if *zif;
726
727 ifp = (struct interface *) vty->index;
728 zif = ifp->info;
729
730 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
731
732 return CMD_SUCCESS;
733 }
734
735 DEFUN (ipv6_nd_reachable_time,
736 ipv6_nd_reachable_time_cmd,
737 "ipv6 nd reachable-time MILLISECONDS",
738 "Interface IPv6 config commands\n"
739 "Neighbor discovery\n"
740 "Reachable time\n"
741 "Reachable time in milliseconds\n")
742 {
743 u_int32_t rtime;
744 struct interface *ifp;
745 struct zebra_if *zif;
746
747 ifp = (struct interface *) vty->index;
748 zif = ifp->info;
749
750 rtime = (u_int32_t) atol (argv[0]);
751
752 if (rtime > RTADV_MAX_REACHABLE_TIME)
753 {
754 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
755 return CMD_WARNING;
756 }
757
758 zif->rtadv.AdvReachableTime = rtime;
759
760 return CMD_SUCCESS;
761 }
762
763 DEFUN (no_ipv6_nd_reachable_time,
764 no_ipv6_nd_reachable_time_cmd,
765 "no ipv6 nd reachable-time",
766 NO_STR
767 "Interface IPv6 config commands\n"
768 "Neighbor discovery\n"
769 "Reachable time\n")
770 {
771 struct interface *ifp;
772 struct zebra_if *zif;
773
774 ifp = (struct interface *) vty->index;
775 zif = ifp->info;
776
777 zif->rtadv.AdvReachableTime = 0;
778
779 return CMD_SUCCESS;
780 }
781
782 DEFUN (ipv6_nd_managed_config_flag,
783 ipv6_nd_managed_config_flag_cmd,
784 "ipv6 nd managed-config-flag",
785 "Interface IPv6 config commands\n"
786 "Neighbor discovery\n"
787 "Managed address configuration flag\n")
788 {
789 struct interface *ifp;
790 struct zebra_if *zif;
791
792 ifp = (struct interface *) vty->index;
793 zif = ifp->info;
794
795 zif->rtadv.AdvManagedFlag = 1;
796
797 return CMD_SUCCESS;
798 }
799
800 DEFUN (no_ipv6_nd_managed_config_flag,
801 no_ipv6_nd_managed_config_flag_cmd,
802 "no ipv6 nd managed-config-flag",
803 NO_STR
804 "Interface IPv6 config commands\n"
805 "Neighbor discovery\n"
806 "Managed address configuration flag\n")
807 {
808 struct interface *ifp;
809 struct zebra_if *zif;
810
811 ifp = (struct interface *) vty->index;
812 zif = ifp->info;
813
814 zif->rtadv.AdvManagedFlag = 0;
815
816 return CMD_SUCCESS;
817 }
818
819 DEFUN (ipv6_nd_other_config_flag,
820 ipv6_nd_other_config_flag_cmd,
821 "ipv6 nd other-config-flag",
822 "Interface IPv6 config commands\n"
823 "Neighbor discovery\n"
824 "Other statefull configuration flag\n")
825 {
826 struct interface *ifp;
827 struct zebra_if *zif;
828
829 ifp = (struct interface *) vty->index;
830 zif = ifp->info;
831
832 zif->rtadv.AdvOtherConfigFlag = 1;
833
834 return CMD_SUCCESS;
835 }
836
837 DEFUN (no_ipv6_nd_other_config_flag,
838 no_ipv6_nd_other_config_flag_cmd,
839 "no ipv6 nd other-config-flag",
840 NO_STR
841 "Interface IPv6 config commands\n"
842 "Neighbor discovery\n"
843 "Other statefull configuration flag\n")
844 {
845 struct interface *ifp;
846 struct zebra_if *zif;
847
848 ifp = (struct interface *) vty->index;
849 zif = ifp->info;
850
851 zif->rtadv.AdvOtherConfigFlag = 0;
852
853 return CMD_SUCCESS;
854 }
855
856 DEFUN (ipv6_nd_prefix,
857 ipv6_nd_prefix_cmd,
858 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
859 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
860 "Interface IPv6 config commands\n"
861 "Neighbor discovery\n"
862 "Prefix information\n"
863 "IPv6 prefix\n"
864 "Valid lifetime in seconds\n"
865 "Infinite valid lifetime\n"
866 "Preferred lifetime in seconds\n"
867 "Infinite preferred lifetime\n"
868 "Do not use prefix for onlink determination\n"
869 "Do not use prefix for autoconfiguration\n")
870 {
871 int i;
872 int ret;
873 int cursor = 1;
874 struct interface *ifp;
875 struct zebra_if *zebra_if;
876 struct rtadv_prefix rp;
877
878 ifp = (struct interface *) vty->index;
879 zebra_if = ifp->info;
880
881 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
882 if (!ret)
883 {
884 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
885 return CMD_WARNING;
886 }
887 rp.AdvOnLinkFlag = 1;
888 rp.AdvAutonomousFlag = 1;
889 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
890 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
891
892 if (argc > 1)
893 {
894 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
895 {
896 if ( strncmp (argv[1], "i", 1) == 0)
897 rp.AdvValidLifetime = UINT32_MAX;
898 else
899 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
900 (char **)NULL, 10);
901
902 if ( strncmp (argv[2], "i", 1) == 0)
903 rp.AdvPreferredLifetime = UINT32_MAX;
904 else
905 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
906 (char **)NULL, 10);
907
908 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
909 {
910 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
911 return CMD_WARNING;
912 }
913 cursor = cursor + 2;
914 }
915 if (argc > cursor)
916 {
917 for (i = cursor; i < argc; i++)
918 {
919 if (strncmp (argv[i], "of", 2) == 0)
920 rp.AdvOnLinkFlag = 0;
921 if (strncmp (argv[i], "no", 2) == 0)
922 rp.AdvAutonomousFlag = 0;
923 }
924 }
925 }
926
927 rtadv_prefix_set (zebra_if, &rp);
928
929 return CMD_SUCCESS;
930 }
931
932 ALIAS (ipv6_nd_prefix,
933 ipv6_nd_prefix_val_rev_cmd,
934 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
935 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
936 "Interface IPv6 config commands\n"
937 "Neighbor discovery\n"
938 "Prefix information\n"
939 "IPv6 prefix\n"
940 "Valid lifetime in seconds\n"
941 "Infinite valid lifetime\n"
942 "Preferred lifetime in seconds\n"
943 "Infinite preferred lifetime\n"
944 "Do not use prefix for autoconfiguration\n"
945 "Do not use prefix for onlink determination\n")
946
947 ALIAS (ipv6_nd_prefix,
948 ipv6_nd_prefix_val_noauto_cmd,
949 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
950 "(<0-4294967295>|infinite) (no-autoconfig|)",
951 "Interface IPv6 config commands\n"
952 "Neighbor discovery\n"
953 "Prefix information\n"
954 "IPv6 prefix\n"
955 "Valid lifetime in seconds\n"
956 "Infinite valid lifetime\n"
957 "Preferred lifetime in seconds\n"
958 "Infinite preferred lifetime\n"
959 "Do not use prefix for autoconfigurationn")
960
961 ALIAS (ipv6_nd_prefix,
962 ipv6_nd_prefix_val_offlink_cmd,
963 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
964 "(<0-4294967295>|infinite) (off-link|)",
965 "Interface IPv6 config commands\n"
966 "Neighbor discovery\n"
967 "Prefix information\n"
968 "IPv6 prefix\n"
969 "Valid lifetime in seconds\n"
970 "Infinite valid lifetime\n"
971 "Preferred lifetime in seconds\n"
972 "Infinite preferred lifetime\n"
973 "Do not use prefix for onlink determination\n")
974
975 ALIAS (ipv6_nd_prefix,
976 ipv6_nd_prefix_val_cmd,
977 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
978 "(<0-4294967295>|infinite)",
979 "Interface IPv6 config commands\n"
980 "Neighbor discovery\n"
981 "Prefix information\n"
982 "IPv6 prefix\n"
983 "Valid lifetime in seconds\n"
984 "Infinite valid lifetime\n"
985 "Preferred lifetime in seconds\n"
986 "Infinite preferred lifetime\n")
987
988 ALIAS (ipv6_nd_prefix,
989 ipv6_nd_prefix_noval_cmd,
990 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
991 "Interface IPv6 config commands\n"
992 "Neighbor discovery\n"
993 "Prefix information\n"
994 "IPv6 prefix\n"
995 "Do not use prefix for autoconfiguration\n"
996 "Do not use prefix for onlink determination\n")
997
998 ALIAS (ipv6_nd_prefix,
999 ipv6_nd_prefix_noval_rev_cmd,
1000 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1001 "Interface IPv6 config commands\n"
1002 "Neighbor discovery\n"
1003 "Prefix information\n"
1004 "IPv6 prefix\n"
1005 "Do not use prefix for onlink determination\n"
1006 "Do not use prefix for autoconfiguration\n")
1007
1008 ALIAS (ipv6_nd_prefix,
1009 ipv6_nd_prefix_noval_noauto_cmd,
1010 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1011 "Interface IPv6 config commands\n"
1012 "Neighbor discovery\n"
1013 "Prefix information\n"
1014 "IPv6 prefix\n"
1015 "Do not use prefix for autoconfiguration\n")
1016
1017 ALIAS (ipv6_nd_prefix,
1018 ipv6_nd_prefix_noval_offlink_cmd,
1019 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1020 "Interface IPv6 config commands\n"
1021 "Neighbor discovery\n"
1022 "Prefix information\n"
1023 "IPv6 prefix\n"
1024 "Do not use prefix for onlink determination\n")
1025
1026 ALIAS (ipv6_nd_prefix,
1027 ipv6_nd_prefix_prefix_cmd,
1028 "ipv6 nd prefix X:X::X:X/M",
1029 "Interface IPv6 config commands\n"
1030 "Neighbor discovery\n"
1031 "Prefix information\n"
1032 "IPv6 prefix\n")
1033
1034 DEFUN (no_ipv6_nd_prefix,
1035 no_ipv6_nd_prefix_cmd,
1036 "no ipv6 nd prefix IPV6PREFIX",
1037 NO_STR
1038 "Interface IPv6 config commands\n"
1039 "Neighbor discovery\n"
1040 "Prefix information\n"
1041 "IPv6 prefix\n")
1042 {
1043 int ret;
1044 struct interface *ifp;
1045 struct zebra_if *zebra_if;
1046 struct rtadv_prefix rp;
1047
1048 ifp = (struct interface *) vty->index;
1049 zebra_if = ifp->info;
1050
1051 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1052 if (!ret)
1053 {
1054 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1055 return CMD_WARNING;
1056 }
1057
1058 ret = rtadv_prefix_reset (zebra_if, &rp);
1059 if (!ret)
1060 {
1061 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1062 return CMD_WARNING;
1063 }
1064
1065 return CMD_SUCCESS;
1066 }
1067
1068 /* Write configuration about router advertisement. */
1069 void
1070 rtadv_config_write (struct vty *vty, struct interface *ifp)
1071 {
1072 struct zebra_if *zif;
1073 listnode node;
1074 struct rtadv_prefix *rprefix;
1075 u_char buf[INET6_ADDRSTRLEN];
1076
1077 if (! rtadv)
1078 return;
1079
1080 zif = ifp->info;
1081
1082 if (! if_is_loopback (ifp))
1083 {
1084 if (zif->rtadv.AdvSendAdvertisements)
1085 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1086 else
1087 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1088 }
1089
1090 if (zif->rtadv.MaxRtrAdvInterval != RTADV_MAX_RTR_ADV_INTERVAL)
1091 vty_out (vty, " ipv6 nd ra-interval %d%s", zif->rtadv.MaxRtrAdvInterval,
1092 VTY_NEWLINE);
1093
1094 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1095 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1096 VTY_NEWLINE);
1097
1098 if (zif->rtadv.AdvReachableTime)
1099 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1100 VTY_NEWLINE);
1101
1102 if (zif->rtadv.AdvManagedFlag)
1103 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1104
1105 if (zif->rtadv.AdvOtherConfigFlag)
1106 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1107
1108 for (node = listhead(zif->rtadv.AdvPrefixList); node; node = nextnode (node))
1109 {
1110 rprefix = getdata (node);
1111 vty_out (vty, " ipv6 nd prefix %s/%d",
1112 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
1113 buf, INET6_ADDRSTRLEN),
1114 rprefix->prefix.prefixlen);
1115 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1116 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1117 {
1118 if (rprefix->AdvValidLifetime == UINT32_MAX)
1119 vty_out (vty, " infinite");
1120 else
1121 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1122 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1123 vty_out (vty, " infinite");
1124 else
1125 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1126 }
1127 if (!rprefix->AdvOnLinkFlag)
1128 vty_out (vty, " off-link");
1129 if (!rprefix->AdvAutonomousFlag)
1130 vty_out (vty, " no-autoconfig");
1131 vty_out (vty, "%s", VTY_NEWLINE);
1132 }
1133 }
1134
1135
1136 void
1137 rtadv_event (enum rtadv_event event, int val)
1138 {
1139 switch (event)
1140 {
1141 case RTADV_START:
1142 if (! rtadv->ra_read)
1143 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1144 if (! rtadv->ra_timer)
1145 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1146 NULL, 0);
1147 break;
1148 case RTADV_STOP:
1149 if (rtadv->ra_timer)
1150 {
1151 thread_cancel (rtadv->ra_timer);
1152 rtadv->ra_timer = NULL;
1153 }
1154 if (rtadv->ra_read)
1155 {
1156 thread_cancel (rtadv->ra_read);
1157 rtadv->ra_read = NULL;
1158 }
1159 break;
1160 case RTADV_TIMER:
1161 if (! rtadv->ra_timer)
1162 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1163 val);
1164 break;
1165 case RTADV_READ:
1166 if (! rtadv->ra_read)
1167 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1168 break;
1169 default:
1170 break;
1171 }
1172 return;
1173 }
1174
1175 void
1176 rtadv_init ()
1177 {
1178 int sock;
1179
1180 sock = rtadv_make_socket ();
1181 if (sock < 0)
1182 return;
1183
1184 rtadv = rtadv_new ();
1185 rtadv->sock = sock;
1186
1187 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1188 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
1189 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
1190 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1191 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1192 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1193 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1194 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1195 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1196 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1197 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1198 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
1199 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
1200 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1201 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1202 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
1203 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1204 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1205 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1206 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1207 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
1208 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1209 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
1210 }
1211
1212 int
1213 if_join_all_router (int sock, struct interface *ifp)
1214 {
1215 int ret;
1216
1217 struct ipv6_mreq mreq;
1218
1219 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1220 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1221 mreq.ipv6mr_interface = ifp->ifindex;
1222
1223 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1224 (char *) &mreq, sizeof mreq);
1225 if (ret < 0)
1226 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno));
1227
1228 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1229
1230 return 0;
1231 }
1232
1233 int
1234 if_leave_all_router (int sock, struct interface *ifp)
1235 {
1236 int ret;
1237
1238 struct ipv6_mreq mreq;
1239
1240 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1241 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1242 mreq.ipv6mr_interface = ifp->ifindex;
1243
1244 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1245 (char *) &mreq, sizeof mreq);
1246 if (ret < 0)
1247 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", strerror (errno));
1248
1249 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1250
1251 return 0;
1252 }
1253
1254 #else
1255 void
1256 rtadv_init ()
1257 {
1258 /* Empty.*/;
1259 }
1260 #endif /* RTADV && HAVE_IPV6 */