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