]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rtadv.c
quagga: option "-z" ("--socket <path>") added
[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 int
91 rtadv_recv_packet (int sock, u_char *buf, int buflen,
92 struct sockaddr_in6 *from, unsigned int *ifindex,
93 int *hoplimit)
94 {
95 int ret;
96 struct msghdr msg;
97 struct iovec iov;
98 struct cmsghdr *cmsgptr;
99 struct in6_addr dst;
100
101 char adata[1024];
102
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;
112
113 /* If recvmsg fail return minus value. */
114 ret = recvmsg (sock, &msg, 0);
115 if (ret < 0)
116 return ret;
117
118 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
119 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
120 {
121 /* I want interface index which this packet comes from. */
122 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
123 cmsgptr->cmsg_type == IPV6_PKTINFO)
124 {
125 struct in6_pktinfo *ptr;
126
127 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
128 *ifindex = ptr->ipi6_ifindex;
129 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
130 }
131
132 /* Incoming packet's hop limit. */
133 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
134 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
135 {
136 int *hoptr = (int *) CMSG_DATA (cmsgptr);
137 *hoplimit = *hoptr;
138 }
139 }
140 return ret;
141 }
142
143 #define RTADV_MSG_SIZE 4096
144
145 /* Send router advertisement packet. */
146 static void
147 rtadv_send_packet (int sock, struct interface *ifp)
148 {
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;
166
167 /*
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.
172 */
173 if (adata == NULL)
174 {
175 /* XXX Free on shutdown. */
176 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
177
178 if (adata == NULL)
179 zlog_err("rtadv_send_packet: can't malloc control data\n");
180 }
181
182 /* Logging of packet. */
183 if (IS_ZEBRA_DEBUG_PACKET)
184 zlog_debug ("Router advertisement send to %s", ifp->name);
185
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));
194
195 /* Fetch interface information. */
196 zif = ifp->info;
197
198 /* Make router advertisement message. */
199 rtadv = (struct nd_router_advert *) buf;
200
201 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
202 rtadv->nd_ra_code = 0;
203 rtadv->nd_ra_cksum = 0;
204
205 rtadv->nd_ra_curhoplimit = 64;
206
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;
211
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);
221
222 len = sizeof (struct nd_router_advert);
223
224 if (zif->rtadv.AdvHomeAgentFlag)
225 {
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);
234 }
235
236 if (zif->rtadv.AdvIntervalOption)
237 {
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);
245 }
246
247 /* Fill in prefix. */
248 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
249 {
250 struct nd_opt_prefix_info *pinfo;
251
252 pinfo = (struct nd_opt_prefix_info *) (buf + len);
253
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;
257
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;
265
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;
269
270 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
271 sizeof (struct in6_addr));
272
273 #ifdef DEBUG
274 {
275 u_char buf[INET6_ADDRSTRLEN];
276
277 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
278 buf, INET6_ADDRSTRLEN));
279
280 }
281 #endif /* DEBUG */
282
283 len += sizeof (struct nd_opt_prefix_info);
284 }
285
286 /* Hardware address. */
287 #ifdef HAVE_STRUCT_SOCKADDR_DL
288 sdl = &ifp->sdl;
289 if (sdl != NULL && sdl->sdl_alen != 0)
290 {
291 buf[len++] = ND_OPT_SOURCE_LINKADDR;
292
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;
296
297 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
298 len += sdl->sdl_alen;
299
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;
303 }
304 #else
305 if (ifp->hw_addr_len != 0)
306 {
307 buf[len++] = ND_OPT_SOURCE_LINKADDR;
308
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;
312
313 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
314 len += ifp->hw_addr_len;
315
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;
319 }
320 #endif /* HAVE_STRUCT_SOCKADDR_DL */
321
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;
331
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;
336
337 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
338 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
339 pkt->ipi6_ifindex = ifp->ifindex;
340
341 ret = sendmsg (sock, &msg, 0);
342 if (ret < 0)
343 {
344 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
345 errno, safe_strerror(errno));
346 }
347 }
348
349 static int
350 rtadv_timer (struct thread *thread)
351 {
352 struct listnode *node, *nnode;
353 struct interface *ifp;
354 struct zebra_if *zif;
355 int period;
356
357 rtadv->ra_timer = NULL;
358 if (rtadv->adv_msec_if_count == 0)
359 {
360 period = 1000; /* 1 s */
361 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
362 }
363 else
364 {
365 period = 10; /* 10 ms */
366 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
367 }
368
369 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
370 {
371 if (if_is_loopback (ifp))
372 continue;
373
374 zif = ifp->info;
375
376 if (zif->rtadv.AdvSendAdvertisements)
377 {
378 zif->rtadv.AdvIntervalTimer -= period;
379 if (zif->rtadv.AdvIntervalTimer <= 0)
380 {
381 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
382 rtadv_send_packet (rtadv->sock, ifp);
383 }
384 }
385 }
386 return 0;
387 }
388
389 static void
390 rtadv_process_solicit (struct interface *ifp)
391 {
392 zlog_info ("Router solicitation received on %s", ifp->name);
393
394 rtadv_send_packet (rtadv->sock, ifp);
395 }
396
397 static void
398 rtadv_process_advert (void)
399 {
400 zlog_info ("Router advertisement received");
401 }
402
403 static void
404 rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
405 {
406 struct icmp6_hdr *icmph;
407 struct interface *ifp;
408 struct zebra_if *zif;
409
410 /* Interface search. */
411 ifp = if_lookup_by_index (ifindex);
412 if (ifp == NULL)
413 {
414 zlog_warn ("Unknown interface index: %d", ifindex);
415 return;
416 }
417
418 if (if_is_loopback (ifp))
419 return;
420
421 /* Check interface configuration. */
422 zif = ifp->info;
423 if (! zif->rtadv.AdvSendAdvertisements)
424 return;
425
426 /* ICMP message length check. */
427 if (len < sizeof (struct icmp6_hdr))
428 {
429 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
430 return;
431 }
432
433 icmph = (struct icmp6_hdr *) buf;
434
435 /* ICMP message type check. */
436 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
437 icmph->icmp6_type != ND_ROUTER_ADVERT)
438 {
439 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
440 return;
441 }
442
443 /* Hoplimit check. */
444 if (hoplimit >= 0 && hoplimit != 255)
445 {
446 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
447 hoplimit);
448 return;
449 }
450
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 ();
456
457 return;
458 }
459
460 static int
461 rtadv_read (struct thread *thread)
462 {
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;
469
470 sock = THREAD_FD (thread);
471 rtadv->ra_read = NULL;
472
473 /* Register myself. */
474 rtadv_event (RTADV_READ, sock);
475
476 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
477
478 if (len < 0)
479 {
480 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
481 return len;
482 }
483
484 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
485
486 return 0;
487 }
488
489 static int
490 rtadv_make_socket (void)
491 {
492 int sock;
493 int ret;
494 struct icmp6_filter filter;
495
496 if ( zserv_privs.change (ZPRIVS_RAISE) )
497 zlog_err ("rtadv_make_socket: could not raise privs, %s",
498 safe_strerror (errno) );
499
500 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
501
502 if ( zserv_privs.change (ZPRIVS_LOWER) )
503 zlog_err ("rtadv_make_socket: could not lower privs, %s",
504 safe_strerror (errno) );
505
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;
510
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;
526
527 ICMP6_FILTER_SETBLOCKALL(&filter);
528 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
529 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
530
531 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
532 sizeof (struct icmp6_filter));
533 if (ret < 0)
534 {
535 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
536 return ret;
537 }
538
539 return sock;
540 }
541 \f
542 static struct rtadv_prefix *
543 rtadv_prefix_new (void)
544 {
545 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
546 }
547
548 static void
549 rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
550 {
551 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
552 }
553
554 static struct rtadv_prefix *
555 rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
556 {
557 struct listnode *node;
558 struct rtadv_prefix *rprefix;
559
560 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
561 if (prefix_same (&rprefix->prefix, p))
562 return rprefix;
563 return NULL;
564 }
565
566 static struct rtadv_prefix *
567 rtadv_prefix_get (struct list *rplist, struct prefix *p)
568 {
569 struct rtadv_prefix *rprefix;
570
571 rprefix = rtadv_prefix_lookup (rplist, p);
572 if (rprefix)
573 return rprefix;
574
575 rprefix = rtadv_prefix_new ();
576 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
577 listnode_add (rplist, rprefix);
578
579 return rprefix;
580 }
581
582 static void
583 rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
584 {
585 struct rtadv_prefix *rprefix;
586
587 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
588
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;
595 }
596
597 static int
598 rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
599 {
600 struct rtadv_prefix *rprefix;
601
602 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
603 if (rprefix != NULL)
604 {
605 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
606 rtadv_prefix_free (rprefix);
607 return 1;
608 }
609 else
610 return 0;
611 }
612
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")
619 {
620 struct interface *ifp;
621 struct zebra_if *zif;
622
623 ifp = vty->index;
624 zif = ifp->info;
625
626 if (if_is_loopback (ifp))
627 {
628 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
629 return CMD_WARNING;
630 }
631
632 if (zif->rtadv.AdvSendAdvertisements)
633 {
634 zif->rtadv.AdvSendAdvertisements = 0;
635 zif->rtadv.AdvIntervalTimer = 0;
636 rtadv->adv_if_count--;
637
638 if_leave_all_router (rtadv->sock, ifp);
639
640 if (rtadv->adv_if_count == 0)
641 rtadv_event (RTADV_STOP, 0);
642 }
643
644 return CMD_SUCCESS;
645 }
646
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")
654 {
655 struct interface *ifp;
656 struct zebra_if *zif;
657
658 ifp = vty->index;
659 zif = ifp->info;
660
661 if (if_is_loopback (ifp))
662 {
663 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
664 return CMD_WARNING;
665 }
666
667 if (! zif->rtadv.AdvSendAdvertisements)
668 {
669 zif->rtadv.AdvSendAdvertisements = 1;
670 zif->rtadv.AdvIntervalTimer = 0;
671 rtadv->adv_if_count++;
672
673 if_join_all_router (rtadv->sock, ifp);
674
675 if (rtadv->adv_if_count == 1)
676 rtadv_event (RTADV_START, rtadv->sock);
677 }
678
679 return CMD_SUCCESS;
680 }
681
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")
689 {
690 int interval;
691 struct interface *ifp;
692 struct zebra_if *zif;
693
694 ifp = (struct interface *) vty->index;
695 zif = ifp->info;
696
697 interval = atoi (argv[0]);
698
699 if (interval <= 0)
700 {
701 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
702 return CMD_WARNING;
703 }
704
705 if (zif->rtadv.MaxRtrAdvInterval % 1000)
706 rtadv->adv_msec_if_count--;
707
708 if (interval % 1000)
709 rtadv->adv_msec_if_count++;
710
711 zif->rtadv.MaxRtrAdvInterval = interval;
712 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
713 zif->rtadv.AdvIntervalTimer = 0;
714
715 return CMD_SUCCESS;
716 }
717
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")
725 {
726 int interval;
727 struct interface *ifp;
728 struct zebra_if *zif;
729
730 ifp = (struct interface *) vty->index;
731 zif = ifp->info;
732
733 interval = atoi (argv[0]);
734
735 if (interval <= 0)
736 {
737 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
738 return CMD_WARNING;
739 }
740
741 if (zif->rtadv.MaxRtrAdvInterval % 1000)
742 rtadv->adv_msec_if_count--;
743
744 /* convert to milliseconds */
745 interval = interval * 1000;
746
747 zif->rtadv.MaxRtrAdvInterval = interval;
748 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
749 zif->rtadv.AdvIntervalTimer = 0;
750
751 return CMD_SUCCESS;
752 }
753
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")
761 {
762 struct interface *ifp;
763 struct zebra_if *zif;
764
765 ifp = (struct interface *) vty->index;
766 zif = ifp->info;
767
768 if (zif->rtadv.MaxRtrAdvInterval % 1000)
769 rtadv->adv_msec_if_count--;
770
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;
774
775 return CMD_SUCCESS;
776 }
777
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")
785 {
786 int lifetime;
787 struct interface *ifp;
788 struct zebra_if *zif;
789
790 ifp = (struct interface *) vty->index;
791 zif = ifp->info;
792
793 lifetime = atoi (argv[0]);
794
795 if (lifetime < 0 || lifetime > 0xffff)
796 {
797 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
798 return CMD_WARNING;
799 }
800
801 zif->rtadv.AdvDefaultLifetime = lifetime;
802
803 return CMD_SUCCESS;
804 }
805
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")
813 {
814 struct interface *ifp;
815 struct zebra_if *zif;
816
817 ifp = (struct interface *) vty->index;
818 zif = ifp->info;
819
820 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
821
822 return CMD_SUCCESS;
823 }
824
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")
832 {
833 u_int32_t rtime;
834 struct interface *ifp;
835 struct zebra_if *zif;
836
837 ifp = (struct interface *) vty->index;
838 zif = ifp->info;
839
840 rtime = (u_int32_t) atol (argv[0]);
841
842 if (rtime > RTADV_MAX_REACHABLE_TIME)
843 {
844 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
845 return CMD_WARNING;
846 }
847
848 zif->rtadv.AdvReachableTime = rtime;
849
850 return CMD_SUCCESS;
851 }
852
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")
860 {
861 struct interface *ifp;
862 struct zebra_if *zif;
863
864 ifp = (struct interface *) vty->index;
865 zif = ifp->info;
866
867 zif->rtadv.AdvReachableTime = 0;
868
869 return CMD_SUCCESS;
870 }
871
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")
879 {
880 u_int32_t hapref;
881 struct interface *ifp;
882 struct zebra_if *zif;
883
884 ifp = (struct interface *) vty->index;
885 zif = ifp->info;
886
887 hapref = (u_int32_t) atol (argv[0]);
888
889 if (hapref > 65535)
890 {
891 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
892 return CMD_WARNING;
893 }
894
895 zif->rtadv.HomeAgentPreference = hapref;
896
897 return CMD_SUCCESS;
898 }
899
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")
907 {
908 struct interface *ifp;
909 struct zebra_if *zif;
910
911 ifp = (struct interface *) vty->index;
912 zif = ifp->info;
913
914 zif->rtadv.HomeAgentPreference = 0;
915
916 return CMD_SUCCESS;
917 }
918
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")
926 {
927 u_int32_t ha_ltime;
928 struct interface *ifp;
929 struct zebra_if *zif;
930
931 ifp = (struct interface *) vty->index;
932 zif = ifp->info;
933
934 ha_ltime = (u_int32_t) atol (argv[0]);
935
936 if (ha_ltime > RTADV_MAX_HALIFETIME)
937 {
938 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
939 return CMD_WARNING;
940 }
941
942 zif->rtadv.HomeAgentLifetime = ha_ltime;
943
944 return CMD_SUCCESS;
945 }
946
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")
954 {
955 struct interface *ifp;
956 struct zebra_if *zif;
957
958 ifp = (struct interface *) vty->index;
959 zif = ifp->info;
960
961 zif->rtadv.HomeAgentLifetime = 0;
962
963 return CMD_SUCCESS;
964 }
965
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")
972 {
973 struct interface *ifp;
974 struct zebra_if *zif;
975
976 ifp = (struct interface *) vty->index;
977 zif = ifp->info;
978
979 zif->rtadv.AdvManagedFlag = 1;
980
981 return CMD_SUCCESS;
982 }
983
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")
991 {
992 struct interface *ifp;
993 struct zebra_if *zif;
994
995 ifp = (struct interface *) vty->index;
996 zif = ifp->info;
997
998 zif->rtadv.AdvManagedFlag = 0;
999
1000 return CMD_SUCCESS;
1001 }
1002
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")
1009 {
1010 struct interface *ifp;
1011 struct zebra_if *zif;
1012
1013 ifp = (struct interface *) vty->index;
1014 zif = ifp->info;
1015
1016 zif->rtadv.AdvHomeAgentFlag = 1;
1017
1018 return CMD_SUCCESS;
1019 }
1020
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")
1028 {
1029 struct interface *ifp;
1030 struct zebra_if *zif;
1031
1032 ifp = (struct interface *) vty->index;
1033 zif = ifp->info;
1034
1035 zif->rtadv.AdvHomeAgentFlag = 0;
1036
1037 return CMD_SUCCESS;
1038 }
1039
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")
1046 {
1047 struct interface *ifp;
1048 struct zebra_if *zif;
1049
1050 ifp = (struct interface *) vty->index;
1051 zif = ifp->info;
1052
1053 zif->rtadv.AdvIntervalOption = 1;
1054
1055 return CMD_SUCCESS;
1056 }
1057
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")
1065 {
1066 struct interface *ifp;
1067 struct zebra_if *zif;
1068
1069 ifp = (struct interface *) vty->index;
1070 zif = ifp->info;
1071
1072 zif->rtadv.AdvIntervalOption = 0;
1073
1074 return CMD_SUCCESS;
1075 }
1076
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")
1083 {
1084 struct interface *ifp;
1085 struct zebra_if *zif;
1086
1087 ifp = (struct interface *) vty->index;
1088 zif = ifp->info;
1089
1090 zif->rtadv.AdvOtherConfigFlag = 1;
1091
1092 return CMD_SUCCESS;
1093 }
1094
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")
1102 {
1103 struct interface *ifp;
1104 struct zebra_if *zif;
1105
1106 ifp = (struct interface *) vty->index;
1107 zif = ifp->info;
1108
1109 zif->rtadv.AdvOtherConfigFlag = 0;
1110
1111 return CMD_SUCCESS;
1112 }
1113
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")
1129 {
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;
1136
1137 ifp = (struct interface *) vty->index;
1138 zebra_if = ifp->info;
1139
1140 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1141 if (!ret)
1142 {
1143 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1144 return CMD_WARNING;
1145 }
1146 rp.AdvOnLinkFlag = 1;
1147 rp.AdvAutonomousFlag = 1;
1148 rp.AdvRouterAddressFlag = 0;
1149 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1150 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1151
1152 if (argc > 1)
1153 {
1154 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
1155 {
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);
1161
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);
1167
1168 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1169 {
1170 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1171 return CMD_WARNING;
1172 }
1173 cursor = cursor + 2;
1174 }
1175 if (argc > cursor)
1176 {
1177 for (i = cursor; i < argc; i++)
1178 {
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;
1185 }
1186 }
1187 }
1188
1189 rtadv_prefix_set (zebra_if, &rp);
1190
1191 return CMD_SUCCESS;
1192 }
1193
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")
1208
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")
1223
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")
1239
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")
1253
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")
1267
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")
1281
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")
1294
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")
1304
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")
1314
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")
1323
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")
1332
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")
1341
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")
1349
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")
1358 {
1359 int ret;
1360 struct interface *ifp;
1361 struct zebra_if *zebra_if;
1362 struct rtadv_prefix rp;
1363
1364 ifp = (struct interface *) vty->index;
1365 zebra_if = ifp->info;
1366
1367 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1368 if (!ret)
1369 {
1370 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1371 return CMD_WARNING;
1372 }
1373
1374 ret = rtadv_prefix_reset (zebra_if, &rp);
1375 if (!ret)
1376 {
1377 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1378 return CMD_WARNING;
1379 }
1380
1381 return CMD_SUCCESS;
1382 }
1383
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")
1393 {
1394 struct interface *ifp;
1395 struct zebra_if *zif;
1396 int i = 0;
1397
1398 ifp = (struct interface *) vty->index;
1399 zif = ifp->info;
1400
1401 while (0 != rtadv_pref_strs[i])
1402 {
1403 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1404 {
1405 zif->rtadv.DefaultPreference = i;
1406 return CMD_SUCCESS;
1407 }
1408 i++;
1409 }
1410
1411 return CMD_ERR_NO_MATCH;
1412 }
1413
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")
1421 {
1422 struct interface *ifp;
1423 struct zebra_if *zif;
1424
1425 ifp = (struct interface *) vty->index;
1426 zif = ifp->info;
1427
1428 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1429
1430 return CMD_SUCCESS;
1431 }
1432
1433 /* Write configuration about router advertisement. */
1434 void
1435 rtadv_config_write (struct vty *vty, struct interface *ifp)
1436 {
1437 struct zebra_if *zif;
1438 struct listnode *node;
1439 struct rtadv_prefix *rprefix;
1440 u_char buf[INET6_ADDRSTRLEN];
1441 int interval;
1442
1443 if (! rtadv)
1444 return;
1445
1446 zif = ifp->info;
1447
1448 if (! if_is_loopback (ifp))
1449 {
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);
1454 }
1455
1456
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);
1465
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);
1469
1470 if (zif->rtadv.AdvReachableTime)
1471 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1472 VTY_NEWLINE);
1473
1474 if (zif->rtadv.AdvManagedFlag)
1475 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1476
1477 if (zif->rtadv.AdvOtherConfigFlag)
1478 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1479
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);
1484
1485 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
1486 {
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))
1493 {
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);
1502 }
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);
1510 }
1511 }
1512
1513
1514 static void
1515 rtadv_event (enum rtadv_event event, int val)
1516 {
1517 switch (event)
1518 {
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)
1528 {
1529 thread_cancel (rtadv->ra_timer);
1530 rtadv->ra_timer = NULL;
1531 }
1532 if (rtadv->ra_read)
1533 {
1534 thread_cancel (rtadv->ra_read);
1535 rtadv->ra_read = NULL;
1536 }
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;
1554 }
1555 return;
1556 }
1557
1558 void
1559 rtadv_init (void)
1560 {
1561 int sock;
1562
1563 sock = rtadv_make_socket ();
1564 if (sock < 0)
1565 return;
1566
1567 rtadv = rtadv_new ();
1568 rtadv->sock = sock;
1569
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);
1608 }
1609
1610 static int
1611 if_join_all_router (int sock, struct interface *ifp)
1612 {
1613 int ret;
1614
1615 struct ipv6_mreq mreq;
1616
1617 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1618 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1619 mreq.ipv6mr_interface = ifp->ifindex;
1620
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));
1625
1626 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1627
1628 return 0;
1629 }
1630
1631 static int
1632 if_leave_all_router (int sock, struct interface *ifp)
1633 {
1634 int ret;
1635
1636 struct ipv6_mreq mreq;
1637
1638 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1639 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1640 mreq.ipv6mr_interface = ifp->ifindex;
1641
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));
1646
1647 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1648
1649 return 0;
1650 }
1651
1652 #else
1653 void
1654 rtadv_init (void)
1655 {
1656 /* Empty.*/;
1657 }
1658 #endif /* RTADV && HAVE_IPV6 */