ospfd: Tighten up the connected check for redistribution
[jleu-quagga.git] / zebra / rtadv.c
blobff96648a15d2d22359513a30431f5c9c121669f4
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 return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));
90 static void
91 rtadv_free (struct rtadv *rtadv)
93 XFREE (MTYPE_TMP, rtadv);
96 static int
97 rtadv_recv_packet (int sock, u_char *buf, int buflen,
98 struct sockaddr_in6 *from, unsigned int *ifindex,
99 int *hoplimit)
101 int ret;
102 struct msghdr msg;
103 struct iovec iov;
104 struct cmsghdr *cmsgptr;
105 struct in6_addr dst;
107 char adata[1024];
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;
119 /* If recvmsg fail return minus value. */
120 ret = recvmsg (sock, &msg, 0);
121 if (ret < 0)
122 return ret;
124 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
125 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
127 /* I want interface index which this packet comes from. */
128 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
129 cmsgptr->cmsg_type == IPV6_PKTINFO)
131 struct in6_pktinfo *ptr;
133 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
134 *ifindex = ptr->ipi6_ifindex;
135 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
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));
143 return ret;
146 #define RTADV_MSG_SIZE 4096
148 /* Send router advertisement packet. */
149 static void
150 rtadv_send_packet (int sock, struct interface *ifp)
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_STRUCT_SOCKADDR_DL
158 struct sockaddr_dl *sdl;
159 #endif /* HAVE_STRUCT_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 struct rtadv_prefix *rprefix;
167 u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
168 struct listnode *node;
171 * Allocate control message bufffer. This is dynamic because
172 * CMSG_SPACE is not guaranteed not to call a function. Note that
173 * the size will be different on different architectures due to
174 * differing alignment rules.
176 if (adata == NULL)
178 /* XXX Free on shutdown. */
179 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
181 if (adata == NULL)
182 zlog_err("rtadv_send_packet: can't malloc control data\n");
185 /* Logging of packet. */
186 if (IS_ZEBRA_DEBUG_PACKET)
187 zlog_debug ("Router advertisement send to %s", ifp->name);
189 /* Fill in sockaddr_in6. */
190 memset (&addr, 0, sizeof (struct sockaddr_in6));
191 addr.sin6_family = AF_INET6;
192 #ifdef SIN6_LEN
193 addr.sin6_len = sizeof (struct sockaddr_in6);
194 #endif /* SIN6_LEN */
195 addr.sin6_port = htons (IPPROTO_ICMPV6);
196 memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
198 /* Fetch interface information. */
199 zif = ifp->info;
201 /* Make router advertisement message. */
202 rtadv = (struct nd_router_advert *) buf;
204 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
205 rtadv->nd_ra_code = 0;
206 rtadv->nd_ra_cksum = 0;
208 rtadv->nd_ra_curhoplimit = 64;
210 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
211 rtadv->nd_ra_flags_reserved =
212 zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
213 rtadv->nd_ra_flags_reserved <<= 3;
215 if (zif->rtadv.AdvManagedFlag)
216 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
217 if (zif->rtadv.AdvOtherConfigFlag)
218 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
219 if (zif->rtadv.AdvHomeAgentFlag)
220 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
221 rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
222 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
223 rtadv->nd_ra_retransmit = htonl (0);
225 len = sizeof (struct nd_router_advert);
227 if (zif->rtadv.AdvHomeAgentFlag)
229 struct nd_opt_homeagent_info *ndopt_hai =
230 (struct nd_opt_homeagent_info *)(buf + len);
231 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
232 ndopt_hai->nd_opt_hai_len = 1;
233 ndopt_hai->nd_opt_hai_reserved = 0;
234 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
235 ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);
236 len += sizeof(struct nd_opt_homeagent_info);
239 if (zif->rtadv.AdvIntervalOption)
241 struct nd_opt_adv_interval *ndopt_adv =
242 (struct nd_opt_adv_interval *)(buf + len);
243 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
244 ndopt_adv->nd_opt_ai_len = 1;
245 ndopt_adv->nd_opt_ai_reserved = 0;
246 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
247 len += sizeof(struct nd_opt_adv_interval);
250 /* Fill in prefix. */
251 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
253 struct nd_opt_prefix_info *pinfo;
255 pinfo = (struct nd_opt_prefix_info *) (buf + len);
257 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
258 pinfo->nd_opt_pi_len = 4;
259 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
261 pinfo->nd_opt_pi_flags_reserved = 0;
262 if (rprefix->AdvOnLinkFlag)
263 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
264 if (rprefix->AdvAutonomousFlag)
265 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
266 if (rprefix->AdvRouterAddressFlag)
267 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
269 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
270 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
271 pinfo->nd_opt_pi_reserved2 = 0;
273 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
274 sizeof (struct in6_addr));
276 #ifdef DEBUG
278 u_char buf[INET6_ADDRSTRLEN];
280 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
281 buf, INET6_ADDRSTRLEN));
284 #endif /* DEBUG */
286 len += sizeof (struct nd_opt_prefix_info);
289 /* Hardware address. */
290 #ifdef HAVE_STRUCT_SOCKADDR_DL
291 sdl = &ifp->sdl;
292 if (sdl != NULL && sdl->sdl_alen != 0)
294 buf[len++] = ND_OPT_SOURCE_LINKADDR;
295 buf[len++] = (sdl->sdl_alen + 2) >> 3;
297 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
298 len += sdl->sdl_alen;
300 #else
301 if (ifp->hw_addr_len != 0)
303 buf[len++] = ND_OPT_SOURCE_LINKADDR;
304 buf[len++] = (ifp->hw_addr_len + 2) >> 3;
306 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
307 len += ifp->hw_addr_len;
309 #endif /* HAVE_STRUCT_SOCKADDR_DL */
311 msg.msg_name = (void *) &addr;
312 msg.msg_namelen = sizeof (struct sockaddr_in6);
313 msg.msg_iov = &iov;
314 msg.msg_iovlen = 1;
315 msg.msg_control = (void *) adata;
316 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
317 msg.msg_flags = 0;
318 iov.iov_base = buf;
319 iov.iov_len = len;
321 cmsgptr = ZCMSG_FIRSTHDR(&msg);
322 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
323 cmsgptr->cmsg_level = IPPROTO_IPV6;
324 cmsgptr->cmsg_type = IPV6_PKTINFO;
326 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
327 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
328 pkt->ipi6_ifindex = ifp->ifindex;
330 ret = sendmsg (sock, &msg, 0);
331 if (ret < 0)
333 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
334 errno, safe_strerror(errno));
338 static int
339 rtadv_timer (struct thread *thread)
341 struct listnode *node, *nnode;
342 struct interface *ifp;
343 struct zebra_if *zif;
344 int period;
346 rtadv->ra_timer = NULL;
347 if (rtadv->adv_msec_if_count == 0)
349 period = 1000; /* 1 s */
350 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
352 else
354 period = 10; /* 10 ms */
355 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
358 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
360 if (if_is_loopback (ifp))
361 continue;
363 zif = ifp->info;
365 if (zif->rtadv.AdvSendAdvertisements)
367 zif->rtadv.AdvIntervalTimer -= period;
368 if (zif->rtadv.AdvIntervalTimer <= 0)
370 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
371 rtadv_send_packet (rtadv->sock, ifp);
375 return 0;
378 static void
379 rtadv_process_solicit (struct interface *ifp)
381 zlog_info ("Router solicitation received on %s", ifp->name);
383 rtadv_send_packet (rtadv->sock, ifp);
386 static void
387 rtadv_process_advert (void)
389 zlog_info ("Router advertisement received");
392 static void
393 rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
395 struct icmp6_hdr *icmph;
396 struct interface *ifp;
397 struct zebra_if *zif;
399 /* Interface search. */
400 ifp = if_lookup_by_index (ifindex);
401 if (ifp == NULL)
403 zlog_warn ("Unknown interface index: %d", ifindex);
404 return;
407 if (if_is_loopback (ifp))
408 return;
410 /* Check interface configuration. */
411 zif = ifp->info;
412 if (! zif->rtadv.AdvSendAdvertisements)
413 return;
415 /* ICMP message length check. */
416 if (len < sizeof (struct icmp6_hdr))
418 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
419 return;
422 icmph = (struct icmp6_hdr *) buf;
424 /* ICMP message type check. */
425 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
426 icmph->icmp6_type != ND_ROUTER_ADVERT)
428 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
429 return;
432 /* Hoplimit check. */
433 if (hoplimit >= 0 && hoplimit != 255)
435 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
436 hoplimit);
437 return;
440 /* Check ICMP message type. */
441 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
442 rtadv_process_solicit (ifp);
443 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
444 rtadv_process_advert ();
446 return;
449 static int
450 rtadv_read (struct thread *thread)
452 int sock;
453 int len;
454 u_char buf[RTADV_MSG_SIZE];
455 struct sockaddr_in6 from;
456 unsigned int ifindex;
457 int hoplimit = -1;
459 sock = THREAD_FD (thread);
460 rtadv->ra_read = NULL;
462 /* Register myself. */
463 rtadv_event (RTADV_READ, sock);
465 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
467 if (len < 0)
469 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
470 return len;
473 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
475 return 0;
478 static int
479 rtadv_make_socket (void)
481 int sock;
482 int ret;
483 struct icmp6_filter filter;
485 if ( zserv_privs.change (ZPRIVS_RAISE) )
486 zlog_err ("rtadv_make_socket: could not raise privs, %s",
487 safe_strerror (errno) );
489 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
491 if ( zserv_privs.change (ZPRIVS_LOWER) )
492 zlog_err ("rtadv_make_socket: could not lower privs, %s",
493 safe_strerror (errno) );
495 /* When we can't make ICMPV6 socket simply back. Router
496 advertisement feature will not be supported. */
497 if (sock < 0)
498 return -1;
500 ret = setsockopt_ipv6_pktinfo (sock, 1);
501 if (ret < 0)
502 return ret;
503 ret = setsockopt_ipv6_multicast_loop (sock, 0);
504 if (ret < 0)
505 return ret;
506 ret = setsockopt_ipv6_unicast_hops (sock, 255);
507 if (ret < 0)
508 return ret;
509 ret = setsockopt_ipv6_multicast_hops (sock, 255);
510 if (ret < 0)
511 return ret;
512 ret = setsockopt_ipv6_hoplimit (sock, 1);
513 if (ret < 0)
514 return ret;
516 ICMP6_FILTER_SETBLOCKALL(&filter);
517 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
518 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
520 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
521 sizeof (struct icmp6_filter));
522 if (ret < 0)
524 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
525 return ret;
528 return sock;
531 static struct rtadv_prefix *
532 rtadv_prefix_new (void)
534 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
537 static void
538 rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
540 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
543 static struct rtadv_prefix *
544 rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
546 struct listnode *node;
547 struct rtadv_prefix *rprefix;
549 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
550 if (prefix_same (&rprefix->prefix, p))
551 return rprefix;
552 return NULL;
555 static struct rtadv_prefix *
556 rtadv_prefix_get (struct list *rplist, struct prefix *p)
558 struct rtadv_prefix *rprefix;
560 rprefix = rtadv_prefix_lookup (rplist, p);
561 if (rprefix)
562 return rprefix;
564 rprefix = rtadv_prefix_new ();
565 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
566 listnode_add (rplist, rprefix);
568 return rprefix;
571 static void
572 rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
574 struct rtadv_prefix *rprefix;
576 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
578 /* Set parameters. */
579 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
580 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
581 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
582 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
583 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
586 static int
587 rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
589 struct rtadv_prefix *rprefix;
591 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
592 if (rprefix != NULL)
594 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
595 rtadv_prefix_free (rprefix);
596 return 1;
598 else
599 return 0;
602 DEFUN (ipv6_nd_suppress_ra,
603 ipv6_nd_suppress_ra_cmd,
604 "ipv6 nd suppress-ra",
605 "Interface IPv6 config commands\n"
606 "Neighbor discovery\n"
607 "Suppress Router Advertisement\n")
609 struct interface *ifp;
610 struct zebra_if *zif;
612 ifp = vty->index;
613 zif = ifp->info;
615 if (if_is_loopback (ifp))
617 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
618 return CMD_WARNING;
621 if (zif->rtadv.AdvSendAdvertisements)
623 zif->rtadv.AdvSendAdvertisements = 0;
624 zif->rtadv.AdvIntervalTimer = 0;
625 rtadv->adv_if_count--;
627 if_leave_all_router (rtadv->sock, ifp);
629 if (rtadv->adv_if_count == 0)
630 rtadv_event (RTADV_STOP, 0);
633 return CMD_SUCCESS;
636 DEFUN (no_ipv6_nd_suppress_ra,
637 no_ipv6_nd_suppress_ra_cmd,
638 "no ipv6 nd suppress-ra",
639 NO_STR
640 "Interface IPv6 config commands\n"
641 "Neighbor discovery\n"
642 "Suppress Router Advertisement\n")
644 struct interface *ifp;
645 struct zebra_if *zif;
647 ifp = vty->index;
648 zif = ifp->info;
650 if (if_is_loopback (ifp))
652 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
653 return CMD_WARNING;
656 if (! zif->rtadv.AdvSendAdvertisements)
658 zif->rtadv.AdvSendAdvertisements = 1;
659 zif->rtadv.AdvIntervalTimer = 0;
660 rtadv->adv_if_count++;
662 if_join_all_router (rtadv->sock, ifp);
664 if (rtadv->adv_if_count == 1)
665 rtadv_event (RTADV_START, rtadv->sock);
668 return CMD_SUCCESS;
671 DEFUN (ipv6_nd_ra_interval_msec,
672 ipv6_nd_ra_interval_msec_cmd,
673 "ipv6 nd ra-interval msec MILLISECONDS",
674 "Interface IPv6 config commands\n"
675 "Neighbor discovery\n"
676 "Router Advertisement interval\n"
677 "Router Advertisement interval in milliseconds\n")
679 int interval;
680 struct interface *ifp;
681 struct zebra_if *zif;
683 ifp = (struct interface *) vty->index;
684 zif = ifp->info;
686 interval = atoi (argv[0]);
688 if (interval <= 0)
690 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
691 return CMD_WARNING;
694 if (zif->rtadv.MaxRtrAdvInterval % 1000)
695 rtadv->adv_msec_if_count--;
697 if (interval % 1000)
698 rtadv->adv_msec_if_count++;
700 zif->rtadv.MaxRtrAdvInterval = interval;
701 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
702 zif->rtadv.AdvIntervalTimer = 0;
704 return CMD_SUCCESS;
707 DEFUN (ipv6_nd_ra_interval,
708 ipv6_nd_ra_interval_cmd,
709 "ipv6 nd ra-interval SECONDS",
710 "Interface IPv6 config commands\n"
711 "Neighbor discovery\n"
712 "Router Advertisement interval\n"
713 "Router Advertisement interval in seconds\n")
715 int interval;
716 struct interface *ifp;
717 struct zebra_if *zif;
719 ifp = (struct interface *) vty->index;
720 zif = ifp->info;
722 interval = atoi (argv[0]);
724 if (interval <= 0)
726 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
727 return CMD_WARNING;
730 if (zif->rtadv.MaxRtrAdvInterval % 1000)
731 rtadv->adv_msec_if_count--;
733 /* convert to milliseconds */
734 interval = interval * 1000;
736 zif->rtadv.MaxRtrAdvInterval = interval;
737 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
738 zif->rtadv.AdvIntervalTimer = 0;
740 return CMD_SUCCESS;
743 DEFUN (no_ipv6_nd_ra_interval,
744 no_ipv6_nd_ra_interval_cmd,
745 "no ipv6 nd ra-interval",
746 NO_STR
747 "Interface IPv6 config commands\n"
748 "Neighbor discovery\n"
749 "Router Advertisement interval\n")
751 struct interface *ifp;
752 struct zebra_if *zif;
754 ifp = (struct interface *) vty->index;
755 zif = ifp->info;
757 if (zif->rtadv.MaxRtrAdvInterval % 1000)
758 rtadv->adv_msec_if_count--;
760 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
761 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
762 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
764 return CMD_SUCCESS;
767 DEFUN (ipv6_nd_ra_lifetime,
768 ipv6_nd_ra_lifetime_cmd,
769 "ipv6 nd ra-lifetime SECONDS",
770 "Interface IPv6 config commands\n"
771 "Neighbor discovery\n"
772 "Router lifetime\n"
773 "Router lifetime in seconds\n")
775 int lifetime;
776 struct interface *ifp;
777 struct zebra_if *zif;
779 ifp = (struct interface *) vty->index;
780 zif = ifp->info;
782 lifetime = atoi (argv[0]);
784 if (lifetime < 0 || lifetime > 0xffff)
786 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
787 return CMD_WARNING;
790 zif->rtadv.AdvDefaultLifetime = lifetime;
792 return CMD_SUCCESS;
795 DEFUN (no_ipv6_nd_ra_lifetime,
796 no_ipv6_nd_ra_lifetime_cmd,
797 "no ipv6 nd ra-lifetime",
798 NO_STR
799 "Interface IPv6 config commands\n"
800 "Neighbor discovery\n"
801 "Router lifetime\n")
803 struct interface *ifp;
804 struct zebra_if *zif;
806 ifp = (struct interface *) vty->index;
807 zif = ifp->info;
809 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
811 return CMD_SUCCESS;
814 DEFUN (ipv6_nd_reachable_time,
815 ipv6_nd_reachable_time_cmd,
816 "ipv6 nd reachable-time MILLISECONDS",
817 "Interface IPv6 config commands\n"
818 "Neighbor discovery\n"
819 "Reachable time\n"
820 "Reachable time in milliseconds\n")
822 u_int32_t rtime;
823 struct interface *ifp;
824 struct zebra_if *zif;
826 ifp = (struct interface *) vty->index;
827 zif = ifp->info;
829 rtime = (u_int32_t) atol (argv[0]);
831 if (rtime > RTADV_MAX_REACHABLE_TIME)
833 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
834 return CMD_WARNING;
837 zif->rtadv.AdvReachableTime = rtime;
839 return CMD_SUCCESS;
842 DEFUN (no_ipv6_nd_reachable_time,
843 no_ipv6_nd_reachable_time_cmd,
844 "no ipv6 nd reachable-time",
845 NO_STR
846 "Interface IPv6 config commands\n"
847 "Neighbor discovery\n"
848 "Reachable time\n")
850 struct interface *ifp;
851 struct zebra_if *zif;
853 ifp = (struct interface *) vty->index;
854 zif = ifp->info;
856 zif->rtadv.AdvReachableTime = 0;
858 return CMD_SUCCESS;
861 DEFUN (ipv6_nd_homeagent_preference,
862 ipv6_nd_homeagent_preference_cmd,
863 "ipv6 nd home-agent-preference PREFERENCE",
864 "Interface IPv6 config commands\n"
865 "Neighbor discovery\n"
866 "Home Agent preference\n"
867 "Home Agent preference value 0..65535\n")
869 u_int32_t hapref;
870 struct interface *ifp;
871 struct zebra_if *zif;
873 ifp = (struct interface *) vty->index;
874 zif = ifp->info;
876 hapref = (u_int32_t) atol (argv[0]);
878 if (hapref > 65535)
880 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
881 return CMD_WARNING;
884 zif->rtadv.HomeAgentPreference = hapref;
886 return CMD_SUCCESS;
889 DEFUN (no_ipv6_nd_homeagent_preference,
890 no_ipv6_nd_homeagent_preference_cmd,
891 "no ipv6 nd home-agent-preference",
892 NO_STR
893 "Interface IPv6 config commands\n"
894 "Neighbor discovery\n"
895 "Home Agent preference\n")
897 struct interface *ifp;
898 struct zebra_if *zif;
900 ifp = (struct interface *) vty->index;
901 zif = ifp->info;
903 zif->rtadv.HomeAgentPreference = 0;
905 return CMD_SUCCESS;
908 DEFUN (ipv6_nd_homeagent_lifetime,
909 ipv6_nd_homeagent_lifetime_cmd,
910 "ipv6 nd home-agent-lifetime SECONDS",
911 "Interface IPv6 config commands\n"
912 "Neighbor discovery\n"
913 "Home Agent lifetime\n"
914 "Home Agent lifetime in seconds\n")
916 u_int32_t ha_ltime;
917 struct interface *ifp;
918 struct zebra_if *zif;
920 ifp = (struct interface *) vty->index;
921 zif = ifp->info;
923 ha_ltime = (u_int32_t) atol (argv[0]);
925 if (ha_ltime > RTADV_MAX_HALIFETIME)
927 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
928 return CMD_WARNING;
931 zif->rtadv.HomeAgentLifetime = ha_ltime;
933 return CMD_SUCCESS;
936 DEFUN (no_ipv6_nd_homeagent_lifetime,
937 no_ipv6_nd_homeagent_lifetime_cmd,
938 "no ipv6 nd home-agent-lifetime",
939 NO_STR
940 "Interface IPv6 config commands\n"
941 "Neighbor discovery\n"
942 "Home Agent lifetime\n")
944 struct interface *ifp;
945 struct zebra_if *zif;
947 ifp = (struct interface *) vty->index;
948 zif = ifp->info;
950 zif->rtadv.HomeAgentLifetime = 0;
952 return CMD_SUCCESS;
955 DEFUN (ipv6_nd_managed_config_flag,
956 ipv6_nd_managed_config_flag_cmd,
957 "ipv6 nd managed-config-flag",
958 "Interface IPv6 config commands\n"
959 "Neighbor discovery\n"
960 "Managed address configuration flag\n")
962 struct interface *ifp;
963 struct zebra_if *zif;
965 ifp = (struct interface *) vty->index;
966 zif = ifp->info;
968 zif->rtadv.AdvManagedFlag = 1;
970 return CMD_SUCCESS;
973 DEFUN (no_ipv6_nd_managed_config_flag,
974 no_ipv6_nd_managed_config_flag_cmd,
975 "no ipv6 nd managed-config-flag",
976 NO_STR
977 "Interface IPv6 config commands\n"
978 "Neighbor discovery\n"
979 "Managed address configuration flag\n")
981 struct interface *ifp;
982 struct zebra_if *zif;
984 ifp = (struct interface *) vty->index;
985 zif = ifp->info;
987 zif->rtadv.AdvManagedFlag = 0;
989 return CMD_SUCCESS;
992 DEFUN (ipv6_nd_homeagent_config_flag,
993 ipv6_nd_homeagent_config_flag_cmd,
994 "ipv6 nd home-agent-config-flag",
995 "Interface IPv6 config commands\n"
996 "Neighbor discovery\n"
997 "Home Agent configuration flag\n")
999 struct interface *ifp;
1000 struct zebra_if *zif;
1002 ifp = (struct interface *) vty->index;
1003 zif = ifp->info;
1005 zif->rtadv.AdvHomeAgentFlag = 1;
1007 return CMD_SUCCESS;
1010 DEFUN (no_ipv6_nd_homeagent_config_flag,
1011 no_ipv6_nd_homeagent_config_flag_cmd,
1012 "no ipv6 nd home-agent-config-flag",
1013 NO_STR
1014 "Interface IPv6 config commands\n"
1015 "Neighbor discovery\n"
1016 "Home Agent configuration flag\n")
1018 struct interface *ifp;
1019 struct zebra_if *zif;
1021 ifp = (struct interface *) vty->index;
1022 zif = ifp->info;
1024 zif->rtadv.AdvHomeAgentFlag = 0;
1026 return CMD_SUCCESS;
1029 DEFUN (ipv6_nd_adv_interval_config_option,
1030 ipv6_nd_adv_interval_config_option_cmd,
1031 "ipv6 nd adv-interval-option",
1032 "Interface IPv6 config commands\n"
1033 "Neighbor discovery\n"
1034 "Advertisement Interval Option\n")
1036 struct interface *ifp;
1037 struct zebra_if *zif;
1039 ifp = (struct interface *) vty->index;
1040 zif = ifp->info;
1042 zif->rtadv.AdvIntervalOption = 1;
1044 return CMD_SUCCESS;
1047 DEFUN (no_ipv6_nd_adv_interval_config_option,
1048 no_ipv6_nd_adv_interval_config_option_cmd,
1049 "no ipv6 nd adv-interval-option",
1050 NO_STR
1051 "Interface IPv6 config commands\n"
1052 "Neighbor discovery\n"
1053 "Advertisement Interval Option\n")
1055 struct interface *ifp;
1056 struct zebra_if *zif;
1058 ifp = (struct interface *) vty->index;
1059 zif = ifp->info;
1061 zif->rtadv.AdvIntervalOption = 0;
1063 return CMD_SUCCESS;
1066 DEFUN (ipv6_nd_other_config_flag,
1067 ipv6_nd_other_config_flag_cmd,
1068 "ipv6 nd other-config-flag",
1069 "Interface IPv6 config commands\n"
1070 "Neighbor discovery\n"
1071 "Other statefull configuration flag\n")
1073 struct interface *ifp;
1074 struct zebra_if *zif;
1076 ifp = (struct interface *) vty->index;
1077 zif = ifp->info;
1079 zif->rtadv.AdvOtherConfigFlag = 1;
1081 return CMD_SUCCESS;
1084 DEFUN (no_ipv6_nd_other_config_flag,
1085 no_ipv6_nd_other_config_flag_cmd,
1086 "no ipv6 nd other-config-flag",
1087 NO_STR
1088 "Interface IPv6 config commands\n"
1089 "Neighbor discovery\n"
1090 "Other statefull configuration flag\n")
1092 struct interface *ifp;
1093 struct zebra_if *zif;
1095 ifp = (struct interface *) vty->index;
1096 zif = ifp->info;
1098 zif->rtadv.AdvOtherConfigFlag = 0;
1100 return CMD_SUCCESS;
1103 DEFUN (ipv6_nd_prefix,
1104 ipv6_nd_prefix_cmd,
1105 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1106 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
1107 "Interface IPv6 config commands\n"
1108 "Neighbor discovery\n"
1109 "Prefix information\n"
1110 "IPv6 prefix\n"
1111 "Valid lifetime in seconds\n"
1112 "Infinite valid lifetime\n"
1113 "Preferred lifetime in seconds\n"
1114 "Infinite preferred lifetime\n"
1115 "Do not use prefix for onlink determination\n"
1116 "Do not use prefix for autoconfiguration\n"
1117 "Set Router Address flag\n")
1119 int i;
1120 int ret;
1121 int cursor = 1;
1122 struct interface *ifp;
1123 struct zebra_if *zebra_if;
1124 struct rtadv_prefix rp;
1126 ifp = (struct interface *) vty->index;
1127 zebra_if = ifp->info;
1129 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1130 if (!ret)
1132 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1133 return CMD_WARNING;
1135 rp.AdvOnLinkFlag = 1;
1136 rp.AdvAutonomousFlag = 1;
1137 rp.AdvRouterAddressFlag = 0;
1138 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1139 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1141 if (argc > 1)
1143 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
1145 if ( strncmp (argv[1], "i", 1) == 0)
1146 rp.AdvValidLifetime = UINT32_MAX;
1147 else
1148 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1149 (char **)NULL, 10);
1151 if ( strncmp (argv[2], "i", 1) == 0)
1152 rp.AdvPreferredLifetime = UINT32_MAX;
1153 else
1154 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1155 (char **)NULL, 10);
1157 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1159 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1160 return CMD_WARNING;
1162 cursor = cursor + 2;
1164 if (argc > cursor)
1166 for (i = cursor; i < argc; i++)
1168 if (strncmp (argv[i], "of", 2) == 0)
1169 rp.AdvOnLinkFlag = 0;
1170 if (strncmp (argv[i], "no", 2) == 0)
1171 rp.AdvAutonomousFlag = 0;
1172 if (strncmp (argv[i], "ro", 2) == 0)
1173 rp.AdvRouterAddressFlag = 1;
1178 rtadv_prefix_set (zebra_if, &rp);
1180 return CMD_SUCCESS;
1183 ALIAS (ipv6_nd_prefix,
1184 ipv6_nd_prefix_val_nortaddr_cmd,
1185 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1186 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1187 "Interface IPv6 config commands\n"
1188 "Neighbor discovery\n"
1189 "Prefix information\n"
1190 "IPv6 prefix\n"
1191 "Valid lifetime in seconds\n"
1192 "Infinite valid lifetime\n"
1193 "Preferred lifetime in seconds\n"
1194 "Infinite preferred lifetime\n"
1195 "Do not use prefix for onlink determination\n"
1196 "Do not use prefix for autoconfiguration\n")
1198 ALIAS (ipv6_nd_prefix,
1199 ipv6_nd_prefix_val_rev_cmd,
1200 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1201 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1202 "Interface IPv6 config commands\n"
1203 "Neighbor discovery\n"
1204 "Prefix information\n"
1205 "IPv6 prefix\n"
1206 "Valid lifetime in seconds\n"
1207 "Infinite valid lifetime\n"
1208 "Preferred lifetime in seconds\n"
1209 "Infinite preferred lifetime\n"
1210 "Do not use prefix for autoconfiguration\n"
1211 "Do not use prefix for onlink determination\n")
1213 ALIAS (ipv6_nd_prefix,
1214 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1215 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1216 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1217 "Interface IPv6 config commands\n"
1218 "Neighbor discovery\n"
1219 "Prefix information\n"
1220 "IPv6 prefix\n"
1221 "Valid lifetime in seconds\n"
1222 "Infinite valid lifetime\n"
1223 "Preferred lifetime in seconds\n"
1224 "Infinite preferred lifetime\n"
1225 "Do not use prefix for autoconfiguration\n"
1226 "Do not use prefix for onlink determination\n"
1227 "Set Router Address flag\n")
1229 ALIAS (ipv6_nd_prefix,
1230 ipv6_nd_prefix_val_noauto_cmd,
1231 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1232 "(<0-4294967295>|infinite) (no-autoconfig|)",
1233 "Interface IPv6 config commands\n"
1234 "Neighbor discovery\n"
1235 "Prefix information\n"
1236 "IPv6 prefix\n"
1237 "Valid lifetime in seconds\n"
1238 "Infinite valid lifetime\n"
1239 "Preferred lifetime in seconds\n"
1240 "Infinite preferred lifetime\n"
1241 "Do not use prefix for autoconfiguration")
1243 ALIAS (ipv6_nd_prefix,
1244 ipv6_nd_prefix_val_offlink_cmd,
1245 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1246 "(<0-4294967295>|infinite) (off-link|)",
1247 "Interface IPv6 config commands\n"
1248 "Neighbor discovery\n"
1249 "Prefix information\n"
1250 "IPv6 prefix\n"
1251 "Valid lifetime in seconds\n"
1252 "Infinite valid lifetime\n"
1253 "Preferred lifetime in seconds\n"
1254 "Infinite preferred lifetime\n"
1255 "Do not use prefix for onlink determination\n")
1257 ALIAS (ipv6_nd_prefix,
1258 ipv6_nd_prefix_val_rtaddr_cmd,
1259 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1260 "(<0-4294967295>|infinite) (router-address|)",
1261 "Interface IPv6 config commands\n"
1262 "Neighbor discovery\n"
1263 "Prefix information\n"
1264 "IPv6 prefix\n"
1265 "Valid lifetime in seconds\n"
1266 "Infinite valid lifetime\n"
1267 "Preferred lifetime in seconds\n"
1268 "Infinite preferred lifetime\n"
1269 "Set Router Address flag\n")
1271 ALIAS (ipv6_nd_prefix,
1272 ipv6_nd_prefix_val_cmd,
1273 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1274 "(<0-4294967295>|infinite)",
1275 "Interface IPv6 config commands\n"
1276 "Neighbor discovery\n"
1277 "Prefix information\n"
1278 "IPv6 prefix\n"
1279 "Valid lifetime in seconds\n"
1280 "Infinite valid lifetime\n"
1281 "Preferred lifetime in seconds\n"
1282 "Infinite preferred lifetime\n")
1284 ALIAS (ipv6_nd_prefix,
1285 ipv6_nd_prefix_noval_cmd,
1286 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1287 "Interface IPv6 config commands\n"
1288 "Neighbor discovery\n"
1289 "Prefix information\n"
1290 "IPv6 prefix\n"
1291 "Do not use prefix for autoconfiguration\n"
1292 "Do not use prefix for onlink determination\n")
1294 ALIAS (ipv6_nd_prefix,
1295 ipv6_nd_prefix_noval_rev_cmd,
1296 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1297 "Interface IPv6 config commands\n"
1298 "Neighbor discovery\n"
1299 "Prefix information\n"
1300 "IPv6 prefix\n"
1301 "Do not use prefix for onlink determination\n"
1302 "Do not use prefix for autoconfiguration\n")
1304 ALIAS (ipv6_nd_prefix,
1305 ipv6_nd_prefix_noval_noauto_cmd,
1306 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1307 "Interface IPv6 config commands\n"
1308 "Neighbor discovery\n"
1309 "Prefix information\n"
1310 "IPv6 prefix\n"
1311 "Do not use prefix for autoconfiguration\n")
1313 ALIAS (ipv6_nd_prefix,
1314 ipv6_nd_prefix_noval_offlink_cmd,
1315 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1316 "Interface IPv6 config commands\n"
1317 "Neighbor discovery\n"
1318 "Prefix information\n"
1319 "IPv6 prefix\n"
1320 "Do not use prefix for onlink determination\n")
1322 ALIAS (ipv6_nd_prefix,
1323 ipv6_nd_prefix_noval_rtaddr_cmd,
1324 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1325 "Interface IPv6 config commands\n"
1326 "Neighbor discovery\n"
1327 "Prefix information\n"
1328 "IPv6 prefix\n"
1329 "Set Router Address flag\n")
1331 ALIAS (ipv6_nd_prefix,
1332 ipv6_nd_prefix_prefix_cmd,
1333 "ipv6 nd prefix X:X::X:X/M",
1334 "Interface IPv6 config commands\n"
1335 "Neighbor discovery\n"
1336 "Prefix information\n"
1337 "IPv6 prefix\n")
1339 DEFUN (no_ipv6_nd_prefix,
1340 no_ipv6_nd_prefix_cmd,
1341 "no ipv6 nd prefix IPV6PREFIX",
1342 NO_STR
1343 "Interface IPv6 config commands\n"
1344 "Neighbor discovery\n"
1345 "Prefix information\n"
1346 "IPv6 prefix\n")
1348 int ret;
1349 struct interface *ifp;
1350 struct zebra_if *zebra_if;
1351 struct rtadv_prefix rp;
1353 ifp = (struct interface *) vty->index;
1354 zebra_if = ifp->info;
1356 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1357 if (!ret)
1359 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1360 return CMD_WARNING;
1363 ret = rtadv_prefix_reset (zebra_if, &rp);
1364 if (!ret)
1366 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1367 return CMD_WARNING;
1370 return CMD_SUCCESS;
1373 DEFUN (ipv6_nd_router_preference,
1374 ipv6_nd_router_preference_cmd,
1375 "ipv6 nd router-preference (high|medium|low)",
1376 "Interface IPv6 config commands\n"
1377 "Neighbor discovery\n"
1378 "Default router preference\n"
1379 "High default router preference\n"
1380 "Low default router preference\n"
1381 "Medium default router preference (default)\n")
1383 struct interface *ifp;
1384 struct zebra_if *zif;
1385 int i = 0;
1387 ifp = (struct interface *) vty->index;
1388 zif = ifp->info;
1390 while (0 != rtadv_pref_strs[i])
1392 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1394 zif->rtadv.DefaultPreference = i;
1395 return CMD_SUCCESS;
1397 i++;
1400 return CMD_ERR_NO_MATCH;
1403 DEFUN (no_ipv6_nd_router_preference,
1404 no_ipv6_nd_router_preference_cmd,
1405 "no ipv6 nd router-preference",
1406 NO_STR
1407 "Interface IPv6 config commands\n"
1408 "Neighbor discovery\n"
1409 "Default router preference\n")
1411 struct interface *ifp;
1412 struct zebra_if *zif;
1414 ifp = (struct interface *) vty->index;
1415 zif = ifp->info;
1417 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1419 return CMD_SUCCESS;
1422 /* Write configuration about router advertisement. */
1423 void
1424 rtadv_config_write (struct vty *vty, struct interface *ifp)
1426 struct zebra_if *zif;
1427 struct listnode *node;
1428 struct rtadv_prefix *rprefix;
1429 u_char buf[INET6_ADDRSTRLEN];
1430 int interval;
1432 if (! rtadv)
1433 return;
1435 zif = ifp->info;
1437 if (! if_is_loopback (ifp))
1439 if (zif->rtadv.AdvSendAdvertisements)
1440 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1441 else
1442 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1446 interval = zif->rtadv.MaxRtrAdvInterval;
1447 if (interval % 1000)
1448 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1449 VTY_NEWLINE);
1450 else
1451 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1452 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
1453 VTY_NEWLINE);
1455 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1456 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1457 VTY_NEWLINE);
1459 if (zif->rtadv.AdvReachableTime)
1460 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1461 VTY_NEWLINE);
1463 if (zif->rtadv.AdvManagedFlag)
1464 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1466 if (zif->rtadv.AdvOtherConfigFlag)
1467 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1469 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1470 vty_out (vty, " ipv6 nd router-preference %s%s",
1471 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1472 VTY_NEWLINE);
1474 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
1476 vty_out (vty, " ipv6 nd prefix %s/%d",
1477 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
1478 (char *) buf, INET6_ADDRSTRLEN),
1479 rprefix->prefix.prefixlen);
1480 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1481 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1483 if (rprefix->AdvValidLifetime == UINT32_MAX)
1484 vty_out (vty, " infinite");
1485 else
1486 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1487 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1488 vty_out (vty, " infinite");
1489 else
1490 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1492 if (!rprefix->AdvOnLinkFlag)
1493 vty_out (vty, " off-link");
1494 if (!rprefix->AdvAutonomousFlag)
1495 vty_out (vty, " no-autoconfig");
1496 if (rprefix->AdvRouterAddressFlag)
1497 vty_out (vty, " router-address");
1498 vty_out (vty, "%s", VTY_NEWLINE);
1503 static void
1504 rtadv_event (enum rtadv_event event, int val)
1506 switch (event)
1508 case RTADV_START:
1509 if (! rtadv->ra_read)
1510 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1511 if (! rtadv->ra_timer)
1512 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1513 NULL, 0);
1514 break;
1515 case RTADV_STOP:
1516 if (rtadv->ra_timer)
1518 thread_cancel (rtadv->ra_timer);
1519 rtadv->ra_timer = NULL;
1521 if (rtadv->ra_read)
1523 thread_cancel (rtadv->ra_read);
1524 rtadv->ra_read = NULL;
1526 break;
1527 case RTADV_TIMER:
1528 if (! rtadv->ra_timer)
1529 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1530 val);
1531 break;
1532 case RTADV_TIMER_MSEC:
1533 if (! rtadv->ra_timer)
1534 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1535 NULL, val);
1536 break;
1537 case RTADV_READ:
1538 if (! rtadv->ra_read)
1539 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1540 break;
1541 default:
1542 break;
1544 return;
1547 void
1548 rtadv_init (void)
1550 int sock;
1552 sock = rtadv_make_socket ();
1553 if (sock < 0)
1554 return;
1556 rtadv = rtadv_new ();
1557 rtadv->sock = sock;
1559 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1560 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
1561 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
1562 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
1563 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1564 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1565 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1566 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1567 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1568 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1569 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1570 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1571 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
1572 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1573 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1574 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1575 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1576 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1577 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1578 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1579 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
1580 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
1581 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1582 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
1583 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1584 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1585 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
1586 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
1587 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1588 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1589 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1590 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1591 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
1592 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
1593 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1594 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
1595 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1596 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
1599 static int
1600 if_join_all_router (int sock, struct interface *ifp)
1602 int ret;
1604 struct ipv6_mreq mreq;
1606 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1607 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1608 mreq.ipv6mr_interface = ifp->ifindex;
1610 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1611 (char *) &mreq, sizeof mreq);
1612 if (ret < 0)
1613 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
1615 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1617 return 0;
1620 static int
1621 if_leave_all_router (int sock, struct interface *ifp)
1623 int ret;
1625 struct ipv6_mreq mreq;
1627 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1628 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1629 mreq.ipv6mr_interface = ifp->ifindex;
1631 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1632 (char *) &mreq, sizeof mreq);
1633 if (ret < 0)
1634 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
1636 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1638 return 0;
1641 #else
1642 void
1643 rtadv_init (void)
1645 /* Empty.*/;
1647 #endif /* RTADV && HAVE_IPV6 */