[release] Bump version to 0.99.10
[jleu-quagga.git] / zebra / rtadv.c
blob4bdb83d5fef39e329413dec63279d1dd746c2df4
1 /* Router advertisement
2 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
3 * Copyright (C) 1999 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
23 #include <zebra.h>
25 #include "memory.h"
26 #include "sockopt.h"
27 #include "thread.h"
28 #include "if.h"
29 #include "log.h"
30 #include "prefix.h"
31 #include "linklist.h"
32 #include "command.h"
33 #include "privs.h"
35 #include "zebra/interface.h"
36 #include "zebra/rtadv.h"
37 #include "zebra/debug.h"
38 #include "zebra/rib.h"
39 #include "zebra/zserv.h"
41 extern struct zebra_privs_t zserv_privs;
43 #if defined (HAVE_IPV6) && defined (RTADV)
45 #ifdef OPEN_BSD
46 #include <netinet/icmp6.h>
47 #endif
49 /* If RFC2133 definition is used. */
50 #ifndef IPV6_JOIN_GROUP
51 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
52 #endif
53 #ifndef IPV6_LEAVE_GROUP
54 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
55 #endif
57 #define ALLNODE "ff02::1"
58 #define ALLROUTER "ff02::2"
60 extern struct zebra_t zebrad;
62 enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
63 RTADV_TIMER_MSEC, RTADV_READ};
65 static void rtadv_event (enum rtadv_event, int);
67 static int if_join_all_router (int, struct interface *);
68 static int if_leave_all_router (int, struct interface *);
70 /* Structure which hold status of router advertisement. */
71 struct rtadv
73 int sock;
75 int adv_if_count;
76 int adv_msec_if_count;
78 struct thread *ra_read;
79 struct thread *ra_timer;
82 struct rtadv *rtadv = NULL;
84 static struct rtadv *
85 rtadv_new (void)
87 struct rtadv *new;
88 new = XMALLOC (MTYPE_TMP, sizeof (struct rtadv));
89 memset (new, 0, sizeof (struct rtadv));
90 return new;
93 static void
94 rtadv_free (struct rtadv *rtadv)
96 XFREE (MTYPE_TMP, rtadv);
99 static int
100 rtadv_recv_packet (int sock, u_char *buf, int buflen,
101 struct sockaddr_in6 *from, unsigned int *ifindex,
102 int *hoplimit)
104 int ret;
105 struct msghdr msg;
106 struct iovec iov;
107 struct cmsghdr *cmsgptr;
108 struct in6_addr dst;
110 char adata[1024];
112 /* Fill in message and iovec. */
113 msg.msg_name = (void *) from;
114 msg.msg_namelen = sizeof (struct sockaddr_in6);
115 msg.msg_iov = &iov;
116 msg.msg_iovlen = 1;
117 msg.msg_control = (void *) adata;
118 msg.msg_controllen = sizeof adata;
119 iov.iov_base = buf;
120 iov.iov_len = buflen;
122 /* If recvmsg fail return minus value. */
123 ret = recvmsg (sock, &msg, 0);
124 if (ret < 0)
125 return ret;
127 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
128 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
130 /* I want interface index which this packet comes from. */
131 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
132 cmsgptr->cmsg_type == IPV6_PKTINFO)
134 struct in6_pktinfo *ptr;
136 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
137 *ifindex = ptr->ipi6_ifindex;
138 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
141 /* Incoming packet's hop limit. */
142 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
143 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
144 *hoplimit = *((int *) CMSG_DATA (cmsgptr));
146 return ret;
149 #define RTADV_MSG_SIZE 4096
151 /* Send router advertisement packet. */
152 static void
153 rtadv_send_packet (int sock, struct interface *ifp)
155 struct msghdr msg;
156 struct iovec iov;
157 struct cmsghdr *cmsgptr;
158 struct in6_pktinfo *pkt;
159 struct sockaddr_in6 addr;
160 #ifdef HAVE_STRUCT_SOCKADDR_DL
161 struct sockaddr_dl *sdl;
162 #endif /* HAVE_STRUCT_SOCKADDR_DL */
163 static void *adata = NULL;
164 unsigned char buf[RTADV_MSG_SIZE];
165 struct nd_router_advert *rtadv;
166 int ret;
167 int len = 0;
168 struct zebra_if *zif;
169 struct rtadv_prefix *rprefix;
170 u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
171 struct listnode *node;
174 * Allocate control message bufffer. This is dynamic because
175 * CMSG_SPACE is not guaranteed not to call a function. Note that
176 * the size will be different on different architectures due to
177 * differing alignment rules.
179 if (adata == NULL)
181 /* XXX Free on shutdown. */
182 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
184 if (adata == NULL)
185 zlog_err("rtadv_send_packet: can't malloc control data\n");
188 /* Logging of packet. */
189 if (IS_ZEBRA_DEBUG_PACKET)
190 zlog_debug ("Router advertisement send to %s", ifp->name);
192 /* Fill in sockaddr_in6. */
193 memset (&addr, 0, sizeof (struct sockaddr_in6));
194 addr.sin6_family = AF_INET6;
195 #ifdef SIN6_LEN
196 addr.sin6_len = sizeof (struct sockaddr_in6);
197 #endif /* SIN6_LEN */
198 addr.sin6_port = htons (IPPROTO_ICMPV6);
199 memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
201 /* Fetch interface information. */
202 zif = ifp->info;
204 /* Make router advertisement message. */
205 rtadv = (struct nd_router_advert *) buf;
207 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
208 rtadv->nd_ra_code = 0;
209 rtadv->nd_ra_cksum = 0;
211 rtadv->nd_ra_curhoplimit = 64;
212 rtadv->nd_ra_flags_reserved = 0;
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 rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
220 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
221 rtadv->nd_ra_retransmit = htonl (0);
223 len = sizeof (struct nd_router_advert);
225 if (zif->rtadv.AdvHomeAgentFlag)
227 struct nd_opt_homeagent_info *ndopt_hai =
228 (struct nd_opt_homeagent_info *)(buf + len);
229 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
230 ndopt_hai->nd_opt_hai_len = 1;
231 ndopt_hai->nd_opt_hai_reserved = 0;
232 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
233 ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);
234 len += sizeof(struct nd_opt_homeagent_info);
237 if (zif->rtadv.AdvIntervalOption)
239 struct nd_opt_adv_interval *ndopt_adv =
240 (struct nd_opt_adv_interval *)(buf + len);
241 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
242 ndopt_adv->nd_opt_ai_len = 1;
243 ndopt_adv->nd_opt_ai_reserved = 0;
244 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
245 len += sizeof(struct nd_opt_adv_interval);
248 /* Fill in prefix. */
249 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
251 struct nd_opt_prefix_info *pinfo;
253 pinfo = (struct nd_opt_prefix_info *) (buf + len);
255 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
256 pinfo->nd_opt_pi_len = 4;
257 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
259 pinfo->nd_opt_pi_flags_reserved = 0;
260 if (rprefix->AdvOnLinkFlag)
261 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
262 if (rprefix->AdvAutonomousFlag)
263 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
264 if (rprefix->AdvRouterAddressFlag)
265 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
267 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
268 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
269 pinfo->nd_opt_pi_reserved2 = 0;
271 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
272 sizeof (struct in6_addr));
274 #ifdef DEBUG
276 u_char buf[INET6_ADDRSTRLEN];
278 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
279 buf, INET6_ADDRSTRLEN));
282 #endif /* DEBUG */
284 len += sizeof (struct nd_opt_prefix_info);
287 /* Hardware address. */
288 #ifdef HAVE_STRUCT_SOCKADDR_DL
289 sdl = &ifp->sdl;
290 if (sdl != NULL && sdl->sdl_alen != 0)
292 buf[len++] = ND_OPT_SOURCE_LINKADDR;
293 buf[len++] = (sdl->sdl_alen + 2) >> 3;
295 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
296 len += sdl->sdl_alen;
298 #else
299 if (ifp->hw_addr_len != 0)
301 buf[len++] = ND_OPT_SOURCE_LINKADDR;
302 buf[len++] = (ifp->hw_addr_len + 2) >> 3;
304 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
305 len += ifp->hw_addr_len;
307 #endif /* HAVE_STRUCT_SOCKADDR_DL */
309 msg.msg_name = (void *) &addr;
310 msg.msg_namelen = sizeof (struct sockaddr_in6);
311 msg.msg_iov = &iov;
312 msg.msg_iovlen = 1;
313 msg.msg_control = (void *) adata;
314 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
315 msg.msg_flags = 0;
316 iov.iov_base = buf;
317 iov.iov_len = len;
319 cmsgptr = ZCMSG_FIRSTHDR(&msg);
320 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
321 cmsgptr->cmsg_level = IPPROTO_IPV6;
322 cmsgptr->cmsg_type = IPV6_PKTINFO;
324 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
325 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
326 pkt->ipi6_ifindex = ifp->ifindex;
328 ret = sendmsg (sock, &msg, 0);
329 if (ret < 0)
331 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
332 errno, safe_strerror(errno));
336 static int
337 rtadv_timer (struct thread *thread)
339 struct listnode *node, *nnode;
340 struct interface *ifp;
341 struct zebra_if *zif;
342 int period;
344 rtadv->ra_timer = NULL;
345 if (rtadv->adv_msec_if_count == 0)
347 period = 1000; /* 1 s */
348 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
350 else
352 period = 10; /* 10 ms */
353 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
356 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
358 if (if_is_loopback (ifp))
359 continue;
361 zif = ifp->info;
363 if (zif->rtadv.AdvSendAdvertisements)
365 zif->rtadv.AdvIntervalTimer -= period;
366 if (zif->rtadv.AdvIntervalTimer <= 0)
368 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
369 rtadv_send_packet (rtadv->sock, ifp);
373 return 0;
376 static void
377 rtadv_process_solicit (struct interface *ifp)
379 zlog_info ("Router solicitation received on %s", ifp->name);
381 rtadv_send_packet (rtadv->sock, ifp);
384 static void
385 rtadv_process_advert (void)
387 zlog_info ("Router advertisement received");
390 static void
391 rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
393 struct icmp6_hdr *icmph;
394 struct interface *ifp;
395 struct zebra_if *zif;
397 /* Interface search. */
398 ifp = if_lookup_by_index (ifindex);
399 if (ifp == NULL)
401 zlog_warn ("Unknown interface index: %d", ifindex);
402 return;
405 if (if_is_loopback (ifp))
406 return;
408 /* Check interface configuration. */
409 zif = ifp->info;
410 if (! zif->rtadv.AdvSendAdvertisements)
411 return;
413 /* ICMP message length check. */
414 if (len < sizeof (struct icmp6_hdr))
416 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
417 return;
420 icmph = (struct icmp6_hdr *) buf;
422 /* ICMP message type check. */
423 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
424 icmph->icmp6_type != ND_ROUTER_ADVERT)
426 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
427 return;
430 /* Hoplimit check. */
431 if (hoplimit >= 0 && hoplimit != 255)
433 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
434 hoplimit);
435 return;
438 /* Check ICMP message type. */
439 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
440 rtadv_process_solicit (ifp);
441 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
442 rtadv_process_advert ();
444 return;
447 static int
448 rtadv_read (struct thread *thread)
450 int sock;
451 int len;
452 u_char buf[RTADV_MSG_SIZE];
453 struct sockaddr_in6 from;
454 unsigned int ifindex;
455 int hoplimit = -1;
457 sock = THREAD_FD (thread);
458 rtadv->ra_read = NULL;
460 /* Register myself. */
461 rtadv_event (RTADV_READ, sock);
463 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
465 if (len < 0)
467 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
468 return len;
471 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
473 return 0;
476 static int
477 rtadv_make_socket (void)
479 int sock;
480 int ret;
481 struct icmp6_filter filter;
483 if ( zserv_privs.change (ZPRIVS_RAISE) )
484 zlog_err ("rtadv_make_socket: could not raise privs, %s",
485 safe_strerror (errno) );
487 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
489 if ( zserv_privs.change (ZPRIVS_LOWER) )
490 zlog_err ("rtadv_make_socket: could not lower privs, %s",
491 safe_strerror (errno) );
493 /* When we can't make ICMPV6 socket simply back. Router
494 advertisement feature will not be supported. */
495 if (sock < 0)
496 return -1;
498 ret = setsockopt_ipv6_pktinfo (sock, 1);
499 if (ret < 0)
500 return ret;
501 ret = setsockopt_ipv6_multicast_loop (sock, 0);
502 if (ret < 0)
503 return ret;
504 ret = setsockopt_ipv6_unicast_hops (sock, 255);
505 if (ret < 0)
506 return ret;
507 ret = setsockopt_ipv6_multicast_hops (sock, 255);
508 if (ret < 0)
509 return ret;
510 ret = setsockopt_ipv6_hoplimit (sock, 1);
511 if (ret < 0)
512 return ret;
514 ICMP6_FILTER_SETBLOCKALL(&filter);
515 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
516 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
518 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
519 sizeof (struct icmp6_filter));
520 if (ret < 0)
522 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
523 return ret;
526 return sock;
529 static struct rtadv_prefix *
530 rtadv_prefix_new ()
532 struct rtadv_prefix *new;
534 new = XMALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
535 memset (new, 0, sizeof (struct rtadv_prefix));
537 return new;
540 static void
541 rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
543 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
546 static struct rtadv_prefix *
547 rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
549 struct listnode *node;
550 struct rtadv_prefix *rprefix;
552 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
553 if (prefix_same (&rprefix->prefix, p))
554 return rprefix;
555 return NULL;
558 static struct rtadv_prefix *
559 rtadv_prefix_get (struct list *rplist, struct prefix *p)
561 struct rtadv_prefix *rprefix;
563 rprefix = rtadv_prefix_lookup (rplist, p);
564 if (rprefix)
565 return rprefix;
567 rprefix = rtadv_prefix_new ();
568 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
569 listnode_add (rplist, rprefix);
571 return rprefix;
574 static void
575 rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
577 struct rtadv_prefix *rprefix;
579 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
581 /* Set parameters. */
582 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
583 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
584 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
585 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
586 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
589 static int
590 rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
592 struct rtadv_prefix *rprefix;
594 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
595 if (rprefix != NULL)
597 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
598 rtadv_prefix_free (rprefix);
599 return 1;
601 else
602 return 0;
605 DEFUN (ipv6_nd_suppress_ra,
606 ipv6_nd_suppress_ra_cmd,
607 "ipv6 nd suppress-ra",
608 "Interface IPv6 config commands\n"
609 "Neighbor discovery\n"
610 "Suppress Router Advertisement\n")
612 struct interface *ifp;
613 struct zebra_if *zif;
615 ifp = vty->index;
616 zif = ifp->info;
618 if (if_is_loopback (ifp))
620 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
621 return CMD_WARNING;
624 if (zif->rtadv.AdvSendAdvertisements)
626 zif->rtadv.AdvSendAdvertisements = 0;
627 zif->rtadv.AdvIntervalTimer = 0;
628 rtadv->adv_if_count--;
630 if_leave_all_router (rtadv->sock, ifp);
632 if (rtadv->adv_if_count == 0)
633 rtadv_event (RTADV_STOP, 0);
636 return CMD_SUCCESS;
639 DEFUN (no_ipv6_nd_suppress_ra,
640 no_ipv6_nd_suppress_ra_cmd,
641 "no ipv6 nd suppress-ra",
642 NO_STR
643 "Interface IPv6 config commands\n"
644 "Neighbor discovery\n"
645 "Suppress Router Advertisement\n")
647 struct interface *ifp;
648 struct zebra_if *zif;
650 ifp = vty->index;
651 zif = ifp->info;
653 if (if_is_loopback (ifp))
655 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
656 return CMD_WARNING;
659 if (! zif->rtadv.AdvSendAdvertisements)
661 zif->rtadv.AdvSendAdvertisements = 1;
662 zif->rtadv.AdvIntervalTimer = 0;
663 rtadv->adv_if_count++;
665 if_join_all_router (rtadv->sock, ifp);
667 if (rtadv->adv_if_count == 1)
668 rtadv_event (RTADV_START, rtadv->sock);
671 return CMD_SUCCESS;
674 DEFUN (ipv6_nd_ra_interval_msec,
675 ipv6_nd_ra_interval_msec_cmd,
676 "ipv6 nd ra-interval msec MILLISECONDS",
677 "Interface IPv6 config commands\n"
678 "Neighbor discovery\n"
679 "Router Advertisement interval\n"
680 "Router Advertisement interval in milliseconds\n")
682 int interval;
683 struct interface *ifp;
684 struct zebra_if *zif;
686 ifp = (struct interface *) vty->index;
687 zif = ifp->info;
689 interval = atoi (argv[0]);
691 if (interval <= 0)
693 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
694 return CMD_WARNING;
697 if (zif->rtadv.MaxRtrAdvInterval % 1000)
698 rtadv->adv_msec_if_count--;
700 if (interval % 1000)
701 rtadv->adv_msec_if_count++;
703 zif->rtadv.MaxRtrAdvInterval = interval;
704 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
705 zif->rtadv.AdvIntervalTimer = 0;
707 return CMD_SUCCESS;
710 DEFUN (ipv6_nd_ra_interval,
711 ipv6_nd_ra_interval_cmd,
712 "ipv6 nd ra-interval SECONDS",
713 "Interface IPv6 config commands\n"
714 "Neighbor discovery\n"
715 "Router Advertisement interval\n"
716 "Router Advertisement interval in seconds\n")
718 int interval;
719 struct interface *ifp;
720 struct zebra_if *zif;
722 ifp = (struct interface *) vty->index;
723 zif = ifp->info;
725 interval = atoi (argv[0]);
727 if (interval <= 0)
729 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
730 return CMD_WARNING;
733 if (zif->rtadv.MaxRtrAdvInterval % 1000)
734 rtadv->adv_msec_if_count--;
736 /* convert to milliseconds */
737 interval = interval * 1000;
739 zif->rtadv.MaxRtrAdvInterval = interval;
740 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
741 zif->rtadv.AdvIntervalTimer = 0;
743 return CMD_SUCCESS;
746 DEFUN (no_ipv6_nd_ra_interval,
747 no_ipv6_nd_ra_interval_cmd,
748 "no ipv6 nd ra-interval",
749 NO_STR
750 "Interface IPv6 config commands\n"
751 "Neighbor discovery\n"
752 "Router Advertisement interval\n")
754 struct interface *ifp;
755 struct zebra_if *zif;
757 ifp = (struct interface *) vty->index;
758 zif = ifp->info;
760 if (zif->rtadv.MaxRtrAdvInterval % 1000)
761 rtadv->adv_msec_if_count--;
763 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
764 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
765 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
767 return CMD_SUCCESS;
770 DEFUN (ipv6_nd_ra_lifetime,
771 ipv6_nd_ra_lifetime_cmd,
772 "ipv6 nd ra-lifetime SECONDS",
773 "Interface IPv6 config commands\n"
774 "Neighbor discovery\n"
775 "Router lifetime\n"
776 "Router lifetime in seconds\n")
778 int lifetime;
779 struct interface *ifp;
780 struct zebra_if *zif;
782 ifp = (struct interface *) vty->index;
783 zif = ifp->info;
785 lifetime = atoi (argv[0]);
787 if (lifetime < 0 || lifetime > 0xffff)
789 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
790 return CMD_WARNING;
793 zif->rtadv.AdvDefaultLifetime = lifetime;
795 return CMD_SUCCESS;
798 DEFUN (no_ipv6_nd_ra_lifetime,
799 no_ipv6_nd_ra_lifetime_cmd,
800 "no ipv6 nd ra-lifetime",
801 NO_STR
802 "Interface IPv6 config commands\n"
803 "Neighbor discovery\n"
804 "Router lifetime\n")
806 struct interface *ifp;
807 struct zebra_if *zif;
809 ifp = (struct interface *) vty->index;
810 zif = ifp->info;
812 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
814 return CMD_SUCCESS;
817 DEFUN (ipv6_nd_reachable_time,
818 ipv6_nd_reachable_time_cmd,
819 "ipv6 nd reachable-time MILLISECONDS",
820 "Interface IPv6 config commands\n"
821 "Neighbor discovery\n"
822 "Reachable time\n"
823 "Reachable time in milliseconds\n")
825 u_int32_t rtime;
826 struct interface *ifp;
827 struct zebra_if *zif;
829 ifp = (struct interface *) vty->index;
830 zif = ifp->info;
832 rtime = (u_int32_t) atol (argv[0]);
834 if (rtime > RTADV_MAX_REACHABLE_TIME)
836 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
837 return CMD_WARNING;
840 zif->rtadv.AdvReachableTime = rtime;
842 return CMD_SUCCESS;
845 DEFUN (no_ipv6_nd_reachable_time,
846 no_ipv6_nd_reachable_time_cmd,
847 "no ipv6 nd reachable-time",
848 NO_STR
849 "Interface IPv6 config commands\n"
850 "Neighbor discovery\n"
851 "Reachable time\n")
853 struct interface *ifp;
854 struct zebra_if *zif;
856 ifp = (struct interface *) vty->index;
857 zif = ifp->info;
859 zif->rtadv.AdvReachableTime = 0;
861 return CMD_SUCCESS;
864 DEFUN (ipv6_nd_homeagent_preference,
865 ipv6_nd_homeagent_preference_cmd,
866 "ipv6 nd home-agent-preference PREFERENCE",
867 "Interface IPv6 config commands\n"
868 "Neighbor discovery\n"
869 "Home Agent preference\n"
870 "Home Agent preference value 0..65535\n")
872 u_int32_t hapref;
873 struct interface *ifp;
874 struct zebra_if *zif;
876 ifp = (struct interface *) vty->index;
877 zif = ifp->info;
879 hapref = (u_int32_t) atol (argv[0]);
881 if (hapref > 65535)
883 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
884 return CMD_WARNING;
887 zif->rtadv.HomeAgentPreference = hapref;
889 return CMD_SUCCESS;
892 DEFUN (no_ipv6_nd_homeagent_preference,
893 no_ipv6_nd_homeagent_preference_cmd,
894 "no ipv6 nd home-agent-preference",
895 NO_STR
896 "Interface IPv6 config commands\n"
897 "Neighbor discovery\n"
898 "Home Agent preference\n")
900 struct interface *ifp;
901 struct zebra_if *zif;
903 ifp = (struct interface *) vty->index;
904 zif = ifp->info;
906 zif->rtadv.HomeAgentPreference = 0;
908 return CMD_SUCCESS;
911 DEFUN (ipv6_nd_homeagent_lifetime,
912 ipv6_nd_homeagent_lifetime_cmd,
913 "ipv6 nd home-agent-lifetime SECONDS",
914 "Interface IPv6 config commands\n"
915 "Neighbor discovery\n"
916 "Home Agent lifetime\n"
917 "Home Agent lifetime in seconds\n")
919 u_int32_t ha_ltime;
920 struct interface *ifp;
921 struct zebra_if *zif;
923 ifp = (struct interface *) vty->index;
924 zif = ifp->info;
926 ha_ltime = (u_int32_t) atol (argv[0]);
928 if (ha_ltime > RTADV_MAX_HALIFETIME)
930 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
931 return CMD_WARNING;
934 zif->rtadv.HomeAgentLifetime = ha_ltime;
936 return CMD_SUCCESS;
939 DEFUN (no_ipv6_nd_homeagent_lifetime,
940 no_ipv6_nd_homeagent_lifetime_cmd,
941 "no ipv6 nd home-agent-lifetime",
942 NO_STR
943 "Interface IPv6 config commands\n"
944 "Neighbor discovery\n"
945 "Home Agent lifetime\n")
947 struct interface *ifp;
948 struct zebra_if *zif;
950 ifp = (struct interface *) vty->index;
951 zif = ifp->info;
953 zif->rtadv.HomeAgentLifetime = 0;
955 return CMD_SUCCESS;
958 DEFUN (ipv6_nd_managed_config_flag,
959 ipv6_nd_managed_config_flag_cmd,
960 "ipv6 nd managed-config-flag",
961 "Interface IPv6 config commands\n"
962 "Neighbor discovery\n"
963 "Managed address configuration flag\n")
965 struct interface *ifp;
966 struct zebra_if *zif;
968 ifp = (struct interface *) vty->index;
969 zif = ifp->info;
971 zif->rtadv.AdvManagedFlag = 1;
973 return CMD_SUCCESS;
976 DEFUN (no_ipv6_nd_managed_config_flag,
977 no_ipv6_nd_managed_config_flag_cmd,
978 "no ipv6 nd managed-config-flag",
979 NO_STR
980 "Interface IPv6 config commands\n"
981 "Neighbor discovery\n"
982 "Managed address configuration flag\n")
984 struct interface *ifp;
985 struct zebra_if *zif;
987 ifp = (struct interface *) vty->index;
988 zif = ifp->info;
990 zif->rtadv.AdvManagedFlag = 0;
992 return CMD_SUCCESS;
995 DEFUN (ipv6_nd_homeagent_config_flag,
996 ipv6_nd_homeagent_config_flag_cmd,
997 "ipv6 nd home-agent-config-flag",
998 "Interface IPv6 config commands\n"
999 "Neighbor discovery\n"
1000 "Home Agent configuration flag\n")
1002 struct interface *ifp;
1003 struct zebra_if *zif;
1005 ifp = (struct interface *) vty->index;
1006 zif = ifp->info;
1008 zif->rtadv.AdvHomeAgentFlag = 1;
1010 return CMD_SUCCESS;
1013 DEFUN (no_ipv6_nd_homeagent_config_flag,
1014 no_ipv6_nd_homeagent_config_flag_cmd,
1015 "no ipv6 nd home-agent-config-flag",
1016 NO_STR
1017 "Interface IPv6 config commands\n"
1018 "Neighbor discovery\n"
1019 "Home Agent configuration flag\n")
1021 struct interface *ifp;
1022 struct zebra_if *zif;
1024 ifp = (struct interface *) vty->index;
1025 zif = ifp->info;
1027 zif->rtadv.AdvHomeAgentFlag = 0;
1029 return CMD_SUCCESS;
1032 DEFUN (ipv6_nd_adv_interval_config_option,
1033 ipv6_nd_adv_interval_config_option_cmd,
1034 "ipv6 nd adv-interval-option",
1035 "Interface IPv6 config commands\n"
1036 "Neighbor discovery\n"
1037 "Advertisement Interval Option\n")
1039 struct interface *ifp;
1040 struct zebra_if *zif;
1042 ifp = (struct interface *) vty->index;
1043 zif = ifp->info;
1045 zif->rtadv.AdvIntervalOption = 1;
1047 return CMD_SUCCESS;
1050 DEFUN (no_ipv6_nd_adv_interval_config_option,
1051 no_ipv6_nd_adv_interval_config_option_cmd,
1052 "no ipv6 nd adv-interval-option",
1053 NO_STR
1054 "Interface IPv6 config commands\n"
1055 "Neighbor discovery\n"
1056 "Advertisement Interval Option\n")
1058 struct interface *ifp;
1059 struct zebra_if *zif;
1061 ifp = (struct interface *) vty->index;
1062 zif = ifp->info;
1064 zif->rtadv.AdvIntervalOption = 0;
1066 return CMD_SUCCESS;
1069 DEFUN (ipv6_nd_other_config_flag,
1070 ipv6_nd_other_config_flag_cmd,
1071 "ipv6 nd other-config-flag",
1072 "Interface IPv6 config commands\n"
1073 "Neighbor discovery\n"
1074 "Other statefull configuration flag\n")
1076 struct interface *ifp;
1077 struct zebra_if *zif;
1079 ifp = (struct interface *) vty->index;
1080 zif = ifp->info;
1082 zif->rtadv.AdvOtherConfigFlag = 1;
1084 return CMD_SUCCESS;
1087 DEFUN (no_ipv6_nd_other_config_flag,
1088 no_ipv6_nd_other_config_flag_cmd,
1089 "no ipv6 nd other-config-flag",
1090 NO_STR
1091 "Interface IPv6 config commands\n"
1092 "Neighbor discovery\n"
1093 "Other statefull configuration flag\n")
1095 struct interface *ifp;
1096 struct zebra_if *zif;
1098 ifp = (struct interface *) vty->index;
1099 zif = ifp->info;
1101 zif->rtadv.AdvOtherConfigFlag = 0;
1103 return CMD_SUCCESS;
1106 DEFUN (ipv6_nd_prefix,
1107 ipv6_nd_prefix_cmd,
1108 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1109 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
1110 "Interface IPv6 config commands\n"
1111 "Neighbor discovery\n"
1112 "Prefix information\n"
1113 "IPv6 prefix\n"
1114 "Valid lifetime in seconds\n"
1115 "Infinite valid lifetime\n"
1116 "Preferred lifetime in seconds\n"
1117 "Infinite preferred lifetime\n"
1118 "Do not use prefix for onlink determination\n"
1119 "Do not use prefix for autoconfiguration\n"
1120 "Set Router Address flag\n")
1122 int i;
1123 int ret;
1124 int cursor = 1;
1125 struct interface *ifp;
1126 struct zebra_if *zebra_if;
1127 struct rtadv_prefix rp;
1129 ifp = (struct interface *) vty->index;
1130 zebra_if = ifp->info;
1132 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1133 if (!ret)
1135 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1136 return CMD_WARNING;
1138 rp.AdvOnLinkFlag = 1;
1139 rp.AdvAutonomousFlag = 1;
1140 rp.AdvRouterAddressFlag = 0;
1141 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1142 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1144 if (argc > 1)
1146 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
1148 if ( strncmp (argv[1], "i", 1) == 0)
1149 rp.AdvValidLifetime = UINT32_MAX;
1150 else
1151 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1152 (char **)NULL, 10);
1154 if ( strncmp (argv[2], "i", 1) == 0)
1155 rp.AdvPreferredLifetime = UINT32_MAX;
1156 else
1157 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1158 (char **)NULL, 10);
1160 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1162 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1163 return CMD_WARNING;
1165 cursor = cursor + 2;
1167 if (argc > cursor)
1169 for (i = cursor; i < argc; i++)
1171 if (strncmp (argv[i], "of", 2) == 0)
1172 rp.AdvOnLinkFlag = 0;
1173 if (strncmp (argv[i], "no", 2) == 0)
1174 rp.AdvAutonomousFlag = 0;
1175 if (strncmp (argv[i], "ro", 2) == 0)
1176 rp.AdvRouterAddressFlag = 1;
1181 rtadv_prefix_set (zebra_if, &rp);
1183 return CMD_SUCCESS;
1186 ALIAS (ipv6_nd_prefix,
1187 ipv6_nd_prefix_val_nortaddr_cmd,
1188 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1189 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1190 "Interface IPv6 config commands\n"
1191 "Neighbor discovery\n"
1192 "Prefix information\n"
1193 "IPv6 prefix\n"
1194 "Valid lifetime in seconds\n"
1195 "Infinite valid lifetime\n"
1196 "Preferred lifetime in seconds\n"
1197 "Infinite preferred lifetime\n"
1198 "Do not use prefix for onlink determination\n"
1199 "Do not use prefix for autoconfiguration\n")
1201 ALIAS (ipv6_nd_prefix,
1202 ipv6_nd_prefix_val_rev_cmd,
1203 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1204 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1205 "Interface IPv6 config commands\n"
1206 "Neighbor discovery\n"
1207 "Prefix information\n"
1208 "IPv6 prefix\n"
1209 "Valid lifetime in seconds\n"
1210 "Infinite valid lifetime\n"
1211 "Preferred lifetime in seconds\n"
1212 "Infinite preferred lifetime\n"
1213 "Do not use prefix for autoconfiguration\n"
1214 "Do not use prefix for onlink determination\n")
1216 ALIAS (ipv6_nd_prefix,
1217 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1218 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1219 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1220 "Interface IPv6 config commands\n"
1221 "Neighbor discovery\n"
1222 "Prefix information\n"
1223 "IPv6 prefix\n"
1224 "Valid lifetime in seconds\n"
1225 "Infinite valid lifetime\n"
1226 "Preferred lifetime in seconds\n"
1227 "Infinite preferred lifetime\n"
1228 "Do not use prefix for autoconfiguration\n"
1229 "Do not use prefix for onlink determination\n"
1230 "Set Router Address flag\n")
1232 ALIAS (ipv6_nd_prefix,
1233 ipv6_nd_prefix_val_noauto_cmd,
1234 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1235 "(<0-4294967295>|infinite) (no-autoconfig|)",
1236 "Interface IPv6 config commands\n"
1237 "Neighbor discovery\n"
1238 "Prefix information\n"
1239 "IPv6 prefix\n"
1240 "Valid lifetime in seconds\n"
1241 "Infinite valid lifetime\n"
1242 "Preferred lifetime in seconds\n"
1243 "Infinite preferred lifetime\n"
1244 "Do not use prefix for autoconfiguration")
1246 ALIAS (ipv6_nd_prefix,
1247 ipv6_nd_prefix_val_offlink_cmd,
1248 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1249 "(<0-4294967295>|infinite) (off-link|)",
1250 "Interface IPv6 config commands\n"
1251 "Neighbor discovery\n"
1252 "Prefix information\n"
1253 "IPv6 prefix\n"
1254 "Valid lifetime in seconds\n"
1255 "Infinite valid lifetime\n"
1256 "Preferred lifetime in seconds\n"
1257 "Infinite preferred lifetime\n"
1258 "Do not use prefix for onlink determination\n")
1260 ALIAS (ipv6_nd_prefix,
1261 ipv6_nd_prefix_val_rtaddr_cmd,
1262 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1263 "(<0-4294967295>|infinite) (router-address|)",
1264 "Interface IPv6 config commands\n"
1265 "Neighbor discovery\n"
1266 "Prefix information\n"
1267 "IPv6 prefix\n"
1268 "Valid lifetime in seconds\n"
1269 "Infinite valid lifetime\n"
1270 "Preferred lifetime in seconds\n"
1271 "Infinite preferred lifetime\n"
1272 "Set Router Address flag\n")
1274 ALIAS (ipv6_nd_prefix,
1275 ipv6_nd_prefix_val_cmd,
1276 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1277 "(<0-4294967295>|infinite)",
1278 "Interface IPv6 config commands\n"
1279 "Neighbor discovery\n"
1280 "Prefix information\n"
1281 "IPv6 prefix\n"
1282 "Valid lifetime in seconds\n"
1283 "Infinite valid lifetime\n"
1284 "Preferred lifetime in seconds\n"
1285 "Infinite preferred lifetime\n")
1287 ALIAS (ipv6_nd_prefix,
1288 ipv6_nd_prefix_noval_cmd,
1289 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1290 "Interface IPv6 config commands\n"
1291 "Neighbor discovery\n"
1292 "Prefix information\n"
1293 "IPv6 prefix\n"
1294 "Do not use prefix for autoconfiguration\n"
1295 "Do not use prefix for onlink determination\n")
1297 ALIAS (ipv6_nd_prefix,
1298 ipv6_nd_prefix_noval_rev_cmd,
1299 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1300 "Interface IPv6 config commands\n"
1301 "Neighbor discovery\n"
1302 "Prefix information\n"
1303 "IPv6 prefix\n"
1304 "Do not use prefix for onlink determination\n"
1305 "Do not use prefix for autoconfiguration\n")
1307 ALIAS (ipv6_nd_prefix,
1308 ipv6_nd_prefix_noval_noauto_cmd,
1309 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1310 "Interface IPv6 config commands\n"
1311 "Neighbor discovery\n"
1312 "Prefix information\n"
1313 "IPv6 prefix\n"
1314 "Do not use prefix for autoconfiguration\n")
1316 ALIAS (ipv6_nd_prefix,
1317 ipv6_nd_prefix_noval_offlink_cmd,
1318 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1319 "Interface IPv6 config commands\n"
1320 "Neighbor discovery\n"
1321 "Prefix information\n"
1322 "IPv6 prefix\n"
1323 "Do not use prefix for onlink determination\n")
1325 ALIAS (ipv6_nd_prefix,
1326 ipv6_nd_prefix_noval_rtaddr_cmd,
1327 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1328 "Interface IPv6 config commands\n"
1329 "Neighbor discovery\n"
1330 "Prefix information\n"
1331 "IPv6 prefix\n"
1332 "Set Router Address flag\n")
1334 ALIAS (ipv6_nd_prefix,
1335 ipv6_nd_prefix_prefix_cmd,
1336 "ipv6 nd prefix X:X::X:X/M",
1337 "Interface IPv6 config commands\n"
1338 "Neighbor discovery\n"
1339 "Prefix information\n"
1340 "IPv6 prefix\n")
1342 DEFUN (no_ipv6_nd_prefix,
1343 no_ipv6_nd_prefix_cmd,
1344 "no ipv6 nd prefix IPV6PREFIX",
1345 NO_STR
1346 "Interface IPv6 config commands\n"
1347 "Neighbor discovery\n"
1348 "Prefix information\n"
1349 "IPv6 prefix\n")
1351 int ret;
1352 struct interface *ifp;
1353 struct zebra_if *zebra_if;
1354 struct rtadv_prefix rp;
1356 ifp = (struct interface *) vty->index;
1357 zebra_if = ifp->info;
1359 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1360 if (!ret)
1362 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1363 return CMD_WARNING;
1366 ret = rtadv_prefix_reset (zebra_if, &rp);
1367 if (!ret)
1369 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1370 return CMD_WARNING;
1373 return CMD_SUCCESS;
1375 /* Write configuration about router advertisement. */
1376 void
1377 rtadv_config_write (struct vty *vty, struct interface *ifp)
1379 struct zebra_if *zif;
1380 struct listnode *node;
1381 struct rtadv_prefix *rprefix;
1382 u_char buf[INET6_ADDRSTRLEN];
1383 int interval;
1385 if (! rtadv)
1386 return;
1388 zif = ifp->info;
1390 if (! if_is_loopback (ifp))
1392 if (zif->rtadv.AdvSendAdvertisements)
1393 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1394 else
1395 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1399 interval = zif->rtadv.MaxRtrAdvInterval;
1400 if (interval % 1000)
1401 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1402 VTY_NEWLINE);
1403 else
1404 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1405 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
1406 VTY_NEWLINE);
1408 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1409 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1410 VTY_NEWLINE);
1412 if (zif->rtadv.AdvReachableTime)
1413 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1414 VTY_NEWLINE);
1416 if (zif->rtadv.AdvManagedFlag)
1417 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1419 if (zif->rtadv.AdvOtherConfigFlag)
1420 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1422 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
1424 vty_out (vty, " ipv6 nd prefix %s/%d",
1425 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
1426 (char *) buf, INET6_ADDRSTRLEN),
1427 rprefix->prefix.prefixlen);
1428 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1429 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1431 if (rprefix->AdvValidLifetime == UINT32_MAX)
1432 vty_out (vty, " infinite");
1433 else
1434 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1435 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1436 vty_out (vty, " infinite");
1437 else
1438 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1440 if (!rprefix->AdvOnLinkFlag)
1441 vty_out (vty, " off-link");
1442 if (!rprefix->AdvAutonomousFlag)
1443 vty_out (vty, " no-autoconfig");
1444 if (rprefix->AdvRouterAddressFlag)
1445 vty_out (vty, " router-address");
1446 vty_out (vty, "%s", VTY_NEWLINE);
1451 static void
1452 rtadv_event (enum rtadv_event event, int val)
1454 switch (event)
1456 case RTADV_START:
1457 if (! rtadv->ra_read)
1458 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1459 if (! rtadv->ra_timer)
1460 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1461 NULL, 0);
1462 break;
1463 case RTADV_STOP:
1464 if (rtadv->ra_timer)
1466 thread_cancel (rtadv->ra_timer);
1467 rtadv->ra_timer = NULL;
1469 if (rtadv->ra_read)
1471 thread_cancel (rtadv->ra_read);
1472 rtadv->ra_read = NULL;
1474 break;
1475 case RTADV_TIMER:
1476 if (! rtadv->ra_timer)
1477 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1478 val);
1479 break;
1480 case RTADV_TIMER_MSEC:
1481 if (! rtadv->ra_timer)
1482 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1483 NULL, val);
1484 break;
1485 case RTADV_READ:
1486 if (! rtadv->ra_read)
1487 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1488 break;
1489 default:
1490 break;
1492 return;
1495 void
1496 rtadv_init (void)
1498 int sock;
1500 sock = rtadv_make_socket ();
1501 if (sock < 0)
1502 return;
1504 rtadv = rtadv_new ();
1505 rtadv->sock = sock;
1507 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1508 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
1509 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
1510 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
1511 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1512 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1513 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1514 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1515 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1516 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1517 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1518 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1519 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
1520 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1521 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1522 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1523 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1524 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1525 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1526 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1527 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
1528 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
1529 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1530 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
1531 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1532 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1533 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
1534 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
1535 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1536 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1537 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1538 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1539 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
1540 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
1541 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1542 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
1545 static int
1546 if_join_all_router (int sock, struct interface *ifp)
1548 int ret;
1550 struct ipv6_mreq mreq;
1552 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1553 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1554 mreq.ipv6mr_interface = ifp->ifindex;
1556 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1557 (char *) &mreq, sizeof mreq);
1558 if (ret < 0)
1559 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
1561 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1563 return 0;
1566 static int
1567 if_leave_all_router (int sock, struct interface *ifp)
1569 int ret;
1571 struct ipv6_mreq mreq;
1573 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1574 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1575 mreq.ipv6mr_interface = ifp->ifindex;
1577 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1578 (char *) &mreq, sizeof mreq);
1579 if (ret < 0)
1580 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
1582 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1584 return 0;
1587 #else
1588 void
1589 rtadv_init (void)
1591 /* Empty.*/;
1593 #endif /* RTADV && HAVE_IPV6 */