zebra: fix more warnings in rtadv
[jleu-quagga.git] / zebra / rtadv.c
blob8cc3c4cbebddab071c5a80aa27f78f04aad3da17
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 int
91 rtadv_recv_packet (int sock, u_char *buf, int buflen,
92 struct sockaddr_in6 *from, unsigned int *ifindex,
93 int *hoplimit)
95 int ret;
96 struct msghdr msg;
97 struct iovec iov;
98 struct cmsghdr *cmsgptr;
99 struct in6_addr dst;
101 char adata[1024];
103 /* Fill in message and iovec. */
104 msg.msg_name = (void *) from;
105 msg.msg_namelen = sizeof (struct sockaddr_in6);
106 msg.msg_iov = &iov;
107 msg.msg_iovlen = 1;
108 msg.msg_control = (void *) adata;
109 msg.msg_controllen = sizeof adata;
110 iov.iov_base = buf;
111 iov.iov_len = buflen;
113 /* If recvmsg fail return minus value. */
114 ret = recvmsg (sock, &msg, 0);
115 if (ret < 0)
116 return ret;
118 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
119 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
121 /* I want interface index which this packet comes from. */
122 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
123 cmsgptr->cmsg_type == IPV6_PKTINFO)
125 struct in6_pktinfo *ptr;
127 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
128 *ifindex = ptr->ipi6_ifindex;
129 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
132 /* Incoming packet's hop limit. */
133 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
134 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
136 int *hoptr = (int *) CMSG_DATA (cmsgptr);
137 *hoplimit = *hoptr;
140 return ret;
143 #define RTADV_MSG_SIZE 4096
145 /* Send router advertisement packet. */
146 static void
147 rtadv_send_packet (int sock, struct interface *ifp)
149 struct msghdr msg;
150 struct iovec iov;
151 struct cmsghdr *cmsgptr;
152 struct in6_pktinfo *pkt;
153 struct sockaddr_in6 addr;
154 #ifdef HAVE_STRUCT_SOCKADDR_DL
155 struct sockaddr_dl *sdl;
156 #endif /* HAVE_STRUCT_SOCKADDR_DL */
157 static void *adata = NULL;
158 unsigned char buf[RTADV_MSG_SIZE];
159 struct nd_router_advert *rtadv;
160 int ret;
161 int len = 0;
162 struct zebra_if *zif;
163 struct rtadv_prefix *rprefix;
164 u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
165 struct listnode *node;
168 * Allocate control message bufffer. This is dynamic because
169 * CMSG_SPACE is not guaranteed not to call a function. Note that
170 * the size will be different on different architectures due to
171 * differing alignment rules.
173 if (adata == NULL)
175 /* XXX Free on shutdown. */
176 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
178 if (adata == NULL)
179 zlog_err("rtadv_send_packet: can't malloc control data\n");
182 /* Logging of packet. */
183 if (IS_ZEBRA_DEBUG_PACKET)
184 zlog_debug ("Router advertisement send to %s", ifp->name);
186 /* Fill in sockaddr_in6. */
187 memset (&addr, 0, sizeof (struct sockaddr_in6));
188 addr.sin6_family = AF_INET6;
189 #ifdef SIN6_LEN
190 addr.sin6_len = sizeof (struct sockaddr_in6);
191 #endif /* SIN6_LEN */
192 addr.sin6_port = htons (IPPROTO_ICMPV6);
193 memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
195 /* Fetch interface information. */
196 zif = ifp->info;
198 /* Make router advertisement message. */
199 rtadv = (struct nd_router_advert *) buf;
201 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
202 rtadv->nd_ra_code = 0;
203 rtadv->nd_ra_cksum = 0;
205 rtadv->nd_ra_curhoplimit = 64;
207 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
208 rtadv->nd_ra_flags_reserved =
209 zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
210 rtadv->nd_ra_flags_reserved <<= 3;
212 if (zif->rtadv.AdvManagedFlag)
213 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
214 if (zif->rtadv.AdvOtherConfigFlag)
215 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
216 if (zif->rtadv.AdvHomeAgentFlag)
217 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
218 rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
219 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
220 rtadv->nd_ra_retransmit = htonl (0);
222 len = sizeof (struct nd_router_advert);
224 if (zif->rtadv.AdvHomeAgentFlag)
226 struct nd_opt_homeagent_info *ndopt_hai =
227 (struct nd_opt_homeagent_info *)(buf + len);
228 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
229 ndopt_hai->nd_opt_hai_len = 1;
230 ndopt_hai->nd_opt_hai_reserved = 0;
231 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
232 ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);
233 len += sizeof(struct nd_opt_homeagent_info);
236 if (zif->rtadv.AdvIntervalOption)
238 struct nd_opt_adv_interval *ndopt_adv =
239 (struct nd_opt_adv_interval *)(buf + len);
240 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
241 ndopt_adv->nd_opt_ai_len = 1;
242 ndopt_adv->nd_opt_ai_reserved = 0;
243 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
244 len += sizeof(struct nd_opt_adv_interval);
247 /* Fill in prefix. */
248 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
250 struct nd_opt_prefix_info *pinfo;
252 pinfo = (struct nd_opt_prefix_info *) (buf + len);
254 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
255 pinfo->nd_opt_pi_len = 4;
256 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
258 pinfo->nd_opt_pi_flags_reserved = 0;
259 if (rprefix->AdvOnLinkFlag)
260 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
261 if (rprefix->AdvAutonomousFlag)
262 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
263 if (rprefix->AdvRouterAddressFlag)
264 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
266 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
267 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
268 pinfo->nd_opt_pi_reserved2 = 0;
270 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
271 sizeof (struct in6_addr));
273 #ifdef DEBUG
275 u_char buf[INET6_ADDRSTRLEN];
277 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
278 buf, INET6_ADDRSTRLEN));
281 #endif /* DEBUG */
283 len += sizeof (struct nd_opt_prefix_info);
286 /* Hardware address. */
287 #ifdef HAVE_STRUCT_SOCKADDR_DL
288 sdl = &ifp->sdl;
289 if (sdl != NULL && sdl->sdl_alen != 0)
291 buf[len++] = ND_OPT_SOURCE_LINKADDR;
293 /* Option length should be rounded up to next octet if
294 the link address does not end on an octet boundary. */
295 buf[len++] = (sdl->sdl_alen + 9) >> 3;
297 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
298 len += sdl->sdl_alen;
300 /* Pad option to end on an octet boundary. */
301 memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
302 len += -(sdl->sdl_alen + 2) & 0x7;
304 #else
305 if (ifp->hw_addr_len != 0)
307 buf[len++] = ND_OPT_SOURCE_LINKADDR;
309 /* Option length should be rounded up to next octet if
310 the link address does not end on an octet boundary. */
311 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
313 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
314 len += ifp->hw_addr_len;
316 /* Pad option to end on an octet boundary. */
317 memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
318 len += -(ifp->hw_addr_len + 2) & 0x7;
320 #endif /* HAVE_STRUCT_SOCKADDR_DL */
322 msg.msg_name = (void *) &addr;
323 msg.msg_namelen = sizeof (struct sockaddr_in6);
324 msg.msg_iov = &iov;
325 msg.msg_iovlen = 1;
326 msg.msg_control = (void *) adata;
327 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
328 msg.msg_flags = 0;
329 iov.iov_base = buf;
330 iov.iov_len = len;
332 cmsgptr = ZCMSG_FIRSTHDR(&msg);
333 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
334 cmsgptr->cmsg_level = IPPROTO_IPV6;
335 cmsgptr->cmsg_type = IPV6_PKTINFO;
337 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
338 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
339 pkt->ipi6_ifindex = ifp->ifindex;
341 ret = sendmsg (sock, &msg, 0);
342 if (ret < 0)
344 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
345 errno, safe_strerror(errno));
349 static int
350 rtadv_timer (struct thread *thread)
352 struct listnode *node, *nnode;
353 struct interface *ifp;
354 struct zebra_if *zif;
355 int period;
357 rtadv->ra_timer = NULL;
358 if (rtadv->adv_msec_if_count == 0)
360 period = 1000; /* 1 s */
361 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
363 else
365 period = 10; /* 10 ms */
366 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
369 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
371 if (if_is_loopback (ifp))
372 continue;
374 zif = ifp->info;
376 if (zif->rtadv.AdvSendAdvertisements)
378 zif->rtadv.AdvIntervalTimer -= period;
379 if (zif->rtadv.AdvIntervalTimer <= 0)
381 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
382 rtadv_send_packet (rtadv->sock, ifp);
386 return 0;
389 static void
390 rtadv_process_solicit (struct interface *ifp)
392 zlog_info ("Router solicitation received on %s", ifp->name);
394 rtadv_send_packet (rtadv->sock, ifp);
397 static void
398 rtadv_process_advert (void)
400 zlog_info ("Router advertisement received");
403 static void
404 rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
406 struct icmp6_hdr *icmph;
407 struct interface *ifp;
408 struct zebra_if *zif;
410 /* Interface search. */
411 ifp = if_lookup_by_index (ifindex);
412 if (ifp == NULL)
414 zlog_warn ("Unknown interface index: %d", ifindex);
415 return;
418 if (if_is_loopback (ifp))
419 return;
421 /* Check interface configuration. */
422 zif = ifp->info;
423 if (! zif->rtadv.AdvSendAdvertisements)
424 return;
426 /* ICMP message length check. */
427 if (len < sizeof (struct icmp6_hdr))
429 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
430 return;
433 icmph = (struct icmp6_hdr *) buf;
435 /* ICMP message type check. */
436 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
437 icmph->icmp6_type != ND_ROUTER_ADVERT)
439 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
440 return;
443 /* Hoplimit check. */
444 if (hoplimit >= 0 && hoplimit != 255)
446 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
447 hoplimit);
448 return;
451 /* Check ICMP message type. */
452 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
453 rtadv_process_solicit (ifp);
454 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
455 rtadv_process_advert ();
457 return;
460 static int
461 rtadv_read (struct thread *thread)
463 int sock;
464 int len;
465 u_char buf[RTADV_MSG_SIZE];
466 struct sockaddr_in6 from;
467 unsigned int ifindex = 0;
468 int hoplimit = -1;
470 sock = THREAD_FD (thread);
471 rtadv->ra_read = NULL;
473 /* Register myself. */
474 rtadv_event (RTADV_READ, sock);
476 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
478 if (len < 0)
480 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
481 return len;
484 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
486 return 0;
489 static int
490 rtadv_make_socket (void)
492 int sock;
493 int ret;
494 struct icmp6_filter filter;
496 if ( zserv_privs.change (ZPRIVS_RAISE) )
497 zlog_err ("rtadv_make_socket: could not raise privs, %s",
498 safe_strerror (errno) );
500 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
502 if ( zserv_privs.change (ZPRIVS_LOWER) )
503 zlog_err ("rtadv_make_socket: could not lower privs, %s",
504 safe_strerror (errno) );
506 /* When we can't make ICMPV6 socket simply back. Router
507 advertisement feature will not be supported. */
508 if (sock < 0)
509 return -1;
511 ret = setsockopt_ipv6_pktinfo (sock, 1);
512 if (ret < 0)
513 return ret;
514 ret = setsockopt_ipv6_multicast_loop (sock, 0);
515 if (ret < 0)
516 return ret;
517 ret = setsockopt_ipv6_unicast_hops (sock, 255);
518 if (ret < 0)
519 return ret;
520 ret = setsockopt_ipv6_multicast_hops (sock, 255);
521 if (ret < 0)
522 return ret;
523 ret = setsockopt_ipv6_hoplimit (sock, 1);
524 if (ret < 0)
525 return ret;
527 ICMP6_FILTER_SETBLOCKALL(&filter);
528 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
529 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
531 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
532 sizeof (struct icmp6_filter));
533 if (ret < 0)
535 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
536 return ret;
539 return sock;
542 static struct rtadv_prefix *
543 rtadv_prefix_new (void)
545 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
548 static void
549 rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
551 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
554 static struct rtadv_prefix *
555 rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
557 struct listnode *node;
558 struct rtadv_prefix *rprefix;
560 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
561 if (prefix_same (&rprefix->prefix, p))
562 return rprefix;
563 return NULL;
566 static struct rtadv_prefix *
567 rtadv_prefix_get (struct list *rplist, struct prefix *p)
569 struct rtadv_prefix *rprefix;
571 rprefix = rtadv_prefix_lookup (rplist, p);
572 if (rprefix)
573 return rprefix;
575 rprefix = rtadv_prefix_new ();
576 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
577 listnode_add (rplist, rprefix);
579 return rprefix;
582 static void
583 rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
585 struct rtadv_prefix *rprefix;
587 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
589 /* Set parameters. */
590 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
591 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
592 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
593 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
594 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
597 static int
598 rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
600 struct rtadv_prefix *rprefix;
602 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
603 if (rprefix != NULL)
605 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
606 rtadv_prefix_free (rprefix);
607 return 1;
609 else
610 return 0;
613 DEFUN (ipv6_nd_suppress_ra,
614 ipv6_nd_suppress_ra_cmd,
615 "ipv6 nd suppress-ra",
616 "Interface IPv6 config commands\n"
617 "Neighbor discovery\n"
618 "Suppress Router Advertisement\n")
620 struct interface *ifp;
621 struct zebra_if *zif;
623 ifp = vty->index;
624 zif = ifp->info;
626 if (if_is_loopback (ifp))
628 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
629 return CMD_WARNING;
632 if (zif->rtadv.AdvSendAdvertisements)
634 zif->rtadv.AdvSendAdvertisements = 0;
635 zif->rtadv.AdvIntervalTimer = 0;
636 rtadv->adv_if_count--;
638 if_leave_all_router (rtadv->sock, ifp);
640 if (rtadv->adv_if_count == 0)
641 rtadv_event (RTADV_STOP, 0);
644 return CMD_SUCCESS;
647 DEFUN (no_ipv6_nd_suppress_ra,
648 no_ipv6_nd_suppress_ra_cmd,
649 "no ipv6 nd suppress-ra",
650 NO_STR
651 "Interface IPv6 config commands\n"
652 "Neighbor discovery\n"
653 "Suppress Router Advertisement\n")
655 struct interface *ifp;
656 struct zebra_if *zif;
658 ifp = vty->index;
659 zif = ifp->info;
661 if (if_is_loopback (ifp))
663 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
664 return CMD_WARNING;
667 if (! zif->rtadv.AdvSendAdvertisements)
669 zif->rtadv.AdvSendAdvertisements = 1;
670 zif->rtadv.AdvIntervalTimer = 0;
671 rtadv->adv_if_count++;
673 if_join_all_router (rtadv->sock, ifp);
675 if (rtadv->adv_if_count == 1)
676 rtadv_event (RTADV_START, rtadv->sock);
679 return CMD_SUCCESS;
682 DEFUN (ipv6_nd_ra_interval_msec,
683 ipv6_nd_ra_interval_msec_cmd,
684 "ipv6 nd ra-interval msec MILLISECONDS",
685 "Interface IPv6 config commands\n"
686 "Neighbor discovery\n"
687 "Router Advertisement interval\n"
688 "Router Advertisement interval in milliseconds\n")
690 int interval;
691 struct interface *ifp;
692 struct zebra_if *zif;
694 ifp = (struct interface *) vty->index;
695 zif = ifp->info;
697 interval = atoi (argv[0]);
699 if (interval <= 0)
701 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
702 return CMD_WARNING;
705 if (zif->rtadv.MaxRtrAdvInterval % 1000)
706 rtadv->adv_msec_if_count--;
708 if (interval % 1000)
709 rtadv->adv_msec_if_count++;
711 zif->rtadv.MaxRtrAdvInterval = interval;
712 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
713 zif->rtadv.AdvIntervalTimer = 0;
715 return CMD_SUCCESS;
718 DEFUN (ipv6_nd_ra_interval,
719 ipv6_nd_ra_interval_cmd,
720 "ipv6 nd ra-interval SECONDS",
721 "Interface IPv6 config commands\n"
722 "Neighbor discovery\n"
723 "Router Advertisement interval\n"
724 "Router Advertisement interval in seconds\n")
726 int interval;
727 struct interface *ifp;
728 struct zebra_if *zif;
730 ifp = (struct interface *) vty->index;
731 zif = ifp->info;
733 interval = atoi (argv[0]);
735 if (interval <= 0)
737 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
738 return CMD_WARNING;
741 if (zif->rtadv.MaxRtrAdvInterval % 1000)
742 rtadv->adv_msec_if_count--;
744 /* convert to milliseconds */
745 interval = interval * 1000;
747 zif->rtadv.MaxRtrAdvInterval = interval;
748 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
749 zif->rtadv.AdvIntervalTimer = 0;
751 return CMD_SUCCESS;
754 DEFUN (no_ipv6_nd_ra_interval,
755 no_ipv6_nd_ra_interval_cmd,
756 "no ipv6 nd ra-interval",
757 NO_STR
758 "Interface IPv6 config commands\n"
759 "Neighbor discovery\n"
760 "Router Advertisement interval\n")
762 struct interface *ifp;
763 struct zebra_if *zif;
765 ifp = (struct interface *) vty->index;
766 zif = ifp->info;
768 if (zif->rtadv.MaxRtrAdvInterval % 1000)
769 rtadv->adv_msec_if_count--;
771 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
772 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
773 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
775 return CMD_SUCCESS;
778 DEFUN (ipv6_nd_ra_lifetime,
779 ipv6_nd_ra_lifetime_cmd,
780 "ipv6 nd ra-lifetime SECONDS",
781 "Interface IPv6 config commands\n"
782 "Neighbor discovery\n"
783 "Router lifetime\n"
784 "Router lifetime in seconds\n")
786 int lifetime;
787 struct interface *ifp;
788 struct zebra_if *zif;
790 ifp = (struct interface *) vty->index;
791 zif = ifp->info;
793 lifetime = atoi (argv[0]);
795 if (lifetime < 0 || lifetime > 0xffff)
797 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
798 return CMD_WARNING;
801 zif->rtadv.AdvDefaultLifetime = lifetime;
803 return CMD_SUCCESS;
806 DEFUN (no_ipv6_nd_ra_lifetime,
807 no_ipv6_nd_ra_lifetime_cmd,
808 "no ipv6 nd ra-lifetime",
809 NO_STR
810 "Interface IPv6 config commands\n"
811 "Neighbor discovery\n"
812 "Router lifetime\n")
814 struct interface *ifp;
815 struct zebra_if *zif;
817 ifp = (struct interface *) vty->index;
818 zif = ifp->info;
820 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
822 return CMD_SUCCESS;
825 DEFUN (ipv6_nd_reachable_time,
826 ipv6_nd_reachable_time_cmd,
827 "ipv6 nd reachable-time MILLISECONDS",
828 "Interface IPv6 config commands\n"
829 "Neighbor discovery\n"
830 "Reachable time\n"
831 "Reachable time in milliseconds\n")
833 u_int32_t rtime;
834 struct interface *ifp;
835 struct zebra_if *zif;
837 ifp = (struct interface *) vty->index;
838 zif = ifp->info;
840 rtime = (u_int32_t) atol (argv[0]);
842 if (rtime > RTADV_MAX_REACHABLE_TIME)
844 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
845 return CMD_WARNING;
848 zif->rtadv.AdvReachableTime = rtime;
850 return CMD_SUCCESS;
853 DEFUN (no_ipv6_nd_reachable_time,
854 no_ipv6_nd_reachable_time_cmd,
855 "no ipv6 nd reachable-time",
856 NO_STR
857 "Interface IPv6 config commands\n"
858 "Neighbor discovery\n"
859 "Reachable time\n")
861 struct interface *ifp;
862 struct zebra_if *zif;
864 ifp = (struct interface *) vty->index;
865 zif = ifp->info;
867 zif->rtadv.AdvReachableTime = 0;
869 return CMD_SUCCESS;
872 DEFUN (ipv6_nd_homeagent_preference,
873 ipv6_nd_homeagent_preference_cmd,
874 "ipv6 nd home-agent-preference PREFERENCE",
875 "Interface IPv6 config commands\n"
876 "Neighbor discovery\n"
877 "Home Agent preference\n"
878 "Home Agent preference value 0..65535\n")
880 u_int32_t hapref;
881 struct interface *ifp;
882 struct zebra_if *zif;
884 ifp = (struct interface *) vty->index;
885 zif = ifp->info;
887 hapref = (u_int32_t) atol (argv[0]);
889 if (hapref > 65535)
891 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
892 return CMD_WARNING;
895 zif->rtadv.HomeAgentPreference = hapref;
897 return CMD_SUCCESS;
900 DEFUN (no_ipv6_nd_homeagent_preference,
901 no_ipv6_nd_homeagent_preference_cmd,
902 "no ipv6 nd home-agent-preference",
903 NO_STR
904 "Interface IPv6 config commands\n"
905 "Neighbor discovery\n"
906 "Home Agent preference\n")
908 struct interface *ifp;
909 struct zebra_if *zif;
911 ifp = (struct interface *) vty->index;
912 zif = ifp->info;
914 zif->rtadv.HomeAgentPreference = 0;
916 return CMD_SUCCESS;
919 DEFUN (ipv6_nd_homeagent_lifetime,
920 ipv6_nd_homeagent_lifetime_cmd,
921 "ipv6 nd home-agent-lifetime SECONDS",
922 "Interface IPv6 config commands\n"
923 "Neighbor discovery\n"
924 "Home Agent lifetime\n"
925 "Home Agent lifetime in seconds\n")
927 u_int32_t ha_ltime;
928 struct interface *ifp;
929 struct zebra_if *zif;
931 ifp = (struct interface *) vty->index;
932 zif = ifp->info;
934 ha_ltime = (u_int32_t) atol (argv[0]);
936 if (ha_ltime > RTADV_MAX_HALIFETIME)
938 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
939 return CMD_WARNING;
942 zif->rtadv.HomeAgentLifetime = ha_ltime;
944 return CMD_SUCCESS;
947 DEFUN (no_ipv6_nd_homeagent_lifetime,
948 no_ipv6_nd_homeagent_lifetime_cmd,
949 "no ipv6 nd home-agent-lifetime",
950 NO_STR
951 "Interface IPv6 config commands\n"
952 "Neighbor discovery\n"
953 "Home Agent lifetime\n")
955 struct interface *ifp;
956 struct zebra_if *zif;
958 ifp = (struct interface *) vty->index;
959 zif = ifp->info;
961 zif->rtadv.HomeAgentLifetime = 0;
963 return CMD_SUCCESS;
966 DEFUN (ipv6_nd_managed_config_flag,
967 ipv6_nd_managed_config_flag_cmd,
968 "ipv6 nd managed-config-flag",
969 "Interface IPv6 config commands\n"
970 "Neighbor discovery\n"
971 "Managed address configuration flag\n")
973 struct interface *ifp;
974 struct zebra_if *zif;
976 ifp = (struct interface *) vty->index;
977 zif = ifp->info;
979 zif->rtadv.AdvManagedFlag = 1;
981 return CMD_SUCCESS;
984 DEFUN (no_ipv6_nd_managed_config_flag,
985 no_ipv6_nd_managed_config_flag_cmd,
986 "no ipv6 nd managed-config-flag",
987 NO_STR
988 "Interface IPv6 config commands\n"
989 "Neighbor discovery\n"
990 "Managed address configuration flag\n")
992 struct interface *ifp;
993 struct zebra_if *zif;
995 ifp = (struct interface *) vty->index;
996 zif = ifp->info;
998 zif->rtadv.AdvManagedFlag = 0;
1000 return CMD_SUCCESS;
1003 DEFUN (ipv6_nd_homeagent_config_flag,
1004 ipv6_nd_homeagent_config_flag_cmd,
1005 "ipv6 nd home-agent-config-flag",
1006 "Interface IPv6 config commands\n"
1007 "Neighbor discovery\n"
1008 "Home Agent configuration flag\n")
1010 struct interface *ifp;
1011 struct zebra_if *zif;
1013 ifp = (struct interface *) vty->index;
1014 zif = ifp->info;
1016 zif->rtadv.AdvHomeAgentFlag = 1;
1018 return CMD_SUCCESS;
1021 DEFUN (no_ipv6_nd_homeagent_config_flag,
1022 no_ipv6_nd_homeagent_config_flag_cmd,
1023 "no ipv6 nd home-agent-config-flag",
1024 NO_STR
1025 "Interface IPv6 config commands\n"
1026 "Neighbor discovery\n"
1027 "Home Agent configuration flag\n")
1029 struct interface *ifp;
1030 struct zebra_if *zif;
1032 ifp = (struct interface *) vty->index;
1033 zif = ifp->info;
1035 zif->rtadv.AdvHomeAgentFlag = 0;
1037 return CMD_SUCCESS;
1040 DEFUN (ipv6_nd_adv_interval_config_option,
1041 ipv6_nd_adv_interval_config_option_cmd,
1042 "ipv6 nd adv-interval-option",
1043 "Interface IPv6 config commands\n"
1044 "Neighbor discovery\n"
1045 "Advertisement Interval Option\n")
1047 struct interface *ifp;
1048 struct zebra_if *zif;
1050 ifp = (struct interface *) vty->index;
1051 zif = ifp->info;
1053 zif->rtadv.AdvIntervalOption = 1;
1055 return CMD_SUCCESS;
1058 DEFUN (no_ipv6_nd_adv_interval_config_option,
1059 no_ipv6_nd_adv_interval_config_option_cmd,
1060 "no ipv6 nd adv-interval-option",
1061 NO_STR
1062 "Interface IPv6 config commands\n"
1063 "Neighbor discovery\n"
1064 "Advertisement Interval Option\n")
1066 struct interface *ifp;
1067 struct zebra_if *zif;
1069 ifp = (struct interface *) vty->index;
1070 zif = ifp->info;
1072 zif->rtadv.AdvIntervalOption = 0;
1074 return CMD_SUCCESS;
1077 DEFUN (ipv6_nd_other_config_flag,
1078 ipv6_nd_other_config_flag_cmd,
1079 "ipv6 nd other-config-flag",
1080 "Interface IPv6 config commands\n"
1081 "Neighbor discovery\n"
1082 "Other statefull configuration flag\n")
1084 struct interface *ifp;
1085 struct zebra_if *zif;
1087 ifp = (struct interface *) vty->index;
1088 zif = ifp->info;
1090 zif->rtadv.AdvOtherConfigFlag = 1;
1092 return CMD_SUCCESS;
1095 DEFUN (no_ipv6_nd_other_config_flag,
1096 no_ipv6_nd_other_config_flag_cmd,
1097 "no ipv6 nd other-config-flag",
1098 NO_STR
1099 "Interface IPv6 config commands\n"
1100 "Neighbor discovery\n"
1101 "Other statefull configuration flag\n")
1103 struct interface *ifp;
1104 struct zebra_if *zif;
1106 ifp = (struct interface *) vty->index;
1107 zif = ifp->info;
1109 zif->rtadv.AdvOtherConfigFlag = 0;
1111 return CMD_SUCCESS;
1114 DEFUN (ipv6_nd_prefix,
1115 ipv6_nd_prefix_cmd,
1116 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1117 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
1118 "Interface IPv6 config commands\n"
1119 "Neighbor discovery\n"
1120 "Prefix information\n"
1121 "IPv6 prefix\n"
1122 "Valid lifetime in seconds\n"
1123 "Infinite valid lifetime\n"
1124 "Preferred lifetime in seconds\n"
1125 "Infinite preferred lifetime\n"
1126 "Do not use prefix for onlink determination\n"
1127 "Do not use prefix for autoconfiguration\n"
1128 "Set Router Address flag\n")
1130 int i;
1131 int ret;
1132 int cursor = 1;
1133 struct interface *ifp;
1134 struct zebra_if *zebra_if;
1135 struct rtadv_prefix rp;
1137 ifp = (struct interface *) vty->index;
1138 zebra_if = ifp->info;
1140 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1141 if (!ret)
1143 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1144 return CMD_WARNING;
1146 rp.AdvOnLinkFlag = 1;
1147 rp.AdvAutonomousFlag = 1;
1148 rp.AdvRouterAddressFlag = 0;
1149 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1150 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1152 if (argc > 1)
1154 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
1156 if ( strncmp (argv[1], "i", 1) == 0)
1157 rp.AdvValidLifetime = UINT32_MAX;
1158 else
1159 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1160 (char **)NULL, 10);
1162 if ( strncmp (argv[2], "i", 1) == 0)
1163 rp.AdvPreferredLifetime = UINT32_MAX;
1164 else
1165 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1166 (char **)NULL, 10);
1168 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1170 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1171 return CMD_WARNING;
1173 cursor = cursor + 2;
1175 if (argc > cursor)
1177 for (i = cursor; i < argc; i++)
1179 if (strncmp (argv[i], "of", 2) == 0)
1180 rp.AdvOnLinkFlag = 0;
1181 if (strncmp (argv[i], "no", 2) == 0)
1182 rp.AdvAutonomousFlag = 0;
1183 if (strncmp (argv[i], "ro", 2) == 0)
1184 rp.AdvRouterAddressFlag = 1;
1189 rtadv_prefix_set (zebra_if, &rp);
1191 return CMD_SUCCESS;
1194 ALIAS (ipv6_nd_prefix,
1195 ipv6_nd_prefix_val_nortaddr_cmd,
1196 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1197 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1198 "Interface IPv6 config commands\n"
1199 "Neighbor discovery\n"
1200 "Prefix information\n"
1201 "IPv6 prefix\n"
1202 "Valid lifetime in seconds\n"
1203 "Infinite valid lifetime\n"
1204 "Preferred lifetime in seconds\n"
1205 "Infinite preferred lifetime\n"
1206 "Do not use prefix for onlink determination\n"
1207 "Do not use prefix for autoconfiguration\n")
1209 ALIAS (ipv6_nd_prefix,
1210 ipv6_nd_prefix_val_rev_cmd,
1211 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1212 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1213 "Interface IPv6 config commands\n"
1214 "Neighbor discovery\n"
1215 "Prefix information\n"
1216 "IPv6 prefix\n"
1217 "Valid lifetime in seconds\n"
1218 "Infinite valid lifetime\n"
1219 "Preferred lifetime in seconds\n"
1220 "Infinite preferred lifetime\n"
1221 "Do not use prefix for autoconfiguration\n"
1222 "Do not use prefix for onlink determination\n")
1224 ALIAS (ipv6_nd_prefix,
1225 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1226 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1227 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1228 "Interface IPv6 config commands\n"
1229 "Neighbor discovery\n"
1230 "Prefix information\n"
1231 "IPv6 prefix\n"
1232 "Valid lifetime in seconds\n"
1233 "Infinite valid lifetime\n"
1234 "Preferred lifetime in seconds\n"
1235 "Infinite preferred lifetime\n"
1236 "Do not use prefix for autoconfiguration\n"
1237 "Do not use prefix for onlink determination\n"
1238 "Set Router Address flag\n")
1240 ALIAS (ipv6_nd_prefix,
1241 ipv6_nd_prefix_val_noauto_cmd,
1242 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1243 "(<0-4294967295>|infinite) (no-autoconfig|)",
1244 "Interface IPv6 config commands\n"
1245 "Neighbor discovery\n"
1246 "Prefix information\n"
1247 "IPv6 prefix\n"
1248 "Valid lifetime in seconds\n"
1249 "Infinite valid lifetime\n"
1250 "Preferred lifetime in seconds\n"
1251 "Infinite preferred lifetime\n"
1252 "Do not use prefix for autoconfiguration")
1254 ALIAS (ipv6_nd_prefix,
1255 ipv6_nd_prefix_val_offlink_cmd,
1256 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1257 "(<0-4294967295>|infinite) (off-link|)",
1258 "Interface IPv6 config commands\n"
1259 "Neighbor discovery\n"
1260 "Prefix information\n"
1261 "IPv6 prefix\n"
1262 "Valid lifetime in seconds\n"
1263 "Infinite valid lifetime\n"
1264 "Preferred lifetime in seconds\n"
1265 "Infinite preferred lifetime\n"
1266 "Do not use prefix for onlink determination\n")
1268 ALIAS (ipv6_nd_prefix,
1269 ipv6_nd_prefix_val_rtaddr_cmd,
1270 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1271 "(<0-4294967295>|infinite) (router-address|)",
1272 "Interface IPv6 config commands\n"
1273 "Neighbor discovery\n"
1274 "Prefix information\n"
1275 "IPv6 prefix\n"
1276 "Valid lifetime in seconds\n"
1277 "Infinite valid lifetime\n"
1278 "Preferred lifetime in seconds\n"
1279 "Infinite preferred lifetime\n"
1280 "Set Router Address flag\n")
1282 ALIAS (ipv6_nd_prefix,
1283 ipv6_nd_prefix_val_cmd,
1284 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1285 "(<0-4294967295>|infinite)",
1286 "Interface IPv6 config commands\n"
1287 "Neighbor discovery\n"
1288 "Prefix information\n"
1289 "IPv6 prefix\n"
1290 "Valid lifetime in seconds\n"
1291 "Infinite valid lifetime\n"
1292 "Preferred lifetime in seconds\n"
1293 "Infinite preferred lifetime\n")
1295 ALIAS (ipv6_nd_prefix,
1296 ipv6_nd_prefix_noval_cmd,
1297 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1298 "Interface IPv6 config commands\n"
1299 "Neighbor discovery\n"
1300 "Prefix information\n"
1301 "IPv6 prefix\n"
1302 "Do not use prefix for autoconfiguration\n"
1303 "Do not use prefix for onlink determination\n")
1305 ALIAS (ipv6_nd_prefix,
1306 ipv6_nd_prefix_noval_rev_cmd,
1307 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1308 "Interface IPv6 config commands\n"
1309 "Neighbor discovery\n"
1310 "Prefix information\n"
1311 "IPv6 prefix\n"
1312 "Do not use prefix for onlink determination\n"
1313 "Do not use prefix for autoconfiguration\n")
1315 ALIAS (ipv6_nd_prefix,
1316 ipv6_nd_prefix_noval_noauto_cmd,
1317 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1318 "Interface IPv6 config commands\n"
1319 "Neighbor discovery\n"
1320 "Prefix information\n"
1321 "IPv6 prefix\n"
1322 "Do not use prefix for autoconfiguration\n")
1324 ALIAS (ipv6_nd_prefix,
1325 ipv6_nd_prefix_noval_offlink_cmd,
1326 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1327 "Interface IPv6 config commands\n"
1328 "Neighbor discovery\n"
1329 "Prefix information\n"
1330 "IPv6 prefix\n"
1331 "Do not use prefix for onlink determination\n")
1333 ALIAS (ipv6_nd_prefix,
1334 ipv6_nd_prefix_noval_rtaddr_cmd,
1335 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1336 "Interface IPv6 config commands\n"
1337 "Neighbor discovery\n"
1338 "Prefix information\n"
1339 "IPv6 prefix\n"
1340 "Set Router Address flag\n")
1342 ALIAS (ipv6_nd_prefix,
1343 ipv6_nd_prefix_prefix_cmd,
1344 "ipv6 nd prefix X:X::X:X/M",
1345 "Interface IPv6 config commands\n"
1346 "Neighbor discovery\n"
1347 "Prefix information\n"
1348 "IPv6 prefix\n")
1350 DEFUN (no_ipv6_nd_prefix,
1351 no_ipv6_nd_prefix_cmd,
1352 "no ipv6 nd prefix IPV6PREFIX",
1353 NO_STR
1354 "Interface IPv6 config commands\n"
1355 "Neighbor discovery\n"
1356 "Prefix information\n"
1357 "IPv6 prefix\n")
1359 int ret;
1360 struct interface *ifp;
1361 struct zebra_if *zebra_if;
1362 struct rtadv_prefix rp;
1364 ifp = (struct interface *) vty->index;
1365 zebra_if = ifp->info;
1367 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1368 if (!ret)
1370 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1371 return CMD_WARNING;
1374 ret = rtadv_prefix_reset (zebra_if, &rp);
1375 if (!ret)
1377 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1378 return CMD_WARNING;
1381 return CMD_SUCCESS;
1384 DEFUN (ipv6_nd_router_preference,
1385 ipv6_nd_router_preference_cmd,
1386 "ipv6 nd router-preference (high|medium|low)",
1387 "Interface IPv6 config commands\n"
1388 "Neighbor discovery\n"
1389 "Default router preference\n"
1390 "High default router preference\n"
1391 "Low default router preference\n"
1392 "Medium default router preference (default)\n")
1394 struct interface *ifp;
1395 struct zebra_if *zif;
1396 int i = 0;
1398 ifp = (struct interface *) vty->index;
1399 zif = ifp->info;
1401 while (0 != rtadv_pref_strs[i])
1403 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1405 zif->rtadv.DefaultPreference = i;
1406 return CMD_SUCCESS;
1408 i++;
1411 return CMD_ERR_NO_MATCH;
1414 DEFUN (no_ipv6_nd_router_preference,
1415 no_ipv6_nd_router_preference_cmd,
1416 "no ipv6 nd router-preference",
1417 NO_STR
1418 "Interface IPv6 config commands\n"
1419 "Neighbor discovery\n"
1420 "Default router preference\n")
1422 struct interface *ifp;
1423 struct zebra_if *zif;
1425 ifp = (struct interface *) vty->index;
1426 zif = ifp->info;
1428 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1430 return CMD_SUCCESS;
1433 /* Write configuration about router advertisement. */
1434 void
1435 rtadv_config_write (struct vty *vty, struct interface *ifp)
1437 struct zebra_if *zif;
1438 struct listnode *node;
1439 struct rtadv_prefix *rprefix;
1440 u_char buf[INET6_ADDRSTRLEN];
1441 int interval;
1443 if (! rtadv)
1444 return;
1446 zif = ifp->info;
1448 if (! if_is_loopback (ifp))
1450 if (zif->rtadv.AdvSendAdvertisements)
1451 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1452 else
1453 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1457 interval = zif->rtadv.MaxRtrAdvInterval;
1458 if (interval % 1000)
1459 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1460 VTY_NEWLINE);
1461 else
1462 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1463 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
1464 VTY_NEWLINE);
1466 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1467 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1468 VTY_NEWLINE);
1470 if (zif->rtadv.AdvReachableTime)
1471 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1472 VTY_NEWLINE);
1474 if (zif->rtadv.AdvManagedFlag)
1475 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1477 if (zif->rtadv.AdvOtherConfigFlag)
1478 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1480 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1481 vty_out (vty, " ipv6 nd router-preference %s%s",
1482 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1483 VTY_NEWLINE);
1485 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
1487 vty_out (vty, " ipv6 nd prefix %s/%d",
1488 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
1489 (char *) buf, INET6_ADDRSTRLEN),
1490 rprefix->prefix.prefixlen);
1491 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1492 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1494 if (rprefix->AdvValidLifetime == UINT32_MAX)
1495 vty_out (vty, " infinite");
1496 else
1497 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1498 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1499 vty_out (vty, " infinite");
1500 else
1501 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1503 if (!rprefix->AdvOnLinkFlag)
1504 vty_out (vty, " off-link");
1505 if (!rprefix->AdvAutonomousFlag)
1506 vty_out (vty, " no-autoconfig");
1507 if (rprefix->AdvRouterAddressFlag)
1508 vty_out (vty, " router-address");
1509 vty_out (vty, "%s", VTY_NEWLINE);
1514 static void
1515 rtadv_event (enum rtadv_event event, int val)
1517 switch (event)
1519 case RTADV_START:
1520 if (! rtadv->ra_read)
1521 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1522 if (! rtadv->ra_timer)
1523 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1524 NULL, 0);
1525 break;
1526 case RTADV_STOP:
1527 if (rtadv->ra_timer)
1529 thread_cancel (rtadv->ra_timer);
1530 rtadv->ra_timer = NULL;
1532 if (rtadv->ra_read)
1534 thread_cancel (rtadv->ra_read);
1535 rtadv->ra_read = NULL;
1537 break;
1538 case RTADV_TIMER:
1539 if (! rtadv->ra_timer)
1540 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1541 val);
1542 break;
1543 case RTADV_TIMER_MSEC:
1544 if (! rtadv->ra_timer)
1545 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1546 NULL, val);
1547 break;
1548 case RTADV_READ:
1549 if (! rtadv->ra_read)
1550 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1551 break;
1552 default:
1553 break;
1555 return;
1558 void
1559 rtadv_init (void)
1561 int sock;
1563 sock = rtadv_make_socket ();
1564 if (sock < 0)
1565 return;
1567 rtadv = rtadv_new ();
1568 rtadv->sock = sock;
1570 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1571 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
1572 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
1573 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
1574 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1575 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1576 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1577 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1578 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1579 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1580 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1581 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1582 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
1583 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1584 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1585 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1586 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1587 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1588 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1589 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1590 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
1591 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
1592 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1593 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
1594 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1595 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1596 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
1597 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
1598 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1599 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1600 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1601 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1602 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
1603 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
1604 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1605 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
1606 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1607 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
1610 static int
1611 if_join_all_router (int sock, struct interface *ifp)
1613 int ret;
1615 struct ipv6_mreq mreq;
1617 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1618 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1619 mreq.ipv6mr_interface = ifp->ifindex;
1621 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1622 (char *) &mreq, sizeof mreq);
1623 if (ret < 0)
1624 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
1626 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1628 return 0;
1631 static int
1632 if_leave_all_router (int sock, struct interface *ifp)
1634 int ret;
1636 struct ipv6_mreq mreq;
1638 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1639 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1640 mreq.ipv6mr_interface = ifp->ifindex;
1642 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1643 (char *) &mreq, sizeof mreq);
1644 if (ret < 0)
1645 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
1647 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1649 return 0;
1652 #else
1653 void
1654 rtadv_init (void)
1656 /* Empty.*/;
1658 #endif /* RTADV && HAVE_IPV6 */