]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rtadv.c
Merge commit 'remotes/jocke/delete_ghost_route'
[mirror_frr.git] / zebra / rtadv.c
CommitLineData
718e3744 1/* Router advertisement
7cee1bb1 2 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
718e3744 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"
edd7c245 33#include "privs.h"
718e3744 34
35#include "zebra/interface.h"
36#include "zebra/rtadv.h"
37#include "zebra/debug.h"
537d8ea9 38#include "zebra/rib.h"
4b5e1359 39#include "zebra/zserv.h"
718e3744 40
edd7c245 41extern struct zebra_privs_t zserv_privs;
42
718e3744 43#if defined (HAVE_IPV6) && defined (RTADV)
44
fa2b17e3 45#ifdef OPEN_BSD
46#include <netinet/icmp6.h>
47#endif
48
718e3744 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
b21b19c5 60extern struct zebra_t zebrad;
61
7cee1bb1 62enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
63 RTADV_TIMER_MSEC, RTADV_READ};
718e3744 64
a1ac18c4 65static void rtadv_event (enum rtadv_event, int);
718e3744 66
a1ac18c4 67static int if_join_all_router (int, struct interface *);
68static int if_leave_all_router (int, struct interface *);
718e3744 69\f
70/* Structure which hold status of router advertisement. */
71struct rtadv
72{
73 int sock;
74
75 int adv_if_count;
7cee1bb1 76 int adv_msec_if_count;
718e3744 77
78 struct thread *ra_read;
79 struct thread *ra_timer;
80};
81
82struct rtadv *rtadv = NULL;
83\f
a1ac18c4 84static struct rtadv *
85rtadv_new (void)
718e3744 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
a1ac18c4 93static void
718e3744 94rtadv_free (struct rtadv *rtadv)
95{
96 XFREE (MTYPE_TMP, rtadv);
97}
98
a1ac18c4 99static int
718e3744 100rtadv_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
b99760ab 127 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
718e3744 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. */
a1ac18c4 152static void
718e3744 153rtadv_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;
6f0e3f6e 160#ifdef HAVE_STRUCT_SOCKADDR_DL
718e3744 161 struct sockaddr_dl *sdl;
6f0e3f6e 162#endif /* HAVE_STRUCT_SOCKADDR_DL */
57492d56 163 static void *adata = NULL;
718e3744 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;
1eb8ef25 169 struct rtadv_prefix *rprefix;
718e3744 170 u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
52dc7ee6 171 struct listnode *node;
718e3744 172
57492d56 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
718e3744 188 /* Logging of packet. */
189 if (IS_ZEBRA_DEBUG_PACKET)
b6178002 190 zlog_debug ("Router advertisement send to %s", ifp->name);
718e3744 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;
7cee1bb1 217 if (zif->rtadv.AdvHomeAgentFlag)
218 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
718e3744 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
7cee1bb1 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
718e3744 248 /* Fill in prefix. */
1eb8ef25 249 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
718e3744 250 {
251 struct nd_opt_prefix_info *pinfo;
718e3744 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;
7cee1bb1 264 if (rprefix->AdvRouterAddressFlag)
265 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
718e3744 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
b6178002 278 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
3e31cded 279 buf, INET6_ADDRSTRLEN));
718e3744 280
281 }
282#endif /* DEBUG */
283
284 len += sizeof (struct nd_opt_prefix_info);
285 }
286
287 /* Hardware address. */
6f0e3f6e 288#ifdef HAVE_STRUCT_SOCKADDR_DL
718e3744 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 }
6f0e3f6e 307#endif /* HAVE_STRUCT_SOCKADDR_DL */
718e3744 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;
f841e02e 314 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
57492d56 315 msg.msg_flags = 0;
718e3744 316 iov.iov_base = buf;
317 iov.iov_len = len;
318
b99760ab 319 cmsgptr = ZCMSG_FIRSTHDR(&msg);
57492d56 320 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
718e3744 321 cmsgptr->cmsg_level = IPPROTO_IPV6;
322 cmsgptr->cmsg_type = IPV6_PKTINFO;
80893817 323
718e3744 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);
9ccabd1c 329 if (ret < 0)
330 {
331 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
6099b3b5 332 errno, safe_strerror(errno));
9ccabd1c 333 }
718e3744 334}
335
a1ac18c4 336static int
718e3744 337rtadv_timer (struct thread *thread)
338{
1eb8ef25 339 struct listnode *node, *nnode;
718e3744 340 struct interface *ifp;
341 struct zebra_if *zif;
7cee1bb1 342 int period;
718e3744 343
344 rtadv->ra_timer = NULL;
7cee1bb1 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 }
718e3744 355
1eb8ef25 356 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
718e3744 357 {
718e3744 358 if (if_is_loopback (ifp))
359 continue;
360
361 zif = ifp->info;
362
363 if (zif->rtadv.AdvSendAdvertisements)
7cee1bb1 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 }
718e3744 372 }
373 return 0;
374}
375
a1ac18c4 376static void
718e3744 377rtadv_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
a1ac18c4 384static void
385rtadv_process_advert (void)
718e3744 386{
387 zlog_info ("Router advertisement received");
388}
389
a1ac18c4 390static void
fce954f8 391rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
718e3744 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
a1ac18c4 447static int
718e3744 448rtadv_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 {
6099b3b5 467 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
718e3744 468 return len;
469 }
470
fce954f8 471 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
718e3744 472
473 return 0;
474}
475
a1ac18c4 476static int
718e3744 477rtadv_make_socket (void)
478{
479 int sock;
480 int ret;
481 struct icmp6_filter filter;
482
edd7c245 483 if ( zserv_privs.change (ZPRIVS_RAISE) )
484 zlog_err ("rtadv_make_socket: could not raise privs, %s",
6099b3b5 485 safe_strerror (errno) );
edd7c245 486
718e3744 487 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
488
edd7c245 489 if ( zserv_privs.change (ZPRIVS_LOWER) )
490 zlog_err ("rtadv_make_socket: could not lower privs, %s",
6099b3b5 491 safe_strerror (errno) );
edd7c245 492
718e3744 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);
718e3744 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 {
6099b3b5 522 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
718e3744 523 return ret;
524 }
525
526 return sock;
527}
528\f
a1ac18c4 529static struct rtadv_prefix *
718e3744 530rtadv_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
a1ac18c4 540static void
718e3744 541rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
542{
543 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
544}
545
a1ac18c4 546static struct rtadv_prefix *
52dc7ee6 547rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
718e3744 548{
52dc7ee6 549 struct listnode *node;
718e3744 550 struct rtadv_prefix *rprefix;
551
1eb8ef25 552 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
553 if (prefix_same (&rprefix->prefix, p))
554 return rprefix;
718e3744 555 return NULL;
556}
557
a1ac18c4 558static struct rtadv_prefix *
52dc7ee6 559rtadv_prefix_get (struct list *rplist, struct prefix *p)
718e3744 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
a1ac18c4 574static void
718e3744 575rtadv_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;
7cee1bb1 586 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
718e3744 587}
588
a1ac18c4 589static int
718e3744 590rtadv_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
605DEFUN (ipv6_nd_suppress_ra,
606 ipv6_nd_suppress_ra_cmd,
607 "ipv6 nd suppress-ra",
3e31cded 608 "Interface IPv6 config commands\n"
718e3744 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
718e3744 639DEFUN (no_ipv6_nd_suppress_ra,
640 no_ipv6_nd_suppress_ra_cmd,
641 "no ipv6 nd suppress-ra",
642 NO_STR
3e31cded 643 "Interface IPv6 config commands\n"
718e3744 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
7cee1bb1 674DEFUN (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
718e3744 710DEFUN (ipv6_nd_ra_interval,
711 ipv6_nd_ra_interval_cmd,
712 "ipv6 nd ra-interval SECONDS",
3e31cded 713 "Interface IPv6 config commands\n"
718e3744 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
7cee1bb1 727 if (interval <= 0)
718e3744 728 {
729 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
730 return CMD_WARNING;
731 }
732
7cee1bb1 733 if (zif->rtadv.MaxRtrAdvInterval % 1000)
734 rtadv->adv_msec_if_count--;
735
736 /* convert to milliseconds */
737 interval = interval * 1000;
738
718e3744 739 zif->rtadv.MaxRtrAdvInterval = interval;
740 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
741 zif->rtadv.AdvIntervalTimer = 0;
742
743 return CMD_SUCCESS;
744}
745
746DEFUN (no_ipv6_nd_ra_interval,
747 no_ipv6_nd_ra_interval_cmd,
748 "no ipv6 nd ra-interval",
749 NO_STR
3e31cded 750 "Interface IPv6 config commands\n"
718e3744 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
7cee1bb1 760 if (zif->rtadv.MaxRtrAdvInterval % 1000)
761 rtadv->adv_msec_if_count--;
762
718e3744 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
770DEFUN (ipv6_nd_ra_lifetime,
771 ipv6_nd_ra_lifetime_cmd,
772 "ipv6 nd ra-lifetime SECONDS",
3e31cded 773 "Interface IPv6 config commands\n"
718e3744 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
798DEFUN (no_ipv6_nd_ra_lifetime,
799 no_ipv6_nd_ra_lifetime_cmd,
800 "no ipv6 nd ra-lifetime",
801 NO_STR
3e31cded 802 "Interface IPv6 config commands\n"
718e3744 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
817DEFUN (ipv6_nd_reachable_time,
818 ipv6_nd_reachable_time_cmd,
819 "ipv6 nd reachable-time MILLISECONDS",
3e31cded 820 "Interface IPv6 config commands\n"
718e3744 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
845DEFUN (no_ipv6_nd_reachable_time,
846 no_ipv6_nd_reachable_time_cmd,
847 "no ipv6 nd reachable-time",
848 NO_STR
3e31cded 849 "Interface IPv6 config commands\n"
718e3744 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
7cee1bb1 864DEFUN (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
892DEFUN (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
911DEFUN (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
939DEFUN (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
718e3744 958DEFUN (ipv6_nd_managed_config_flag,
959 ipv6_nd_managed_config_flag_cmd,
960 "ipv6 nd managed-config-flag",
3e31cded 961 "Interface IPv6 config commands\n"
718e3744 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
976DEFUN (no_ipv6_nd_managed_config_flag,
977 no_ipv6_nd_managed_config_flag_cmd,
978 "no ipv6 nd managed-config-flag",
979 NO_STR
3e31cded 980 "Interface IPv6 config commands\n"
718e3744 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
7cee1bb1 995DEFUN (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
1013DEFUN (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
1032DEFUN (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
1050DEFUN (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
718e3744 1069DEFUN (ipv6_nd_other_config_flag,
1070 ipv6_nd_other_config_flag_cmd,
1071 "ipv6 nd other-config-flag",
3e31cded 1072 "Interface IPv6 config commands\n"
718e3744 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
1087DEFUN (no_ipv6_nd_other_config_flag,
1088 no_ipv6_nd_other_config_flag_cmd,
1089 "no ipv6 nd other-config-flag",
1090 NO_STR
3e31cded 1091 "Interface IPv6 config commands\n"
718e3744 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
3e31cded 1106DEFUN (ipv6_nd_prefix,
1107 ipv6_nd_prefix_cmd,
1108 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
7cee1bb1 1109 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
3e31cded 1110 "Interface IPv6 config commands\n"
718e3744 1111 "Neighbor discovery\n"
1112 "Prefix information\n"
1113 "IPv6 prefix\n"
1114 "Valid lifetime in seconds\n"
3e31cded 1115 "Infinite valid lifetime\n"
718e3744 1116 "Preferred lifetime in seconds\n"
3e31cded 1117 "Infinite preferred lifetime\n"
1118 "Do not use prefix for onlink determination\n"
7cee1bb1 1119 "Do not use prefix for autoconfiguration\n"
1120 "Set Router Address flag\n")
718e3744 1121{
1122 int i;
1123 int ret;
3e31cded 1124 int cursor = 1;
718e3744 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 }
3e31cded 1138 rp.AdvOnLinkFlag = 1;
1139 rp.AdvAutonomousFlag = 1;
7cee1bb1 1140 rp.AdvRouterAddressFlag = 0;
3e31cded 1141 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1142 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
718e3744 1143
3e31cded 1144 if (argc > 1)
718e3744 1145 {
3e31cded 1146 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
718e3744 1147 {
3e31cded 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;
718e3744 1166 }
3e31cded 1167 if (argc > cursor)
718e3744 1168 {
3e31cded 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;
7cee1bb1 1175 if (strncmp (argv[i], "ro", 2) == 0)
1176 rp.AdvRouterAddressFlag = 1;
3e31cded 1177 }
718e3744 1178 }
1179 }
1180
1181 rtadv_prefix_set (zebra_if, &rp);
1182
1183 return CMD_SUCCESS;
1184}
1185
7cee1bb1 1186ALIAS (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
3e31cded 1201ALIAS (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
7cee1bb1 1216ALIAS (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
3e31cded 1232ALIAS (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"
7cee1bb1 1244 "Do not use prefix for autoconfiguration")
3e31cded 1245
1246ALIAS (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
7cee1bb1 1260ALIAS (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
3e31cded 1274ALIAS (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
1287ALIAS (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
1297ALIAS (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
1307ALIAS (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
1316ALIAS (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
7cee1bb1 1325ALIAS (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
3e31cded 1334ALIAS (ipv6_nd_prefix,
1335 ipv6_nd_prefix_prefix_cmd,
1336 "ipv6 nd prefix X:X::X:X/M",
1337 "Interface IPv6 config commands\n"
718e3744 1338 "Neighbor discovery\n"
1339 "Prefix information\n"
1340 "IPv6 prefix\n")
1341
3e31cded 1342DEFUN (no_ipv6_nd_prefix,
1343 no_ipv6_nd_prefix_cmd,
1344 "no ipv6 nd prefix IPV6PREFIX",
718e3744 1345 NO_STR
3e31cded 1346 "Interface IPv6 config commands\n"
718e3744 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}
718e3744 1375/* Write configuration about router advertisement. */
1376void
1377rtadv_config_write (struct vty *vty, struct interface *ifp)
1378{
1379 struct zebra_if *zif;
52dc7ee6 1380 struct listnode *node;
718e3744 1381 struct rtadv_prefix *rprefix;
1382 u_char buf[INET6_ADDRSTRLEN];
7cee1bb1 1383 int interval;
718e3744 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
7cee1bb1 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,
718e3744 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
1eb8ef25 1422 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
718e3744 1423 {
3e31cded 1424 vty_out (vty, " ipv6 nd prefix %s/%d",
718e3744 1425 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
c9e52be3 1426 (char *) buf, INET6_ADDRSTRLEN),
3e31cded 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");
7cee1bb1 1444 if (rprefix->AdvRouterAddressFlag)
1445 vty_out (vty, " router-address");
718e3744 1446 vty_out (vty, "%s", VTY_NEWLINE);
1447 }
1448}
1449
718e3744 1450
a1ac18c4 1451static void
718e3744 1452rtadv_event (enum rtadv_event event, int val)
1453{
1454 switch (event)
1455 {
1456 case RTADV_START:
1457 if (! rtadv->ra_read)
b21b19c5 1458 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
718e3744 1459 if (! rtadv->ra_timer)
3e31cded 1460 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1461 NULL, 0);
718e3744 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)
3e31cded 1477 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1478 val);
718e3744 1479 break;
7cee1bb1 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;
718e3744 1485 case RTADV_READ:
1486 if (! rtadv->ra_read)
b21b19c5 1487 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
718e3744 1488 break;
1489 default:
1490 break;
1491 }
1492 return;
1493}
1494
1495void
a1ac18c4 1496rtadv_init (void)
718e3744 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);
718e3744 1509 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
7cee1bb1 1510 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
718e3744 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);
7cee1bb1 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);
3e31cded 1528 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
7cee1bb1 1529 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1530 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
3e31cded 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);
7cee1bb1 1534 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
3e31cded 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);
7cee1bb1 1540 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
3e31cded 1541 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1542 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
718e3744 1543}
1544
a1ac18c4 1545static int
718e3744 1546if_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)
6099b3b5 1559 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
718e3744 1560
1561 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1562
1563 return 0;
1564}
1565
a1ac18c4 1566static int
718e3744 1567if_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)
6099b3b5 1580 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
718e3744 1581
1582 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1583
1584 return 0;
1585}
1586
1587#else
1588void
a1ac18c4 1589rtadv_init (void)
718e3744 1590{
1591 /* Empty.*/;
1592}
1593#endif /* RTADV && HAVE_IPV6 */