]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rtadv.c
[cleanup] Convert XMALLOC/memset to XCALLOC
[mirror_frr.git] / zebra / rtadv.c
1 /* Router advertisement
2 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
3 * Copyright (C) 1999 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
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.
11 *
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.
16 *
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.
21 */
22
23 #include <zebra.h>
24
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"
34
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"
40
41 extern struct zebra_privs_t zserv_privs;
42
43 #if defined (HAVE_IPV6) && defined (RTADV)
44
45 #ifdef OPEN_BSD
46 #include <netinet/icmp6.h>
47 #endif
48
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
56
57 #define ALLNODE "ff02::1"
58 #define ALLROUTER "ff02::2"
59
60 extern struct zebra_t zebrad;
61
62 enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
63 RTADV_TIMER_MSEC, RTADV_READ};
64
65 static void rtadv_event (enum rtadv_event, int);
66
67 static int if_join_all_router (int, struct interface *);
68 static int if_leave_all_router (int, struct interface *);
69 \f
70 /* Structure which hold status of router advertisement. */
71 struct rtadv
72 {
73 int sock;
74
75 int adv_if_count;
76 int adv_msec_if_count;
77
78 struct thread *ra_read;
79 struct thread *ra_timer;
80 };
81
82 struct rtadv *rtadv = NULL;
83 \f
84 static struct rtadv *
85 rtadv_new (void)
86 {
87 return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));
88 }
89
90 static void
91 rtadv_free (struct rtadv *rtadv)
92 {
93 XFREE (MTYPE_TMP, rtadv);
94 }
95
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)
100 {
101 int ret;
102 struct msghdr msg;
103 struct iovec iov;
104 struct cmsghdr *cmsgptr;
105 struct in6_addr dst;
106
107 char adata[1024];
108
109 /* Fill in message and iovec. */
110 msg.msg_name = (void *) from;
111 msg.msg_namelen = sizeof (struct sockaddr_in6);
112 msg.msg_iov = &iov;
113 msg.msg_iovlen = 1;
114 msg.msg_control = (void *) adata;
115 msg.msg_controllen = sizeof adata;
116 iov.iov_base = buf;
117 iov.iov_len = buflen;
118
119 /* If recvmsg fail return minus value. */
120 ret = recvmsg (sock, &msg, 0);
121 if (ret < 0)
122 return ret;
123
124 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
125 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
126 {
127 /* I want interface index which this packet comes from. */
128 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
129 cmsgptr->cmsg_type == IPV6_PKTINFO)
130 {
131 struct in6_pktinfo *ptr;
132
133 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
134 *ifindex = ptr->ipi6_ifindex;
135 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
136 }
137
138 /* Incoming packet's hop limit. */
139 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
140 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
141 *hoplimit = *((int *) CMSG_DATA (cmsgptr));
142 }
143 return ret;
144 }
145
146 #define RTADV_MSG_SIZE 4096
147
148 /* Send router advertisement packet. */
149 static void
150 rtadv_send_packet (int sock, struct interface *ifp)
151 {
152 struct msghdr msg;
153 struct iovec iov;
154 struct cmsghdr *cmsgptr;
155 struct in6_pktinfo *pkt;
156 struct sockaddr_in6 addr;
157 #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;
169
170 /*
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.
175 */
176 if (adata == NULL)
177 {
178 /* XXX Free on shutdown. */
179 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
180
181 if (adata == NULL)
182 zlog_err("rtadv_send_packet: can't malloc control data\n");
183 }
184
185 /* Logging of packet. */
186 if (IS_ZEBRA_DEBUG_PACKET)
187 zlog_debug ("Router advertisement send to %s", ifp->name);
188
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));
197
198 /* Fetch interface information. */
199 zif = ifp->info;
200
201 /* Make router advertisement message. */
202 rtadv = (struct nd_router_advert *) buf;
203
204 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
205 rtadv->nd_ra_code = 0;
206 rtadv->nd_ra_cksum = 0;
207
208 rtadv->nd_ra_curhoplimit = 64;
209 rtadv->nd_ra_flags_reserved = 0;
210 if (zif->rtadv.AdvManagedFlag)
211 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
212 if (zif->rtadv.AdvOtherConfigFlag)
213 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
214 if (zif->rtadv.AdvHomeAgentFlag)
215 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
216 rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
217 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
218 rtadv->nd_ra_retransmit = htonl (0);
219
220 len = sizeof (struct nd_router_advert);
221
222 if (zif->rtadv.AdvHomeAgentFlag)
223 {
224 struct nd_opt_homeagent_info *ndopt_hai =
225 (struct nd_opt_homeagent_info *)(buf + len);
226 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
227 ndopt_hai->nd_opt_hai_len = 1;
228 ndopt_hai->nd_opt_hai_reserved = 0;
229 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
230 ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);
231 len += sizeof(struct nd_opt_homeagent_info);
232 }
233
234 if (zif->rtadv.AdvIntervalOption)
235 {
236 struct nd_opt_adv_interval *ndopt_adv =
237 (struct nd_opt_adv_interval *)(buf + len);
238 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
239 ndopt_adv->nd_opt_ai_len = 1;
240 ndopt_adv->nd_opt_ai_reserved = 0;
241 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
242 len += sizeof(struct nd_opt_adv_interval);
243 }
244
245 /* Fill in prefix. */
246 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
247 {
248 struct nd_opt_prefix_info *pinfo;
249
250 pinfo = (struct nd_opt_prefix_info *) (buf + len);
251
252 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
253 pinfo->nd_opt_pi_len = 4;
254 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
255
256 pinfo->nd_opt_pi_flags_reserved = 0;
257 if (rprefix->AdvOnLinkFlag)
258 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
259 if (rprefix->AdvAutonomousFlag)
260 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
261 if (rprefix->AdvRouterAddressFlag)
262 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
263
264 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
265 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
266 pinfo->nd_opt_pi_reserved2 = 0;
267
268 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
269 sizeof (struct in6_addr));
270
271 #ifdef DEBUG
272 {
273 u_char buf[INET6_ADDRSTRLEN];
274
275 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
276 buf, INET6_ADDRSTRLEN));
277
278 }
279 #endif /* DEBUG */
280
281 len += sizeof (struct nd_opt_prefix_info);
282 }
283
284 /* Hardware address. */
285 #ifdef HAVE_STRUCT_SOCKADDR_DL
286 sdl = &ifp->sdl;
287 if (sdl != NULL && sdl->sdl_alen != 0)
288 {
289 buf[len++] = ND_OPT_SOURCE_LINKADDR;
290 buf[len++] = (sdl->sdl_alen + 2) >> 3;
291
292 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
293 len += sdl->sdl_alen;
294 }
295 #else
296 if (ifp->hw_addr_len != 0)
297 {
298 buf[len++] = ND_OPT_SOURCE_LINKADDR;
299 buf[len++] = (ifp->hw_addr_len + 2) >> 3;
300
301 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
302 len += ifp->hw_addr_len;
303 }
304 #endif /* HAVE_STRUCT_SOCKADDR_DL */
305
306 msg.msg_name = (void *) &addr;
307 msg.msg_namelen = sizeof (struct sockaddr_in6);
308 msg.msg_iov = &iov;
309 msg.msg_iovlen = 1;
310 msg.msg_control = (void *) adata;
311 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
312 msg.msg_flags = 0;
313 iov.iov_base = buf;
314 iov.iov_len = len;
315
316 cmsgptr = ZCMSG_FIRSTHDR(&msg);
317 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
318 cmsgptr->cmsg_level = IPPROTO_IPV6;
319 cmsgptr->cmsg_type = IPV6_PKTINFO;
320
321 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
322 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
323 pkt->ipi6_ifindex = ifp->ifindex;
324
325 ret = sendmsg (sock, &msg, 0);
326 if (ret < 0)
327 {
328 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
329 errno, safe_strerror(errno));
330 }
331 }
332
333 static int
334 rtadv_timer (struct thread *thread)
335 {
336 struct listnode *node, *nnode;
337 struct interface *ifp;
338 struct zebra_if *zif;
339 int period;
340
341 rtadv->ra_timer = NULL;
342 if (rtadv->adv_msec_if_count == 0)
343 {
344 period = 1000; /* 1 s */
345 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
346 }
347 else
348 {
349 period = 10; /* 10 ms */
350 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
351 }
352
353 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
354 {
355 if (if_is_loopback (ifp))
356 continue;
357
358 zif = ifp->info;
359
360 if (zif->rtadv.AdvSendAdvertisements)
361 {
362 zif->rtadv.AdvIntervalTimer -= period;
363 if (zif->rtadv.AdvIntervalTimer <= 0)
364 {
365 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
366 rtadv_send_packet (rtadv->sock, ifp);
367 }
368 }
369 }
370 return 0;
371 }
372
373 static void
374 rtadv_process_solicit (struct interface *ifp)
375 {
376 zlog_info ("Router solicitation received on %s", ifp->name);
377
378 rtadv_send_packet (rtadv->sock, ifp);
379 }
380
381 static void
382 rtadv_process_advert (void)
383 {
384 zlog_info ("Router advertisement received");
385 }
386
387 static void
388 rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
389 {
390 struct icmp6_hdr *icmph;
391 struct interface *ifp;
392 struct zebra_if *zif;
393
394 /* Interface search. */
395 ifp = if_lookup_by_index (ifindex);
396 if (ifp == NULL)
397 {
398 zlog_warn ("Unknown interface index: %d", ifindex);
399 return;
400 }
401
402 if (if_is_loopback (ifp))
403 return;
404
405 /* Check interface configuration. */
406 zif = ifp->info;
407 if (! zif->rtadv.AdvSendAdvertisements)
408 return;
409
410 /* ICMP message length check. */
411 if (len < sizeof (struct icmp6_hdr))
412 {
413 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
414 return;
415 }
416
417 icmph = (struct icmp6_hdr *) buf;
418
419 /* ICMP message type check. */
420 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
421 icmph->icmp6_type != ND_ROUTER_ADVERT)
422 {
423 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
424 return;
425 }
426
427 /* Hoplimit check. */
428 if (hoplimit >= 0 && hoplimit != 255)
429 {
430 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
431 hoplimit);
432 return;
433 }
434
435 /* Check ICMP message type. */
436 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
437 rtadv_process_solicit (ifp);
438 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
439 rtadv_process_advert ();
440
441 return;
442 }
443
444 static int
445 rtadv_read (struct thread *thread)
446 {
447 int sock;
448 int len;
449 u_char buf[RTADV_MSG_SIZE];
450 struct sockaddr_in6 from;
451 unsigned int ifindex;
452 int hoplimit = -1;
453
454 sock = THREAD_FD (thread);
455 rtadv->ra_read = NULL;
456
457 /* Register myself. */
458 rtadv_event (RTADV_READ, sock);
459
460 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
461
462 if (len < 0)
463 {
464 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
465 return len;
466 }
467
468 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
469
470 return 0;
471 }
472
473 static int
474 rtadv_make_socket (void)
475 {
476 int sock;
477 int ret;
478 struct icmp6_filter filter;
479
480 if ( zserv_privs.change (ZPRIVS_RAISE) )
481 zlog_err ("rtadv_make_socket: could not raise privs, %s",
482 safe_strerror (errno) );
483
484 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
485
486 if ( zserv_privs.change (ZPRIVS_LOWER) )
487 zlog_err ("rtadv_make_socket: could not lower privs, %s",
488 safe_strerror (errno) );
489
490 /* When we can't make ICMPV6 socket simply back. Router
491 advertisement feature will not be supported. */
492 if (sock < 0)
493 return -1;
494
495 ret = setsockopt_ipv6_pktinfo (sock, 1);
496 if (ret < 0)
497 return ret;
498 ret = setsockopt_ipv6_multicast_loop (sock, 0);
499 if (ret < 0)
500 return ret;
501 ret = setsockopt_ipv6_unicast_hops (sock, 255);
502 if (ret < 0)
503 return ret;
504 ret = setsockopt_ipv6_multicast_hops (sock, 255);
505 if (ret < 0)
506 return ret;
507 ret = setsockopt_ipv6_hoplimit (sock, 1);
508 if (ret < 0)
509 return ret;
510
511 ICMP6_FILTER_SETBLOCKALL(&filter);
512 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
513 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
514
515 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
516 sizeof (struct icmp6_filter));
517 if (ret < 0)
518 {
519 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
520 return ret;
521 }
522
523 return sock;
524 }
525 \f
526 static struct rtadv_prefix *
527 rtadv_prefix_new ()
528 {
529 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
530 }
531
532 static void
533 rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
534 {
535 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
536 }
537
538 static struct rtadv_prefix *
539 rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
540 {
541 struct listnode *node;
542 struct rtadv_prefix *rprefix;
543
544 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
545 if (prefix_same (&rprefix->prefix, p))
546 return rprefix;
547 return NULL;
548 }
549
550 static struct rtadv_prefix *
551 rtadv_prefix_get (struct list *rplist, struct prefix *p)
552 {
553 struct rtadv_prefix *rprefix;
554
555 rprefix = rtadv_prefix_lookup (rplist, p);
556 if (rprefix)
557 return rprefix;
558
559 rprefix = rtadv_prefix_new ();
560 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
561 listnode_add (rplist, rprefix);
562
563 return rprefix;
564 }
565
566 static void
567 rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
568 {
569 struct rtadv_prefix *rprefix;
570
571 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
572
573 /* Set parameters. */
574 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
575 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
576 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
577 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
578 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
579 }
580
581 static int
582 rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
583 {
584 struct rtadv_prefix *rprefix;
585
586 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
587 if (rprefix != NULL)
588 {
589 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
590 rtadv_prefix_free (rprefix);
591 return 1;
592 }
593 else
594 return 0;
595 }
596
597 DEFUN (ipv6_nd_suppress_ra,
598 ipv6_nd_suppress_ra_cmd,
599 "ipv6 nd suppress-ra",
600 "Interface IPv6 config commands\n"
601 "Neighbor discovery\n"
602 "Suppress Router Advertisement\n")
603 {
604 struct interface *ifp;
605 struct zebra_if *zif;
606
607 ifp = vty->index;
608 zif = ifp->info;
609
610 if (if_is_loopback (ifp))
611 {
612 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
613 return CMD_WARNING;
614 }
615
616 if (zif->rtadv.AdvSendAdvertisements)
617 {
618 zif->rtadv.AdvSendAdvertisements = 0;
619 zif->rtadv.AdvIntervalTimer = 0;
620 rtadv->adv_if_count--;
621
622 if_leave_all_router (rtadv->sock, ifp);
623
624 if (rtadv->adv_if_count == 0)
625 rtadv_event (RTADV_STOP, 0);
626 }
627
628 return CMD_SUCCESS;
629 }
630
631 DEFUN (no_ipv6_nd_suppress_ra,
632 no_ipv6_nd_suppress_ra_cmd,
633 "no ipv6 nd suppress-ra",
634 NO_STR
635 "Interface IPv6 config commands\n"
636 "Neighbor discovery\n"
637 "Suppress Router Advertisement\n")
638 {
639 struct interface *ifp;
640 struct zebra_if *zif;
641
642 ifp = vty->index;
643 zif = ifp->info;
644
645 if (if_is_loopback (ifp))
646 {
647 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
648 return CMD_WARNING;
649 }
650
651 if (! zif->rtadv.AdvSendAdvertisements)
652 {
653 zif->rtadv.AdvSendAdvertisements = 1;
654 zif->rtadv.AdvIntervalTimer = 0;
655 rtadv->adv_if_count++;
656
657 if_join_all_router (rtadv->sock, ifp);
658
659 if (rtadv->adv_if_count == 1)
660 rtadv_event (RTADV_START, rtadv->sock);
661 }
662
663 return CMD_SUCCESS;
664 }
665
666 DEFUN (ipv6_nd_ra_interval_msec,
667 ipv6_nd_ra_interval_msec_cmd,
668 "ipv6 nd ra-interval msec MILLISECONDS",
669 "Interface IPv6 config commands\n"
670 "Neighbor discovery\n"
671 "Router Advertisement interval\n"
672 "Router Advertisement interval in milliseconds\n")
673 {
674 int interval;
675 struct interface *ifp;
676 struct zebra_if *zif;
677
678 ifp = (struct interface *) vty->index;
679 zif = ifp->info;
680
681 interval = atoi (argv[0]);
682
683 if (interval <= 0)
684 {
685 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
686 return CMD_WARNING;
687 }
688
689 if (zif->rtadv.MaxRtrAdvInterval % 1000)
690 rtadv->adv_msec_if_count--;
691
692 if (interval % 1000)
693 rtadv->adv_msec_if_count++;
694
695 zif->rtadv.MaxRtrAdvInterval = interval;
696 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
697 zif->rtadv.AdvIntervalTimer = 0;
698
699 return CMD_SUCCESS;
700 }
701
702 DEFUN (ipv6_nd_ra_interval,
703 ipv6_nd_ra_interval_cmd,
704 "ipv6 nd ra-interval SECONDS",
705 "Interface IPv6 config commands\n"
706 "Neighbor discovery\n"
707 "Router Advertisement interval\n"
708 "Router Advertisement interval in seconds\n")
709 {
710 int interval;
711 struct interface *ifp;
712 struct zebra_if *zif;
713
714 ifp = (struct interface *) vty->index;
715 zif = ifp->info;
716
717 interval = atoi (argv[0]);
718
719 if (interval <= 0)
720 {
721 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
722 return CMD_WARNING;
723 }
724
725 if (zif->rtadv.MaxRtrAdvInterval % 1000)
726 rtadv->adv_msec_if_count--;
727
728 /* convert to milliseconds */
729 interval = interval * 1000;
730
731 zif->rtadv.MaxRtrAdvInterval = interval;
732 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
733 zif->rtadv.AdvIntervalTimer = 0;
734
735 return CMD_SUCCESS;
736 }
737
738 DEFUN (no_ipv6_nd_ra_interval,
739 no_ipv6_nd_ra_interval_cmd,
740 "no ipv6 nd ra-interval",
741 NO_STR
742 "Interface IPv6 config commands\n"
743 "Neighbor discovery\n"
744 "Router Advertisement interval\n")
745 {
746 struct interface *ifp;
747 struct zebra_if *zif;
748
749 ifp = (struct interface *) vty->index;
750 zif = ifp->info;
751
752 if (zif->rtadv.MaxRtrAdvInterval % 1000)
753 rtadv->adv_msec_if_count--;
754
755 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
756 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
757 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
758
759 return CMD_SUCCESS;
760 }
761
762 DEFUN (ipv6_nd_ra_lifetime,
763 ipv6_nd_ra_lifetime_cmd,
764 "ipv6 nd ra-lifetime SECONDS",
765 "Interface IPv6 config commands\n"
766 "Neighbor discovery\n"
767 "Router lifetime\n"
768 "Router lifetime in seconds\n")
769 {
770 int lifetime;
771 struct interface *ifp;
772 struct zebra_if *zif;
773
774 ifp = (struct interface *) vty->index;
775 zif = ifp->info;
776
777 lifetime = atoi (argv[0]);
778
779 if (lifetime < 0 || lifetime > 0xffff)
780 {
781 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
782 return CMD_WARNING;
783 }
784
785 zif->rtadv.AdvDefaultLifetime = lifetime;
786
787 return CMD_SUCCESS;
788 }
789
790 DEFUN (no_ipv6_nd_ra_lifetime,
791 no_ipv6_nd_ra_lifetime_cmd,
792 "no ipv6 nd ra-lifetime",
793 NO_STR
794 "Interface IPv6 config commands\n"
795 "Neighbor discovery\n"
796 "Router lifetime\n")
797 {
798 struct interface *ifp;
799 struct zebra_if *zif;
800
801 ifp = (struct interface *) vty->index;
802 zif = ifp->info;
803
804 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
805
806 return CMD_SUCCESS;
807 }
808
809 DEFUN (ipv6_nd_reachable_time,
810 ipv6_nd_reachable_time_cmd,
811 "ipv6 nd reachable-time MILLISECONDS",
812 "Interface IPv6 config commands\n"
813 "Neighbor discovery\n"
814 "Reachable time\n"
815 "Reachable time in milliseconds\n")
816 {
817 u_int32_t rtime;
818 struct interface *ifp;
819 struct zebra_if *zif;
820
821 ifp = (struct interface *) vty->index;
822 zif = ifp->info;
823
824 rtime = (u_int32_t) atol (argv[0]);
825
826 if (rtime > RTADV_MAX_REACHABLE_TIME)
827 {
828 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
829 return CMD_WARNING;
830 }
831
832 zif->rtadv.AdvReachableTime = rtime;
833
834 return CMD_SUCCESS;
835 }
836
837 DEFUN (no_ipv6_nd_reachable_time,
838 no_ipv6_nd_reachable_time_cmd,
839 "no ipv6 nd reachable-time",
840 NO_STR
841 "Interface IPv6 config commands\n"
842 "Neighbor discovery\n"
843 "Reachable time\n")
844 {
845 struct interface *ifp;
846 struct zebra_if *zif;
847
848 ifp = (struct interface *) vty->index;
849 zif = ifp->info;
850
851 zif->rtadv.AdvReachableTime = 0;
852
853 return CMD_SUCCESS;
854 }
855
856 DEFUN (ipv6_nd_homeagent_preference,
857 ipv6_nd_homeagent_preference_cmd,
858 "ipv6 nd home-agent-preference PREFERENCE",
859 "Interface IPv6 config commands\n"
860 "Neighbor discovery\n"
861 "Home Agent preference\n"
862 "Home Agent preference value 0..65535\n")
863 {
864 u_int32_t hapref;
865 struct interface *ifp;
866 struct zebra_if *zif;
867
868 ifp = (struct interface *) vty->index;
869 zif = ifp->info;
870
871 hapref = (u_int32_t) atol (argv[0]);
872
873 if (hapref > 65535)
874 {
875 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
876 return CMD_WARNING;
877 }
878
879 zif->rtadv.HomeAgentPreference = hapref;
880
881 return CMD_SUCCESS;
882 }
883
884 DEFUN (no_ipv6_nd_homeagent_preference,
885 no_ipv6_nd_homeagent_preference_cmd,
886 "no ipv6 nd home-agent-preference",
887 NO_STR
888 "Interface IPv6 config commands\n"
889 "Neighbor discovery\n"
890 "Home Agent preference\n")
891 {
892 struct interface *ifp;
893 struct zebra_if *zif;
894
895 ifp = (struct interface *) vty->index;
896 zif = ifp->info;
897
898 zif->rtadv.HomeAgentPreference = 0;
899
900 return CMD_SUCCESS;
901 }
902
903 DEFUN (ipv6_nd_homeagent_lifetime,
904 ipv6_nd_homeagent_lifetime_cmd,
905 "ipv6 nd home-agent-lifetime SECONDS",
906 "Interface IPv6 config commands\n"
907 "Neighbor discovery\n"
908 "Home Agent lifetime\n"
909 "Home Agent lifetime in seconds\n")
910 {
911 u_int32_t ha_ltime;
912 struct interface *ifp;
913 struct zebra_if *zif;
914
915 ifp = (struct interface *) vty->index;
916 zif = ifp->info;
917
918 ha_ltime = (u_int32_t) atol (argv[0]);
919
920 if (ha_ltime > RTADV_MAX_HALIFETIME)
921 {
922 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
923 return CMD_WARNING;
924 }
925
926 zif->rtadv.HomeAgentLifetime = ha_ltime;
927
928 return CMD_SUCCESS;
929 }
930
931 DEFUN (no_ipv6_nd_homeagent_lifetime,
932 no_ipv6_nd_homeagent_lifetime_cmd,
933 "no ipv6 nd home-agent-lifetime",
934 NO_STR
935 "Interface IPv6 config commands\n"
936 "Neighbor discovery\n"
937 "Home Agent lifetime\n")
938 {
939 struct interface *ifp;
940 struct zebra_if *zif;
941
942 ifp = (struct interface *) vty->index;
943 zif = ifp->info;
944
945 zif->rtadv.HomeAgentLifetime = 0;
946
947 return CMD_SUCCESS;
948 }
949
950 DEFUN (ipv6_nd_managed_config_flag,
951 ipv6_nd_managed_config_flag_cmd,
952 "ipv6 nd managed-config-flag",
953 "Interface IPv6 config commands\n"
954 "Neighbor discovery\n"
955 "Managed address configuration flag\n")
956 {
957 struct interface *ifp;
958 struct zebra_if *zif;
959
960 ifp = (struct interface *) vty->index;
961 zif = ifp->info;
962
963 zif->rtadv.AdvManagedFlag = 1;
964
965 return CMD_SUCCESS;
966 }
967
968 DEFUN (no_ipv6_nd_managed_config_flag,
969 no_ipv6_nd_managed_config_flag_cmd,
970 "no ipv6 nd managed-config-flag",
971 NO_STR
972 "Interface IPv6 config commands\n"
973 "Neighbor discovery\n"
974 "Managed address configuration flag\n")
975 {
976 struct interface *ifp;
977 struct zebra_if *zif;
978
979 ifp = (struct interface *) vty->index;
980 zif = ifp->info;
981
982 zif->rtadv.AdvManagedFlag = 0;
983
984 return CMD_SUCCESS;
985 }
986
987 DEFUN (ipv6_nd_homeagent_config_flag,
988 ipv6_nd_homeagent_config_flag_cmd,
989 "ipv6 nd home-agent-config-flag",
990 "Interface IPv6 config commands\n"
991 "Neighbor discovery\n"
992 "Home Agent configuration flag\n")
993 {
994 struct interface *ifp;
995 struct zebra_if *zif;
996
997 ifp = (struct interface *) vty->index;
998 zif = ifp->info;
999
1000 zif->rtadv.AdvHomeAgentFlag = 1;
1001
1002 return CMD_SUCCESS;
1003 }
1004
1005 DEFUN (no_ipv6_nd_homeagent_config_flag,
1006 no_ipv6_nd_homeagent_config_flag_cmd,
1007 "no ipv6 nd home-agent-config-flag",
1008 NO_STR
1009 "Interface IPv6 config commands\n"
1010 "Neighbor discovery\n"
1011 "Home Agent configuration flag\n")
1012 {
1013 struct interface *ifp;
1014 struct zebra_if *zif;
1015
1016 ifp = (struct interface *) vty->index;
1017 zif = ifp->info;
1018
1019 zif->rtadv.AdvHomeAgentFlag = 0;
1020
1021 return CMD_SUCCESS;
1022 }
1023
1024 DEFUN (ipv6_nd_adv_interval_config_option,
1025 ipv6_nd_adv_interval_config_option_cmd,
1026 "ipv6 nd adv-interval-option",
1027 "Interface IPv6 config commands\n"
1028 "Neighbor discovery\n"
1029 "Advertisement Interval Option\n")
1030 {
1031 struct interface *ifp;
1032 struct zebra_if *zif;
1033
1034 ifp = (struct interface *) vty->index;
1035 zif = ifp->info;
1036
1037 zif->rtadv.AdvIntervalOption = 1;
1038
1039 return CMD_SUCCESS;
1040 }
1041
1042 DEFUN (no_ipv6_nd_adv_interval_config_option,
1043 no_ipv6_nd_adv_interval_config_option_cmd,
1044 "no ipv6 nd adv-interval-option",
1045 NO_STR
1046 "Interface IPv6 config commands\n"
1047 "Neighbor discovery\n"
1048 "Advertisement Interval Option\n")
1049 {
1050 struct interface *ifp;
1051 struct zebra_if *zif;
1052
1053 ifp = (struct interface *) vty->index;
1054 zif = ifp->info;
1055
1056 zif->rtadv.AdvIntervalOption = 0;
1057
1058 return CMD_SUCCESS;
1059 }
1060
1061 DEFUN (ipv6_nd_other_config_flag,
1062 ipv6_nd_other_config_flag_cmd,
1063 "ipv6 nd other-config-flag",
1064 "Interface IPv6 config commands\n"
1065 "Neighbor discovery\n"
1066 "Other statefull configuration flag\n")
1067 {
1068 struct interface *ifp;
1069 struct zebra_if *zif;
1070
1071 ifp = (struct interface *) vty->index;
1072 zif = ifp->info;
1073
1074 zif->rtadv.AdvOtherConfigFlag = 1;
1075
1076 return CMD_SUCCESS;
1077 }
1078
1079 DEFUN (no_ipv6_nd_other_config_flag,
1080 no_ipv6_nd_other_config_flag_cmd,
1081 "no ipv6 nd other-config-flag",
1082 NO_STR
1083 "Interface IPv6 config commands\n"
1084 "Neighbor discovery\n"
1085 "Other statefull configuration flag\n")
1086 {
1087 struct interface *ifp;
1088 struct zebra_if *zif;
1089
1090 ifp = (struct interface *) vty->index;
1091 zif = ifp->info;
1092
1093 zif->rtadv.AdvOtherConfigFlag = 0;
1094
1095 return CMD_SUCCESS;
1096 }
1097
1098 DEFUN (ipv6_nd_prefix,
1099 ipv6_nd_prefix_cmd,
1100 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1101 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
1102 "Interface IPv6 config commands\n"
1103 "Neighbor discovery\n"
1104 "Prefix information\n"
1105 "IPv6 prefix\n"
1106 "Valid lifetime in seconds\n"
1107 "Infinite valid lifetime\n"
1108 "Preferred lifetime in seconds\n"
1109 "Infinite preferred lifetime\n"
1110 "Do not use prefix for onlink determination\n"
1111 "Do not use prefix for autoconfiguration\n"
1112 "Set Router Address flag\n")
1113 {
1114 int i;
1115 int ret;
1116 int cursor = 1;
1117 struct interface *ifp;
1118 struct zebra_if *zebra_if;
1119 struct rtadv_prefix rp;
1120
1121 ifp = (struct interface *) vty->index;
1122 zebra_if = ifp->info;
1123
1124 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1125 if (!ret)
1126 {
1127 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1128 return CMD_WARNING;
1129 }
1130 rp.AdvOnLinkFlag = 1;
1131 rp.AdvAutonomousFlag = 1;
1132 rp.AdvRouterAddressFlag = 0;
1133 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1134 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1135
1136 if (argc > 1)
1137 {
1138 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
1139 {
1140 if ( strncmp (argv[1], "i", 1) == 0)
1141 rp.AdvValidLifetime = UINT32_MAX;
1142 else
1143 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1144 (char **)NULL, 10);
1145
1146 if ( strncmp (argv[2], "i", 1) == 0)
1147 rp.AdvPreferredLifetime = UINT32_MAX;
1148 else
1149 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1150 (char **)NULL, 10);
1151
1152 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1153 {
1154 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1155 return CMD_WARNING;
1156 }
1157 cursor = cursor + 2;
1158 }
1159 if (argc > cursor)
1160 {
1161 for (i = cursor; i < argc; i++)
1162 {
1163 if (strncmp (argv[i], "of", 2) == 0)
1164 rp.AdvOnLinkFlag = 0;
1165 if (strncmp (argv[i], "no", 2) == 0)
1166 rp.AdvAutonomousFlag = 0;
1167 if (strncmp (argv[i], "ro", 2) == 0)
1168 rp.AdvRouterAddressFlag = 1;
1169 }
1170 }
1171 }
1172
1173 rtadv_prefix_set (zebra_if, &rp);
1174
1175 return CMD_SUCCESS;
1176 }
1177
1178 ALIAS (ipv6_nd_prefix,
1179 ipv6_nd_prefix_val_nortaddr_cmd,
1180 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1181 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1182 "Interface IPv6 config commands\n"
1183 "Neighbor discovery\n"
1184 "Prefix information\n"
1185 "IPv6 prefix\n"
1186 "Valid lifetime in seconds\n"
1187 "Infinite valid lifetime\n"
1188 "Preferred lifetime in seconds\n"
1189 "Infinite preferred lifetime\n"
1190 "Do not use prefix for onlink determination\n"
1191 "Do not use prefix for autoconfiguration\n")
1192
1193 ALIAS (ipv6_nd_prefix,
1194 ipv6_nd_prefix_val_rev_cmd,
1195 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1196 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1197 "Interface IPv6 config commands\n"
1198 "Neighbor discovery\n"
1199 "Prefix information\n"
1200 "IPv6 prefix\n"
1201 "Valid lifetime in seconds\n"
1202 "Infinite valid lifetime\n"
1203 "Preferred lifetime in seconds\n"
1204 "Infinite preferred lifetime\n"
1205 "Do not use prefix for autoconfiguration\n"
1206 "Do not use prefix for onlink determination\n")
1207
1208 ALIAS (ipv6_nd_prefix,
1209 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1210 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1211 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1212 "Interface IPv6 config commands\n"
1213 "Neighbor discovery\n"
1214 "Prefix information\n"
1215 "IPv6 prefix\n"
1216 "Valid lifetime in seconds\n"
1217 "Infinite valid lifetime\n"
1218 "Preferred lifetime in seconds\n"
1219 "Infinite preferred lifetime\n"
1220 "Do not use prefix for autoconfiguration\n"
1221 "Do not use prefix for onlink determination\n"
1222 "Set Router Address flag\n")
1223
1224 ALIAS (ipv6_nd_prefix,
1225 ipv6_nd_prefix_val_noauto_cmd,
1226 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1227 "(<0-4294967295>|infinite) (no-autoconfig|)",
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")
1237
1238 ALIAS (ipv6_nd_prefix,
1239 ipv6_nd_prefix_val_offlink_cmd,
1240 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1241 "(<0-4294967295>|infinite) (off-link|)",
1242 "Interface IPv6 config commands\n"
1243 "Neighbor discovery\n"
1244 "Prefix information\n"
1245 "IPv6 prefix\n"
1246 "Valid lifetime in seconds\n"
1247 "Infinite valid lifetime\n"
1248 "Preferred lifetime in seconds\n"
1249 "Infinite preferred lifetime\n"
1250 "Do not use prefix for onlink determination\n")
1251
1252 ALIAS (ipv6_nd_prefix,
1253 ipv6_nd_prefix_val_rtaddr_cmd,
1254 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1255 "(<0-4294967295>|infinite) (router-address|)",
1256 "Interface IPv6 config commands\n"
1257 "Neighbor discovery\n"
1258 "Prefix information\n"
1259 "IPv6 prefix\n"
1260 "Valid lifetime in seconds\n"
1261 "Infinite valid lifetime\n"
1262 "Preferred lifetime in seconds\n"
1263 "Infinite preferred lifetime\n"
1264 "Set Router Address flag\n")
1265
1266 ALIAS (ipv6_nd_prefix,
1267 ipv6_nd_prefix_val_cmd,
1268 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1269 "(<0-4294967295>|infinite)",
1270 "Interface IPv6 config commands\n"
1271 "Neighbor discovery\n"
1272 "Prefix information\n"
1273 "IPv6 prefix\n"
1274 "Valid lifetime in seconds\n"
1275 "Infinite valid lifetime\n"
1276 "Preferred lifetime in seconds\n"
1277 "Infinite preferred lifetime\n")
1278
1279 ALIAS (ipv6_nd_prefix,
1280 ipv6_nd_prefix_noval_cmd,
1281 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1282 "Interface IPv6 config commands\n"
1283 "Neighbor discovery\n"
1284 "Prefix information\n"
1285 "IPv6 prefix\n"
1286 "Do not use prefix for autoconfiguration\n"
1287 "Do not use prefix for onlink determination\n")
1288
1289 ALIAS (ipv6_nd_prefix,
1290 ipv6_nd_prefix_noval_rev_cmd,
1291 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1292 "Interface IPv6 config commands\n"
1293 "Neighbor discovery\n"
1294 "Prefix information\n"
1295 "IPv6 prefix\n"
1296 "Do not use prefix for onlink determination\n"
1297 "Do not use prefix for autoconfiguration\n")
1298
1299 ALIAS (ipv6_nd_prefix,
1300 ipv6_nd_prefix_noval_noauto_cmd,
1301 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1302 "Interface IPv6 config commands\n"
1303 "Neighbor discovery\n"
1304 "Prefix information\n"
1305 "IPv6 prefix\n"
1306 "Do not use prefix for autoconfiguration\n")
1307
1308 ALIAS (ipv6_nd_prefix,
1309 ipv6_nd_prefix_noval_offlink_cmd,
1310 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1311 "Interface IPv6 config commands\n"
1312 "Neighbor discovery\n"
1313 "Prefix information\n"
1314 "IPv6 prefix\n"
1315 "Do not use prefix for onlink determination\n")
1316
1317 ALIAS (ipv6_nd_prefix,
1318 ipv6_nd_prefix_noval_rtaddr_cmd,
1319 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1320 "Interface IPv6 config commands\n"
1321 "Neighbor discovery\n"
1322 "Prefix information\n"
1323 "IPv6 prefix\n"
1324 "Set Router Address flag\n")
1325
1326 ALIAS (ipv6_nd_prefix,
1327 ipv6_nd_prefix_prefix_cmd,
1328 "ipv6 nd prefix X:X::X:X/M",
1329 "Interface IPv6 config commands\n"
1330 "Neighbor discovery\n"
1331 "Prefix information\n"
1332 "IPv6 prefix\n")
1333
1334 DEFUN (no_ipv6_nd_prefix,
1335 no_ipv6_nd_prefix_cmd,
1336 "no ipv6 nd prefix IPV6PREFIX",
1337 NO_STR
1338 "Interface IPv6 config commands\n"
1339 "Neighbor discovery\n"
1340 "Prefix information\n"
1341 "IPv6 prefix\n")
1342 {
1343 int ret;
1344 struct interface *ifp;
1345 struct zebra_if *zebra_if;
1346 struct rtadv_prefix rp;
1347
1348 ifp = (struct interface *) vty->index;
1349 zebra_if = ifp->info;
1350
1351 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1352 if (!ret)
1353 {
1354 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1355 return CMD_WARNING;
1356 }
1357
1358 ret = rtadv_prefix_reset (zebra_if, &rp);
1359 if (!ret)
1360 {
1361 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1362 return CMD_WARNING;
1363 }
1364
1365 return CMD_SUCCESS;
1366 }
1367 /* Write configuration about router advertisement. */
1368 void
1369 rtadv_config_write (struct vty *vty, struct interface *ifp)
1370 {
1371 struct zebra_if *zif;
1372 struct listnode *node;
1373 struct rtadv_prefix *rprefix;
1374 u_char buf[INET6_ADDRSTRLEN];
1375 int interval;
1376
1377 if (! rtadv)
1378 return;
1379
1380 zif = ifp->info;
1381
1382 if (! if_is_loopback (ifp))
1383 {
1384 if (zif->rtadv.AdvSendAdvertisements)
1385 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1386 else
1387 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1388 }
1389
1390
1391 interval = zif->rtadv.MaxRtrAdvInterval;
1392 if (interval % 1000)
1393 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1394 VTY_NEWLINE);
1395 else
1396 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1397 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
1398 VTY_NEWLINE);
1399
1400 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1401 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1402 VTY_NEWLINE);
1403
1404 if (zif->rtadv.AdvReachableTime)
1405 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1406 VTY_NEWLINE);
1407
1408 if (zif->rtadv.AdvManagedFlag)
1409 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1410
1411 if (zif->rtadv.AdvOtherConfigFlag)
1412 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1413
1414 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
1415 {
1416 vty_out (vty, " ipv6 nd prefix %s/%d",
1417 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
1418 (char *) buf, INET6_ADDRSTRLEN),
1419 rprefix->prefix.prefixlen);
1420 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1421 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1422 {
1423 if (rprefix->AdvValidLifetime == UINT32_MAX)
1424 vty_out (vty, " infinite");
1425 else
1426 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1427 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1428 vty_out (vty, " infinite");
1429 else
1430 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1431 }
1432 if (!rprefix->AdvOnLinkFlag)
1433 vty_out (vty, " off-link");
1434 if (!rprefix->AdvAutonomousFlag)
1435 vty_out (vty, " no-autoconfig");
1436 if (rprefix->AdvRouterAddressFlag)
1437 vty_out (vty, " router-address");
1438 vty_out (vty, "%s", VTY_NEWLINE);
1439 }
1440 }
1441
1442
1443 static void
1444 rtadv_event (enum rtadv_event event, int val)
1445 {
1446 switch (event)
1447 {
1448 case RTADV_START:
1449 if (! rtadv->ra_read)
1450 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1451 if (! rtadv->ra_timer)
1452 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1453 NULL, 0);
1454 break;
1455 case RTADV_STOP:
1456 if (rtadv->ra_timer)
1457 {
1458 thread_cancel (rtadv->ra_timer);
1459 rtadv->ra_timer = NULL;
1460 }
1461 if (rtadv->ra_read)
1462 {
1463 thread_cancel (rtadv->ra_read);
1464 rtadv->ra_read = NULL;
1465 }
1466 break;
1467 case RTADV_TIMER:
1468 if (! rtadv->ra_timer)
1469 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1470 val);
1471 break;
1472 case RTADV_TIMER_MSEC:
1473 if (! rtadv->ra_timer)
1474 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1475 NULL, val);
1476 break;
1477 case RTADV_READ:
1478 if (! rtadv->ra_read)
1479 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
1480 break;
1481 default:
1482 break;
1483 }
1484 return;
1485 }
1486
1487 void
1488 rtadv_init (void)
1489 {
1490 int sock;
1491
1492 sock = rtadv_make_socket ();
1493 if (sock < 0)
1494 return;
1495
1496 rtadv = rtadv_new ();
1497 rtadv->sock = sock;
1498
1499 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1500 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
1501 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
1502 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
1503 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1504 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1505 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1506 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1507 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1508 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1509 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1510 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1511 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
1512 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1513 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1514 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1515 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1516 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1517 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1518 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1519 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
1520 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
1521 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1522 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
1523 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1524 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1525 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
1526 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
1527 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1528 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1529 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1530 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1531 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
1532 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
1533 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1534 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
1535 }
1536
1537 static int
1538 if_join_all_router (int sock, struct interface *ifp)
1539 {
1540 int ret;
1541
1542 struct ipv6_mreq mreq;
1543
1544 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1545 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1546 mreq.ipv6mr_interface = ifp->ifindex;
1547
1548 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1549 (char *) &mreq, sizeof mreq);
1550 if (ret < 0)
1551 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
1552
1553 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1554
1555 return 0;
1556 }
1557
1558 static int
1559 if_leave_all_router (int sock, struct interface *ifp)
1560 {
1561 int ret;
1562
1563 struct ipv6_mreq mreq;
1564
1565 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1566 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1567 mreq.ipv6mr_interface = ifp->ifindex;
1568
1569 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1570 (char *) &mreq, sizeof mreq);
1571 if (ret < 0)
1572 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
1573
1574 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1575
1576 return 0;
1577 }
1578
1579 #else
1580 void
1581 rtadv_init (void)
1582 {
1583 /* Empty.*/;
1584 }
1585 #endif /* RTADV && HAVE_IPV6 */