]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rtadv.c
*: nuke ^L (page feed)
[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 *);
6b0655a2 69
718e3744 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;
6b0655a2 83
a1ac18c4 84static struct rtadv *
85rtadv_new (void)
718e3744 86{
393deb9b 87 return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));
718e3744 88}
89
a1ac18c4 90static int
718e3744 91rtadv_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
b99760ab 118 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
718e3744 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)
b0b709ab
SH
135 {
136 int *hoptr = (int *) CMSG_DATA (cmsgptr);
137 *hoplimit = *hoptr;
138 }
718e3744 139 }
140 return ret;
141}
142
143#define RTADV_MSG_SIZE 4096
144
145/* Send router advertisement packet. */
a1ac18c4 146static void
718e3744 147rtadv_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;
6f0e3f6e 154#ifdef HAVE_STRUCT_SOCKADDR_DL
718e3744 155 struct sockaddr_dl *sdl;
6f0e3f6e 156#endif /* HAVE_STRUCT_SOCKADDR_DL */
57492d56 157 static void *adata = NULL;
718e3744 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;
1eb8ef25 163 struct rtadv_prefix *rprefix;
718e3744 164 u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
52dc7ee6 165 struct listnode *node;
d660f698 166 u_int16_t pkt_RouterLifetime;
718e3744 167
57492d56 168 /*
169 * Allocate control message bufffer. This is dynamic because
170 * CMSG_SPACE is not guaranteed not to call a function. Note that
171 * the size will be different on different architectures due to
172 * differing alignment rules.
173 */
174 if (adata == NULL)
175 {
176 /* XXX Free on shutdown. */
177 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
178
179 if (adata == NULL)
180 zlog_err("rtadv_send_packet: can't malloc control data\n");
181 }
182
718e3744 183 /* Logging of packet. */
184 if (IS_ZEBRA_DEBUG_PACKET)
b6178002 185 zlog_debug ("Router advertisement send to %s", ifp->name);
718e3744 186
187 /* Fill in sockaddr_in6. */
188 memset (&addr, 0, sizeof (struct sockaddr_in6));
189 addr.sin6_family = AF_INET6;
190#ifdef SIN6_LEN
191 addr.sin6_len = sizeof (struct sockaddr_in6);
192#endif /* SIN6_LEN */
193 addr.sin6_port = htons (IPPROTO_ICMPV6);
aca43b65 194 IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr);
718e3744 195
196 /* Fetch interface information. */
197 zif = ifp->info;
198
199 /* Make router advertisement message. */
200 rtadv = (struct nd_router_advert *) buf;
201
202 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
203 rtadv->nd_ra_code = 0;
204 rtadv->nd_ra_cksum = 0;
205
206 rtadv->nd_ra_curhoplimit = 64;
b60668d0
CC
207
208 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
209 rtadv->nd_ra_flags_reserved =
210 zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
211 rtadv->nd_ra_flags_reserved <<= 3;
212
718e3744 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;
d660f698
DO
219 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
220 * AdvDefaultLifetime is by default based on the value of
221 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
222 * field of Router Advertisements. Given that this field is expressed
223 * in seconds, a small MaxRtrAdvInterval value can result in a zero
224 * value for this field. To prevent this, routers SHOULD keep
225 * AdvDefaultLifetime in at least one second, even if the use of
226 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
227 pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ?
228 zif->rtadv.AdvDefaultLifetime :
229 MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
230 rtadv->nd_ra_router_lifetime = htons (pkt_RouterLifetime);
718e3744 231 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
232 rtadv->nd_ra_retransmit = htonl (0);
233
234 len = sizeof (struct nd_router_advert);
235
d660f698
DO
236 /* If both the Home Agent Preference and Home Agent Lifetime are set to
237 * their default values specified above, this option SHOULD NOT be
238 * included in the Router Advertisement messages sent by this home
239 * agent. -- RFC6275, 7.4 */
240 if
241 (
242 zif->rtadv.AdvHomeAgentFlag &&
243 (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1)
244 )
7cee1bb1 245 {
246 struct nd_opt_homeagent_info *ndopt_hai =
247 (struct nd_opt_homeagent_info *)(buf + len);
248 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
249 ndopt_hai->nd_opt_hai_len = 1;
250 ndopt_hai->nd_opt_hai_reserved = 0;
251 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
d660f698
DO
252 /* 16-bit unsigned integer. The lifetime associated with the home
253 * agent in units of seconds. The default value is the same as the
254 * Router Lifetime, as specified in the main body of the Router
255 * Advertisement. The maximum value corresponds to 18.2 hours. A
256 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
257 ndopt_hai->nd_opt_hai_lifetime = htons
258 (
259 zif->rtadv.HomeAgentLifetime != -1 ?
260 zif->rtadv.HomeAgentLifetime :
261 MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/
262 );
7cee1bb1 263 len += sizeof(struct nd_opt_homeagent_info);
264 }
265
266 if (zif->rtadv.AdvIntervalOption)
267 {
268 struct nd_opt_adv_interval *ndopt_adv =
269 (struct nd_opt_adv_interval *)(buf + len);
270 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
271 ndopt_adv->nd_opt_ai_len = 1;
272 ndopt_adv->nd_opt_ai_reserved = 0;
273 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
274 len += sizeof(struct nd_opt_adv_interval);
275 }
276
718e3744 277 /* Fill in prefix. */
1eb8ef25 278 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
718e3744 279 {
280 struct nd_opt_prefix_info *pinfo;
718e3744 281
282 pinfo = (struct nd_opt_prefix_info *) (buf + len);
283
284 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
285 pinfo->nd_opt_pi_len = 4;
286 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
287
288 pinfo->nd_opt_pi_flags_reserved = 0;
289 if (rprefix->AdvOnLinkFlag)
290 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
291 if (rprefix->AdvAutonomousFlag)
292 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
7cee1bb1 293 if (rprefix->AdvRouterAddressFlag)
294 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
718e3744 295
296 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
297 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
298 pinfo->nd_opt_pi_reserved2 = 0;
299
aca43b65 300 IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix);
718e3744 301
302#ifdef DEBUG
303 {
304 u_char buf[INET6_ADDRSTRLEN];
305
b6178002 306 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
3e31cded 307 buf, INET6_ADDRSTRLEN));
718e3744 308
309 }
310#endif /* DEBUG */
311
312 len += sizeof (struct nd_opt_prefix_info);
313 }
314
315 /* Hardware address. */
6f0e3f6e 316#ifdef HAVE_STRUCT_SOCKADDR_DL
718e3744 317 sdl = &ifp->sdl;
318 if (sdl != NULL && sdl->sdl_alen != 0)
319 {
320 buf[len++] = ND_OPT_SOURCE_LINKADDR;
50adf783
DW
321
322 /* Option length should be rounded up to next octet if
323 the link address does not end on an octet boundary. */
324 buf[len++] = (sdl->sdl_alen + 9) >> 3;
718e3744 325
326 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
327 len += sdl->sdl_alen;
50adf783
DW
328
329 /* Pad option to end on an octet boundary. */
330 memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
331 len += -(sdl->sdl_alen + 2) & 0x7;
718e3744 332 }
333#else
334 if (ifp->hw_addr_len != 0)
335 {
336 buf[len++] = ND_OPT_SOURCE_LINKADDR;
50adf783
DW
337
338 /* Option length should be rounded up to next octet if
339 the link address does not end on an octet boundary. */
340 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
718e3744 341
342 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
343 len += ifp->hw_addr_len;
50adf783
DW
344
345 /* Pad option to end on an octet boundary. */
346 memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
347 len += -(ifp->hw_addr_len + 2) & 0x7;
718e3744 348 }
6f0e3f6e 349#endif /* HAVE_STRUCT_SOCKADDR_DL */
718e3744 350
6ae93c05
DO
351 /* MTU */
352 if (zif->rtadv.AdvLinkMTU)
353 {
354 struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len);
355 opt->nd_opt_mtu_type = ND_OPT_MTU;
356 opt->nd_opt_mtu_len = 1;
357 opt->nd_opt_mtu_reserved = 0;
358 opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU);
359 len += sizeof (struct nd_opt_mtu);
360 }
361
718e3744 362 msg.msg_name = (void *) &addr;
363 msg.msg_namelen = sizeof (struct sockaddr_in6);
364 msg.msg_iov = &iov;
365 msg.msg_iovlen = 1;
366 msg.msg_control = (void *) adata;
f841e02e 367 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
57492d56 368 msg.msg_flags = 0;
718e3744 369 iov.iov_base = buf;
370 iov.iov_len = len;
371
b99760ab 372 cmsgptr = ZCMSG_FIRSTHDR(&msg);
57492d56 373 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
718e3744 374 cmsgptr->cmsg_level = IPPROTO_IPV6;
375 cmsgptr->cmsg_type = IPV6_PKTINFO;
80893817 376
718e3744 377 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
378 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
379 pkt->ipi6_ifindex = ifp->ifindex;
380
381 ret = sendmsg (sock, &msg, 0);
9ccabd1c 382 if (ret < 0)
383 {
384 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
6099b3b5 385 errno, safe_strerror(errno));
9ccabd1c 386 }
718e3744 387}
388
a1ac18c4 389static int
718e3744 390rtadv_timer (struct thread *thread)
391{
1eb8ef25 392 struct listnode *node, *nnode;
718e3744 393 struct interface *ifp;
394 struct zebra_if *zif;
7cee1bb1 395 int period;
718e3744 396
397 rtadv->ra_timer = NULL;
7cee1bb1 398 if (rtadv->adv_msec_if_count == 0)
399 {
400 period = 1000; /* 1 s */
401 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
402 }
403 else
404 {
405 period = 10; /* 10 ms */
406 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
407 }
718e3744 408
1eb8ef25 409 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
718e3744 410 {
fb5174a2 411 if (if_is_loopback (ifp) || ! if_is_operative (ifp))
718e3744 412 continue;
413
414 zif = ifp->info;
415
416 if (zif->rtadv.AdvSendAdvertisements)
7cee1bb1 417 {
418 zif->rtadv.AdvIntervalTimer -= period;
419 if (zif->rtadv.AdvIntervalTimer <= 0)
420 {
d660f698
DO
421 /* FIXME: using MaxRtrAdvInterval each time isn't what section
422 6.2.4 of RFC4861 tells to do. */
7cee1bb1 423 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
424 rtadv_send_packet (rtadv->sock, ifp);
425 }
426 }
718e3744 427 }
428 return 0;
429}
430
a1ac18c4 431static void
718e3744 432rtadv_process_solicit (struct interface *ifp)
433{
434 zlog_info ("Router solicitation received on %s", ifp->name);
435
436 rtadv_send_packet (rtadv->sock, ifp);
437}
438
a1ac18c4 439static void
440rtadv_process_advert (void)
718e3744 441{
442 zlog_info ("Router advertisement received");
443}
444
a1ac18c4 445static void
fce954f8 446rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
718e3744 447{
448 struct icmp6_hdr *icmph;
449 struct interface *ifp;
450 struct zebra_if *zif;
451
452 /* Interface search. */
453 ifp = if_lookup_by_index (ifindex);
454 if (ifp == NULL)
455 {
456 zlog_warn ("Unknown interface index: %d", ifindex);
457 return;
458 }
459
460 if (if_is_loopback (ifp))
461 return;
462
463 /* Check interface configuration. */
464 zif = ifp->info;
465 if (! zif->rtadv.AdvSendAdvertisements)
466 return;
467
468 /* ICMP message length check. */
469 if (len < sizeof (struct icmp6_hdr))
470 {
471 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
472 return;
473 }
474
475 icmph = (struct icmp6_hdr *) buf;
476
477 /* ICMP message type check. */
478 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
479 icmph->icmp6_type != ND_ROUTER_ADVERT)
480 {
481 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
482 return;
483 }
484
485 /* Hoplimit check. */
486 if (hoplimit >= 0 && hoplimit != 255)
487 {
488 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
489 hoplimit);
490 return;
491 }
492
493 /* Check ICMP message type. */
494 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
495 rtadv_process_solicit (ifp);
496 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
497 rtadv_process_advert ();
498
499 return;
500}
501
a1ac18c4 502static int
718e3744 503rtadv_read (struct thread *thread)
504{
505 int sock;
506 int len;
507 u_char buf[RTADV_MSG_SIZE];
508 struct sockaddr_in6 from;
b0b709ab 509 unsigned int ifindex = 0;
718e3744 510 int hoplimit = -1;
511
512 sock = THREAD_FD (thread);
513 rtadv->ra_read = NULL;
514
515 /* Register myself. */
516 rtadv_event (RTADV_READ, sock);
517
518 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
519
520 if (len < 0)
521 {
6099b3b5 522 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
718e3744 523 return len;
524 }
525
fce954f8 526 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
718e3744 527
528 return 0;
529}
530
a1ac18c4 531static int
718e3744 532rtadv_make_socket (void)
533{
534 int sock;
535 int ret;
536 struct icmp6_filter filter;
537
edd7c245 538 if ( zserv_privs.change (ZPRIVS_RAISE) )
539 zlog_err ("rtadv_make_socket: could not raise privs, %s",
6099b3b5 540 safe_strerror (errno) );
edd7c245 541
718e3744 542 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
543
edd7c245 544 if ( zserv_privs.change (ZPRIVS_LOWER) )
545 zlog_err ("rtadv_make_socket: could not lower privs, %s",
6099b3b5 546 safe_strerror (errno) );
edd7c245 547
718e3744 548 /* When we can't make ICMPV6 socket simply back. Router
549 advertisement feature will not be supported. */
550 if (sock < 0)
551 return -1;
552
553 ret = setsockopt_ipv6_pktinfo (sock, 1);
718e3744 554 if (ret < 0)
555 return ret;
556 ret = setsockopt_ipv6_multicast_loop (sock, 0);
557 if (ret < 0)
558 return ret;
559 ret = setsockopt_ipv6_unicast_hops (sock, 255);
560 if (ret < 0)
561 return ret;
562 ret = setsockopt_ipv6_multicast_hops (sock, 255);
563 if (ret < 0)
564 return ret;
565 ret = setsockopt_ipv6_hoplimit (sock, 1);
566 if (ret < 0)
567 return ret;
568
569 ICMP6_FILTER_SETBLOCKALL(&filter);
570 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
571 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
572
573 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
574 sizeof (struct icmp6_filter));
575 if (ret < 0)
576 {
6099b3b5 577 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
718e3744 578 return ret;
579 }
580
581 return sock;
582}
6b0655a2 583
a1ac18c4 584static struct rtadv_prefix *
66e5cd87 585rtadv_prefix_new (void)
718e3744 586{
393deb9b 587 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
718e3744 588}
589
a1ac18c4 590static void
718e3744 591rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
592{
593 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
594}
595
a1ac18c4 596static struct rtadv_prefix *
aca43b65 597rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p)
718e3744 598{
52dc7ee6 599 struct listnode *node;
718e3744 600 struct rtadv_prefix *rprefix;
601
1eb8ef25 602 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
aca43b65 603 if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p))
1eb8ef25 604 return rprefix;
718e3744 605 return NULL;
606}
607
a1ac18c4 608static struct rtadv_prefix *
aca43b65 609rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p)
718e3744 610{
611 struct rtadv_prefix *rprefix;
612
613 rprefix = rtadv_prefix_lookup (rplist, p);
614 if (rprefix)
615 return rprefix;
616
617 rprefix = rtadv_prefix_new ();
aca43b65 618 memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6));
718e3744 619 listnode_add (rplist, rprefix);
620
621 return rprefix;
622}
623
a1ac18c4 624static void
718e3744 625rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
626{
627 struct rtadv_prefix *rprefix;
628
629 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
630
631 /* Set parameters. */
632 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
633 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
634 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
635 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
7cee1bb1 636 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
718e3744 637}
638
a1ac18c4 639static int
718e3744 640rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
641{
642 struct rtadv_prefix *rprefix;
643
644 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
645 if (rprefix != NULL)
646 {
647 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
648 rtadv_prefix_free (rprefix);
649 return 1;
650 }
651 else
652 return 0;
653}
654
655DEFUN (ipv6_nd_suppress_ra,
656 ipv6_nd_suppress_ra_cmd,
657 "ipv6 nd suppress-ra",
3e31cded 658 "Interface IPv6 config commands\n"
718e3744 659 "Neighbor discovery\n"
660 "Suppress Router Advertisement\n")
661{
662 struct interface *ifp;
663 struct zebra_if *zif;
664
665 ifp = vty->index;
666 zif = ifp->info;
667
668 if (if_is_loopback (ifp))
669 {
670 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
671 return CMD_WARNING;
672 }
673
674 if (zif->rtadv.AdvSendAdvertisements)
675 {
676 zif->rtadv.AdvSendAdvertisements = 0;
677 zif->rtadv.AdvIntervalTimer = 0;
678 rtadv->adv_if_count--;
679
680 if_leave_all_router (rtadv->sock, ifp);
681
682 if (rtadv->adv_if_count == 0)
683 rtadv_event (RTADV_STOP, 0);
684 }
685
686 return CMD_SUCCESS;
687}
688
718e3744 689DEFUN (no_ipv6_nd_suppress_ra,
690 no_ipv6_nd_suppress_ra_cmd,
691 "no ipv6 nd suppress-ra",
692 NO_STR
3e31cded 693 "Interface IPv6 config commands\n"
718e3744 694 "Neighbor discovery\n"
695 "Suppress Router Advertisement\n")
696{
697 struct interface *ifp;
698 struct zebra_if *zif;
699
700 ifp = vty->index;
701 zif = ifp->info;
702
703 if (if_is_loopback (ifp))
704 {
705 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
706 return CMD_WARNING;
707 }
708
709 if (! zif->rtadv.AdvSendAdvertisements)
710 {
711 zif->rtadv.AdvSendAdvertisements = 1;
712 zif->rtadv.AdvIntervalTimer = 0;
713 rtadv->adv_if_count++;
714
715 if_join_all_router (rtadv->sock, ifp);
716
717 if (rtadv->adv_if_count == 1)
718 rtadv_event (RTADV_START, rtadv->sock);
719 }
720
721 return CMD_SUCCESS;
722}
723
7cee1bb1 724DEFUN (ipv6_nd_ra_interval_msec,
725 ipv6_nd_ra_interval_msec_cmd,
4afa50b3 726 "ipv6 nd ra-interval msec <70-1800000>",
7cee1bb1 727 "Interface IPv6 config commands\n"
728 "Neighbor discovery\n"
729 "Router Advertisement interval\n"
730 "Router Advertisement interval in milliseconds\n")
731{
4afa50b3
DO
732 unsigned interval;
733 struct interface *ifp = (struct interface *) vty->index;
734 struct zebra_if *zif = ifp->info;
7cee1bb1 735
4afa50b3
DO
736 VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
737 if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000))
738 {
739 vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
740 return CMD_WARNING;
741 }
7cee1bb1 742
743 if (zif->rtadv.MaxRtrAdvInterval % 1000)
744 rtadv->adv_msec_if_count--;
745
746 if (interval % 1000)
747 rtadv->adv_msec_if_count++;
748
749 zif->rtadv.MaxRtrAdvInterval = interval;
750 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
751 zif->rtadv.AdvIntervalTimer = 0;
752
753 return CMD_SUCCESS;
754}
755
718e3744 756DEFUN (ipv6_nd_ra_interval,
757 ipv6_nd_ra_interval_cmd,
4afa50b3 758 "ipv6 nd ra-interval <1-1800>",
3e31cded 759 "Interface IPv6 config commands\n"
718e3744 760 "Neighbor discovery\n"
761 "Router Advertisement interval\n"
762 "Router Advertisement interval in seconds\n")
763{
4afa50b3
DO
764 unsigned interval;
765 struct interface *ifp = (struct interface *) vty->index;
766 struct zebra_if *zif = ifp->info;
718e3744 767
4afa50b3
DO
768 VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
769 if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime))
770 {
771 vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
772 return CMD_WARNING;
773 }
718e3744 774
7cee1bb1 775 if (zif->rtadv.MaxRtrAdvInterval % 1000)
776 rtadv->adv_msec_if_count--;
777
778 /* convert to milliseconds */
779 interval = interval * 1000;
780
718e3744 781 zif->rtadv.MaxRtrAdvInterval = interval;
782 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
783 zif->rtadv.AdvIntervalTimer = 0;
784
785 return CMD_SUCCESS;
786}
787
788DEFUN (no_ipv6_nd_ra_interval,
789 no_ipv6_nd_ra_interval_cmd,
790 "no ipv6 nd ra-interval",
791 NO_STR
3e31cded 792 "Interface IPv6 config commands\n"
718e3744 793 "Neighbor discovery\n"
794 "Router Advertisement interval\n")
795{
796 struct interface *ifp;
797 struct zebra_if *zif;
798
799 ifp = (struct interface *) vty->index;
800 zif = ifp->info;
801
7cee1bb1 802 if (zif->rtadv.MaxRtrAdvInterval % 1000)
803 rtadv->adv_msec_if_count--;
804
718e3744 805 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
806 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
807 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
808
809 return CMD_SUCCESS;
810}
811
4afa50b3
DO
812ALIAS (no_ipv6_nd_ra_interval,
813 no_ipv6_nd_ra_interval_val_cmd,
814 "no ipv6 nd ra-interval <1-1800>",
815 NO_STR
816 "Interface IPv6 config commands\n"
817 "Neighbor discovery\n"
818 "Router Advertisement interval\n")
819
820ALIAS (no_ipv6_nd_ra_interval,
821 no_ipv6_nd_ra_interval_msec_val_cmd,
822 "no ipv6 nd ra-interval msec <1-1800000>",
823 NO_STR
824 "Interface IPv6 config commands\n"
825 "Neighbor discovery\n"
826 "Router Advertisement interval\n"
827 "Router Advertisement interval in milliseconds\n")
828
718e3744 829DEFUN (ipv6_nd_ra_lifetime,
830 ipv6_nd_ra_lifetime_cmd,
4afa50b3 831 "ipv6 nd ra-lifetime <0-9000>",
3e31cded 832 "Interface IPv6 config commands\n"
718e3744 833 "Neighbor discovery\n"
834 "Router lifetime\n"
4afa50b3 835 "Router lifetime in seconds (0 stands for a non-default gw)\n")
718e3744 836{
837 int lifetime;
838 struct interface *ifp;
839 struct zebra_if *zif;
840
841 ifp = (struct interface *) vty->index;
842 zif = ifp->info;
843
4afa50b3 844 VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[0], 0, 9000);
718e3744 845
d660f698
DO
846 /* The value to be placed in the Router Lifetime field
847 * of Router Advertisements sent from the interface,
848 * in seconds. MUST be either zero or between
849 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
4afa50b3 850 if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval))
718e3744 851 {
4afa50b3 852 vty_out (vty, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE);
718e3744 853 return CMD_WARNING;
854 }
855
856 zif->rtadv.AdvDefaultLifetime = lifetime;
857
858 return CMD_SUCCESS;
859}
860
861DEFUN (no_ipv6_nd_ra_lifetime,
862 no_ipv6_nd_ra_lifetime_cmd,
863 "no ipv6 nd ra-lifetime",
864 NO_STR
3e31cded 865 "Interface IPv6 config commands\n"
718e3744 866 "Neighbor discovery\n"
867 "Router lifetime\n")
868{
869 struct interface *ifp;
870 struct zebra_if *zif;
871
872 ifp = (struct interface *) vty->index;
873 zif = ifp->info;
874
d660f698 875 zif->rtadv.AdvDefaultLifetime = -1;
718e3744 876
877 return CMD_SUCCESS;
878}
879
4afa50b3
DO
880ALIAS (no_ipv6_nd_ra_lifetime,
881 no_ipv6_nd_ra_lifetime_val_cmd,
882 "no ipv6 nd ra-lifetime <0-9000>",
883 NO_STR
884 "Interface IPv6 config commands\n"
885 "Neighbor discovery\n"
886 "Router lifetime\n"
887 "Router lifetime in seconds (0 stands for a non-default gw)\n")
888
718e3744 889DEFUN (ipv6_nd_reachable_time,
890 ipv6_nd_reachable_time_cmd,
4afa50b3 891 "ipv6 nd reachable-time <1-3600000>",
3e31cded 892 "Interface IPv6 config commands\n"
718e3744 893 "Neighbor discovery\n"
894 "Reachable time\n"
895 "Reachable time in milliseconds\n")
896{
4afa50b3
DO
897 struct interface *ifp = (struct interface *) vty->index;
898 struct zebra_if *zif = ifp->info;
899 VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[0], 1, RTADV_MAX_REACHABLE_TIME);
718e3744 900 return CMD_SUCCESS;
901}
902
903DEFUN (no_ipv6_nd_reachable_time,
904 no_ipv6_nd_reachable_time_cmd,
905 "no ipv6 nd reachable-time",
906 NO_STR
3e31cded 907 "Interface IPv6 config commands\n"
718e3744 908 "Neighbor discovery\n"
909 "Reachable time\n")
910{
911 struct interface *ifp;
912 struct zebra_if *zif;
913
914 ifp = (struct interface *) vty->index;
915 zif = ifp->info;
916
917 zif->rtadv.AdvReachableTime = 0;
918
919 return CMD_SUCCESS;
920}
921
4afa50b3
DO
922ALIAS (no_ipv6_nd_reachable_time,
923 no_ipv6_nd_reachable_time_val_cmd,
924 "no ipv6 nd reachable-time <1-3600000>",
925 NO_STR
926 "Interface IPv6 config commands\n"
927 "Neighbor discovery\n"
928 "Reachable time\n"
929 "Reachable time in milliseconds\n")
930
7cee1bb1 931DEFUN (ipv6_nd_homeagent_preference,
932 ipv6_nd_homeagent_preference_cmd,
4afa50b3 933 "ipv6 nd home-agent-preference <0-65535>",
7cee1bb1 934 "Interface IPv6 config commands\n"
935 "Neighbor discovery\n"
936 "Home Agent preference\n"
4afa50b3 937 "preference value (default is 0, least preferred)\n")
7cee1bb1 938{
4afa50b3
DO
939 struct interface *ifp = (struct interface *) vty->index;
940 struct zebra_if *zif = ifp->info;
941 VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[0], 0, 65535);
7cee1bb1 942 return CMD_SUCCESS;
943}
944
945DEFUN (no_ipv6_nd_homeagent_preference,
946 no_ipv6_nd_homeagent_preference_cmd,
947 "no ipv6 nd home-agent-preference",
948 NO_STR
949 "Interface IPv6 config commands\n"
950 "Neighbor discovery\n"
951 "Home Agent preference\n")
952{
953 struct interface *ifp;
954 struct zebra_if *zif;
955
956 ifp = (struct interface *) vty->index;
957 zif = ifp->info;
958
959 zif->rtadv.HomeAgentPreference = 0;
960
961 return CMD_SUCCESS;
962}
963
4afa50b3
DO
964ALIAS (no_ipv6_nd_homeagent_preference,
965 no_ipv6_nd_homeagent_preference_val_cmd,
966 "no ipv6 nd home-agent-preference <0-65535>",
967 NO_STR
968 "Interface IPv6 config commands\n"
969 "Neighbor discovery\n"
970 "Home Agent preference\n"
971 "preference value (default is 0, least preferred)\n")
972
7cee1bb1 973DEFUN (ipv6_nd_homeagent_lifetime,
974 ipv6_nd_homeagent_lifetime_cmd,
4afa50b3 975 "ipv6 nd home-agent-lifetime <0-65520>",
7cee1bb1 976 "Interface IPv6 config commands\n"
977 "Neighbor discovery\n"
978 "Home Agent lifetime\n"
4afa50b3 979 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
7cee1bb1 980{
4afa50b3
DO
981 struct interface *ifp = (struct interface *) vty->index;
982 struct zebra_if *zif = ifp->info;
983 VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[0], 0, RTADV_MAX_HALIFETIME);
7cee1bb1 984 return CMD_SUCCESS;
985}
986
987DEFUN (no_ipv6_nd_homeagent_lifetime,
988 no_ipv6_nd_homeagent_lifetime_cmd,
989 "no ipv6 nd home-agent-lifetime",
990 NO_STR
991 "Interface IPv6 config commands\n"
992 "Neighbor discovery\n"
993 "Home Agent lifetime\n")
994{
995 struct interface *ifp;
996 struct zebra_if *zif;
997
998 ifp = (struct interface *) vty->index;
999 zif = ifp->info;
1000
d660f698 1001 zif->rtadv.HomeAgentLifetime = -1;
7cee1bb1 1002
1003 return CMD_SUCCESS;
1004}
1005
4afa50b3
DO
1006ALIAS (no_ipv6_nd_homeagent_lifetime,
1007 no_ipv6_nd_homeagent_lifetime_val_cmd,
1008 "no ipv6 nd home-agent-lifetime <0-65520>",
1009 NO_STR
1010 "Interface IPv6 config commands\n"
1011 "Neighbor discovery\n"
1012 "Home Agent lifetime\n"
1013 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1014
718e3744 1015DEFUN (ipv6_nd_managed_config_flag,
1016 ipv6_nd_managed_config_flag_cmd,
1017 "ipv6 nd managed-config-flag",
3e31cded 1018 "Interface IPv6 config commands\n"
718e3744 1019 "Neighbor discovery\n"
1020 "Managed address configuration flag\n")
1021{
1022 struct interface *ifp;
1023 struct zebra_if *zif;
1024
1025 ifp = (struct interface *) vty->index;
1026 zif = ifp->info;
1027
1028 zif->rtadv.AdvManagedFlag = 1;
1029
1030 return CMD_SUCCESS;
1031}
1032
1033DEFUN (no_ipv6_nd_managed_config_flag,
1034 no_ipv6_nd_managed_config_flag_cmd,
1035 "no ipv6 nd managed-config-flag",
1036 NO_STR
3e31cded 1037 "Interface IPv6 config commands\n"
718e3744 1038 "Neighbor discovery\n"
1039 "Managed address configuration flag\n")
1040{
1041 struct interface *ifp;
1042 struct zebra_if *zif;
1043
1044 ifp = (struct interface *) vty->index;
1045 zif = ifp->info;
1046
1047 zif->rtadv.AdvManagedFlag = 0;
1048
1049 return CMD_SUCCESS;
1050}
1051
7cee1bb1 1052DEFUN (ipv6_nd_homeagent_config_flag,
1053 ipv6_nd_homeagent_config_flag_cmd,
1054 "ipv6 nd home-agent-config-flag",
1055 "Interface IPv6 config commands\n"
1056 "Neighbor discovery\n"
1057 "Home Agent configuration flag\n")
1058{
1059 struct interface *ifp;
1060 struct zebra_if *zif;
1061
1062 ifp = (struct interface *) vty->index;
1063 zif = ifp->info;
1064
1065 zif->rtadv.AdvHomeAgentFlag = 1;
1066
1067 return CMD_SUCCESS;
1068}
1069
1070DEFUN (no_ipv6_nd_homeagent_config_flag,
1071 no_ipv6_nd_homeagent_config_flag_cmd,
1072 "no ipv6 nd home-agent-config-flag",
1073 NO_STR
1074 "Interface IPv6 config commands\n"
1075 "Neighbor discovery\n"
1076 "Home Agent configuration flag\n")
1077{
1078 struct interface *ifp;
1079 struct zebra_if *zif;
1080
1081 ifp = (struct interface *) vty->index;
1082 zif = ifp->info;
1083
1084 zif->rtadv.AdvHomeAgentFlag = 0;
1085
1086 return CMD_SUCCESS;
1087}
1088
1089DEFUN (ipv6_nd_adv_interval_config_option,
1090 ipv6_nd_adv_interval_config_option_cmd,
1091 "ipv6 nd adv-interval-option",
1092 "Interface IPv6 config commands\n"
1093 "Neighbor discovery\n"
1094 "Advertisement Interval Option\n")
1095{
1096 struct interface *ifp;
1097 struct zebra_if *zif;
1098
1099 ifp = (struct interface *) vty->index;
1100 zif = ifp->info;
1101
1102 zif->rtadv.AdvIntervalOption = 1;
1103
1104 return CMD_SUCCESS;
1105}
1106
1107DEFUN (no_ipv6_nd_adv_interval_config_option,
1108 no_ipv6_nd_adv_interval_config_option_cmd,
1109 "no ipv6 nd adv-interval-option",
1110 NO_STR
1111 "Interface IPv6 config commands\n"
1112 "Neighbor discovery\n"
1113 "Advertisement Interval Option\n")
1114{
1115 struct interface *ifp;
1116 struct zebra_if *zif;
1117
1118 ifp = (struct interface *) vty->index;
1119 zif = ifp->info;
1120
1121 zif->rtadv.AdvIntervalOption = 0;
1122
1123 return CMD_SUCCESS;
1124}
1125
718e3744 1126DEFUN (ipv6_nd_other_config_flag,
1127 ipv6_nd_other_config_flag_cmd,
1128 "ipv6 nd other-config-flag",
3e31cded 1129 "Interface IPv6 config commands\n"
718e3744 1130 "Neighbor discovery\n"
1131 "Other statefull configuration flag\n")
1132{
1133 struct interface *ifp;
1134 struct zebra_if *zif;
1135
1136 ifp = (struct interface *) vty->index;
1137 zif = ifp->info;
1138
1139 zif->rtadv.AdvOtherConfigFlag = 1;
1140
1141 return CMD_SUCCESS;
1142}
1143
1144DEFUN (no_ipv6_nd_other_config_flag,
1145 no_ipv6_nd_other_config_flag_cmd,
1146 "no ipv6 nd other-config-flag",
1147 NO_STR
3e31cded 1148 "Interface IPv6 config commands\n"
718e3744 1149 "Neighbor discovery\n"
1150 "Other statefull configuration flag\n")
1151{
1152 struct interface *ifp;
1153 struct zebra_if *zif;
1154
1155 ifp = (struct interface *) vty->index;
1156 zif = ifp->info;
1157
1158 zif->rtadv.AdvOtherConfigFlag = 0;
1159
1160 return CMD_SUCCESS;
1161}
1162
3e31cded 1163DEFUN (ipv6_nd_prefix,
1164 ipv6_nd_prefix_cmd,
1165 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
7cee1bb1 1166 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
3e31cded 1167 "Interface IPv6 config commands\n"
718e3744 1168 "Neighbor discovery\n"
1169 "Prefix information\n"
1170 "IPv6 prefix\n"
1171 "Valid lifetime in seconds\n"
3e31cded 1172 "Infinite valid lifetime\n"
718e3744 1173 "Preferred lifetime in seconds\n"
3e31cded 1174 "Infinite preferred lifetime\n"
1175 "Do not use prefix for onlink determination\n"
7cee1bb1 1176 "Do not use prefix for autoconfiguration\n"
1177 "Set Router Address flag\n")
718e3744 1178{
1179 int i;
1180 int ret;
3e31cded 1181 int cursor = 1;
718e3744 1182 struct interface *ifp;
1183 struct zebra_if *zebra_if;
1184 struct rtadv_prefix rp;
1185
1186 ifp = (struct interface *) vty->index;
1187 zebra_if = ifp->info;
1188
aca43b65 1189 ret = str2prefix_ipv6 (argv[0], &rp.prefix);
718e3744 1190 if (!ret)
1191 {
1192 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1193 return CMD_WARNING;
1194 }
6bb1273e 1195 apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
3e31cded 1196 rp.AdvOnLinkFlag = 1;
1197 rp.AdvAutonomousFlag = 1;
7cee1bb1 1198 rp.AdvRouterAddressFlag = 0;
3e31cded 1199 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1200 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
718e3744 1201
3e31cded 1202 if (argc > 1)
718e3744 1203 {
3e31cded 1204 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
718e3744 1205 {
3e31cded 1206 if ( strncmp (argv[1], "i", 1) == 0)
1207 rp.AdvValidLifetime = UINT32_MAX;
1208 else
1209 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1210 (char **)NULL, 10);
1211
1212 if ( strncmp (argv[2], "i", 1) == 0)
1213 rp.AdvPreferredLifetime = UINT32_MAX;
1214 else
1215 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1216 (char **)NULL, 10);
1217
1218 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1219 {
1220 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1221 return CMD_WARNING;
1222 }
1223 cursor = cursor + 2;
718e3744 1224 }
3e31cded 1225 if (argc > cursor)
718e3744 1226 {
3e31cded 1227 for (i = cursor; i < argc; i++)
1228 {
1229 if (strncmp (argv[i], "of", 2) == 0)
1230 rp.AdvOnLinkFlag = 0;
1231 if (strncmp (argv[i], "no", 2) == 0)
1232 rp.AdvAutonomousFlag = 0;
7cee1bb1 1233 if (strncmp (argv[i], "ro", 2) == 0)
1234 rp.AdvRouterAddressFlag = 1;
3e31cded 1235 }
718e3744 1236 }
1237 }
1238
1239 rtadv_prefix_set (zebra_if, &rp);
1240
1241 return CMD_SUCCESS;
1242}
1243
7cee1bb1 1244ALIAS (ipv6_nd_prefix,
1245 ipv6_nd_prefix_val_nortaddr_cmd,
1246 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1247 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1248 "Interface IPv6 config commands\n"
1249 "Neighbor discovery\n"
1250 "Prefix information\n"
1251 "IPv6 prefix\n"
1252 "Valid lifetime in seconds\n"
1253 "Infinite valid lifetime\n"
1254 "Preferred lifetime in seconds\n"
1255 "Infinite preferred lifetime\n"
1256 "Do not use prefix for onlink determination\n"
1257 "Do not use prefix for autoconfiguration\n")
1258
3e31cded 1259ALIAS (ipv6_nd_prefix,
1260 ipv6_nd_prefix_val_rev_cmd,
1261 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1262 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1263 "Interface IPv6 config commands\n"
1264 "Neighbor discovery\n"
1265 "Prefix information\n"
1266 "IPv6 prefix\n"
1267 "Valid lifetime in seconds\n"
1268 "Infinite valid lifetime\n"
1269 "Preferred lifetime in seconds\n"
1270 "Infinite preferred lifetime\n"
1271 "Do not use prefix for autoconfiguration\n"
1272 "Do not use prefix for onlink determination\n")
1273
7cee1bb1 1274ALIAS (ipv6_nd_prefix,
1275 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1276 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1277 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
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 "Do not use prefix for autoconfiguration\n"
1287 "Do not use prefix for onlink determination\n"
1288 "Set Router Address flag\n")
1289
3e31cded 1290ALIAS (ipv6_nd_prefix,
1291 ipv6_nd_prefix_val_noauto_cmd,
1292 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1293 "(<0-4294967295>|infinite) (no-autoconfig|)",
1294 "Interface IPv6 config commands\n"
1295 "Neighbor discovery\n"
1296 "Prefix information\n"
1297 "IPv6 prefix\n"
1298 "Valid lifetime in seconds\n"
1299 "Infinite valid lifetime\n"
1300 "Preferred lifetime in seconds\n"
1301 "Infinite preferred lifetime\n"
7cee1bb1 1302 "Do not use prefix for autoconfiguration")
3e31cded 1303
1304ALIAS (ipv6_nd_prefix,
1305 ipv6_nd_prefix_val_offlink_cmd,
1306 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1307 "(<0-4294967295>|infinite) (off-link|)",
1308 "Interface IPv6 config commands\n"
1309 "Neighbor discovery\n"
1310 "Prefix information\n"
1311 "IPv6 prefix\n"
1312 "Valid lifetime in seconds\n"
1313 "Infinite valid lifetime\n"
1314 "Preferred lifetime in seconds\n"
1315 "Infinite preferred lifetime\n"
1316 "Do not use prefix for onlink determination\n")
1317
7cee1bb1 1318ALIAS (ipv6_nd_prefix,
1319 ipv6_nd_prefix_val_rtaddr_cmd,
1320 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1321 "(<0-4294967295>|infinite) (router-address|)",
1322 "Interface IPv6 config commands\n"
1323 "Neighbor discovery\n"
1324 "Prefix information\n"
1325 "IPv6 prefix\n"
1326 "Valid lifetime in seconds\n"
1327 "Infinite valid lifetime\n"
1328 "Preferred lifetime in seconds\n"
1329 "Infinite preferred lifetime\n"
1330 "Set Router Address flag\n")
1331
3e31cded 1332ALIAS (ipv6_nd_prefix,
1333 ipv6_nd_prefix_val_cmd,
1334 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1335 "(<0-4294967295>|infinite)",
1336 "Interface IPv6 config commands\n"
1337 "Neighbor discovery\n"
1338 "Prefix information\n"
1339 "IPv6 prefix\n"
1340 "Valid lifetime in seconds\n"
1341 "Infinite valid lifetime\n"
1342 "Preferred lifetime in seconds\n"
1343 "Infinite preferred lifetime\n")
1344
1345ALIAS (ipv6_nd_prefix,
1346 ipv6_nd_prefix_noval_cmd,
1347 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1348 "Interface IPv6 config commands\n"
1349 "Neighbor discovery\n"
1350 "Prefix information\n"
1351 "IPv6 prefix\n"
1352 "Do not use prefix for autoconfiguration\n"
1353 "Do not use prefix for onlink determination\n")
1354
1355ALIAS (ipv6_nd_prefix,
1356 ipv6_nd_prefix_noval_rev_cmd,
1357 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1358 "Interface IPv6 config commands\n"
1359 "Neighbor discovery\n"
1360 "Prefix information\n"
1361 "IPv6 prefix\n"
1362 "Do not use prefix for onlink determination\n"
1363 "Do not use prefix for autoconfiguration\n")
1364
1365ALIAS (ipv6_nd_prefix,
1366 ipv6_nd_prefix_noval_noauto_cmd,
1367 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1368 "Interface IPv6 config commands\n"
1369 "Neighbor discovery\n"
1370 "Prefix information\n"
1371 "IPv6 prefix\n"
1372 "Do not use prefix for autoconfiguration\n")
1373
1374ALIAS (ipv6_nd_prefix,
1375 ipv6_nd_prefix_noval_offlink_cmd,
1376 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1377 "Interface IPv6 config commands\n"
1378 "Neighbor discovery\n"
1379 "Prefix information\n"
1380 "IPv6 prefix\n"
1381 "Do not use prefix for onlink determination\n")
1382
7cee1bb1 1383ALIAS (ipv6_nd_prefix,
1384 ipv6_nd_prefix_noval_rtaddr_cmd,
1385 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1386 "Interface IPv6 config commands\n"
1387 "Neighbor discovery\n"
1388 "Prefix information\n"
1389 "IPv6 prefix\n"
1390 "Set Router Address flag\n")
1391
3e31cded 1392ALIAS (ipv6_nd_prefix,
1393 ipv6_nd_prefix_prefix_cmd,
1394 "ipv6 nd prefix X:X::X:X/M",
1395 "Interface IPv6 config commands\n"
718e3744 1396 "Neighbor discovery\n"
1397 "Prefix information\n"
1398 "IPv6 prefix\n")
1399
3e31cded 1400DEFUN (no_ipv6_nd_prefix,
1401 no_ipv6_nd_prefix_cmd,
1402 "no ipv6 nd prefix IPV6PREFIX",
718e3744 1403 NO_STR
3e31cded 1404 "Interface IPv6 config commands\n"
718e3744 1405 "Neighbor discovery\n"
1406 "Prefix information\n"
1407 "IPv6 prefix\n")
1408{
1409 int ret;
1410 struct interface *ifp;
1411 struct zebra_if *zebra_if;
1412 struct rtadv_prefix rp;
1413
1414 ifp = (struct interface *) vty->index;
1415 zebra_if = ifp->info;
1416
aca43b65 1417 ret = str2prefix_ipv6 (argv[0], &rp.prefix);
718e3744 1418 if (!ret)
1419 {
1420 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1421 return CMD_WARNING;
1422 }
6bb1273e 1423 apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
718e3744 1424
1425 ret = rtadv_prefix_reset (zebra_if, &rp);
1426 if (!ret)
1427 {
1428 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1429 return CMD_WARNING;
1430 }
1431
1432 return CMD_SUCCESS;
1433}
b60668d0
CC
1434
1435DEFUN (ipv6_nd_router_preference,
1436 ipv6_nd_router_preference_cmd,
1437 "ipv6 nd router-preference (high|medium|low)",
1438 "Interface IPv6 config commands\n"
1439 "Neighbor discovery\n"
1440 "Default router preference\n"
1441 "High default router preference\n"
1442 "Low default router preference\n"
1443 "Medium default router preference (default)\n")
1444{
1445 struct interface *ifp;
1446 struct zebra_if *zif;
1447 int i = 0;
1448
1449 ifp = (struct interface *) vty->index;
1450 zif = ifp->info;
1451
1452 while (0 != rtadv_pref_strs[i])
1453 {
1454 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1455 {
1456 zif->rtadv.DefaultPreference = i;
1457 return CMD_SUCCESS;
1458 }
1459 i++;
1460 }
1461
1462 return CMD_ERR_NO_MATCH;
1463}
1464
1465DEFUN (no_ipv6_nd_router_preference,
1466 no_ipv6_nd_router_preference_cmd,
1467 "no ipv6 nd router-preference",
1468 NO_STR
1469 "Interface IPv6 config commands\n"
1470 "Neighbor discovery\n"
1471 "Default router preference\n")
1472{
1473 struct interface *ifp;
1474 struct zebra_if *zif;
1475
1476 ifp = (struct interface *) vty->index;
1477 zif = ifp->info;
1478
1479 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1480
1481 return CMD_SUCCESS;
1482}
1483
4afa50b3
DO
1484ALIAS (no_ipv6_nd_router_preference,
1485 no_ipv6_nd_router_preference_val_cmd,
2b00515a 1486 "no ipv6 nd router-preference (high|medium|low)",
4afa50b3
DO
1487 NO_STR
1488 "Interface IPv6 config commands\n"
1489 "Neighbor discovery\n"
1490 "Default router preference\n"
1491 "High default router preference\n"
1492 "Low default router preference\n"
1493 "Medium default router preference (default)\n")
1494
6ae93c05
DO
1495DEFUN (ipv6_nd_mtu,
1496 ipv6_nd_mtu_cmd,
1497 "ipv6 nd mtu <1-65535>",
1498 "Interface IPv6 config commands\n"
1499 "Neighbor discovery\n"
1500 "Advertised MTU\n"
1501 "MTU in bytes\n")
1502{
1503 struct interface *ifp = (struct interface *) vty->index;
1504 struct zebra_if *zif = ifp->info;
1505 VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
1506 return CMD_SUCCESS;
1507}
1508
1509DEFUN (no_ipv6_nd_mtu,
1510 no_ipv6_nd_mtu_cmd,
1511 "no ipv6 nd mtu",
1512 NO_STR
1513 "Interface IPv6 config commands\n"
1514 "Neighbor discovery\n"
1515 "Advertised MTU\n")
1516{
1517 struct interface *ifp = (struct interface *) vty->index;
1518 struct zebra_if *zif = ifp->info;
1519 zif->rtadv.AdvLinkMTU = 0;
1520 return CMD_SUCCESS;
1521}
1522
1523ALIAS (no_ipv6_nd_mtu,
1524 no_ipv6_nd_mtu_val_cmd,
1525 "no ipv6 nd mtu <1-65535>",
1526 NO_STR
1527 "Interface IPv6 config commands\n"
1528 "Neighbor discovery\n"
1529 "Advertised MTU\n"
1530 "MTU in bytes\n")
1531
718e3744 1532/* Write configuration about router advertisement. */
1533void
1534rtadv_config_write (struct vty *vty, struct interface *ifp)
1535{
1536 struct zebra_if *zif;
52dc7ee6 1537 struct listnode *node;
718e3744 1538 struct rtadv_prefix *rprefix;
1539 u_char buf[INET6_ADDRSTRLEN];
7cee1bb1 1540 int interval;
718e3744 1541
1542 if (! rtadv)
1543 return;
1544
1545 zif = ifp->info;
1546
1547 if (! if_is_loopback (ifp))
1548 {
1549 if (zif->rtadv.AdvSendAdvertisements)
1550 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1551 else
1552 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1553 }
1554
7cee1bb1 1555
1556 interval = zif->rtadv.MaxRtrAdvInterval;
1557 if (interval % 1000)
1558 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1559 VTY_NEWLINE);
1560 else
1561 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1562 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
718e3744 1563 VTY_NEWLINE);
1564
6134b875
DO
1565 if (zif->rtadv.AdvIntervalOption)
1566 vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE);
1567
d660f698 1568 if (zif->rtadv.AdvDefaultLifetime != -1)
718e3744 1569 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1570 VTY_NEWLINE);
1571
6134b875
DO
1572 if (zif->rtadv.HomeAgentPreference)
1573 vty_out (vty, " ipv6 nd home-agent-preference %u%s",
1574 zif->rtadv.HomeAgentPreference, VTY_NEWLINE);
1575
d660f698 1576 if (zif->rtadv.HomeAgentLifetime != -1)
6134b875
DO
1577 vty_out (vty, " ipv6 nd home-agent-lifetime %u%s",
1578 zif->rtadv.HomeAgentLifetime, VTY_NEWLINE);
1579
1580 if (zif->rtadv.AdvHomeAgentFlag)
1581 vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE);
1582
718e3744 1583 if (zif->rtadv.AdvReachableTime)
1584 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1585 VTY_NEWLINE);
1586
1587 if (zif->rtadv.AdvManagedFlag)
1588 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1589
1590 if (zif->rtadv.AdvOtherConfigFlag)
1591 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1592
b60668d0
CC
1593 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1594 vty_out (vty, " ipv6 nd router-preference %s%s",
1595 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1596 VTY_NEWLINE);
1597
6ae93c05
DO
1598 if (zif->rtadv.AdvLinkMTU)
1599 vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
1600
1eb8ef25 1601 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
718e3744 1602 {
3e31cded 1603 vty_out (vty, " ipv6 nd prefix %s/%d",
aca43b65 1604 inet_ntop (AF_INET6, &rprefix->prefix.prefix,
c9e52be3 1605 (char *) buf, INET6_ADDRSTRLEN),
3e31cded 1606 rprefix->prefix.prefixlen);
1607 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1608 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1609 {
1610 if (rprefix->AdvValidLifetime == UINT32_MAX)
1611 vty_out (vty, " infinite");
1612 else
1613 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1614 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1615 vty_out (vty, " infinite");
1616 else
1617 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1618 }
1619 if (!rprefix->AdvOnLinkFlag)
1620 vty_out (vty, " off-link");
1621 if (!rprefix->AdvAutonomousFlag)
1622 vty_out (vty, " no-autoconfig");
7cee1bb1 1623 if (rprefix->AdvRouterAddressFlag)
1624 vty_out (vty, " router-address");
718e3744 1625 vty_out (vty, "%s", VTY_NEWLINE);
1626 }
1627}
1628
718e3744 1629
a1ac18c4 1630static void
718e3744 1631rtadv_event (enum rtadv_event event, int val)
1632{
1633 switch (event)
1634 {
1635 case RTADV_START:
1636 if (! rtadv->ra_read)
b21b19c5 1637 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
718e3744 1638 if (! rtadv->ra_timer)
3e31cded 1639 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1640 NULL, 0);
718e3744 1641 break;
1642 case RTADV_STOP:
1643 if (rtadv->ra_timer)
1644 {
1645 thread_cancel (rtadv->ra_timer);
1646 rtadv->ra_timer = NULL;
1647 }
1648 if (rtadv->ra_read)
1649 {
1650 thread_cancel (rtadv->ra_read);
1651 rtadv->ra_read = NULL;
1652 }
1653 break;
1654 case RTADV_TIMER:
1655 if (! rtadv->ra_timer)
3e31cded 1656 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1657 val);
718e3744 1658 break;
7cee1bb1 1659 case RTADV_TIMER_MSEC:
1660 if (! rtadv->ra_timer)
1661 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1662 NULL, val);
1663 break;
718e3744 1664 case RTADV_READ:
1665 if (! rtadv->ra_read)
b21b19c5 1666 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
718e3744 1667 break;
1668 default:
1669 break;
1670 }
1671 return;
1672}
1673
1674void
a1ac18c4 1675rtadv_init (void)
718e3744 1676{
1677 int sock;
1678
1679 sock = rtadv_make_socket ();
1680 if (sock < 0)
1681 return;
1682
1683 rtadv = rtadv_new ();
1684 rtadv->sock = sock;
1685
1686 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1687 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
718e3744 1688 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
7cee1bb1 1689 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
718e3744 1690 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
4afa50b3
DO
1691 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_val_cmd);
1692 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_msec_val_cmd);
718e3744 1693 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1694 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
4afa50b3 1695 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_val_cmd);
718e3744 1696 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1697 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
4afa50b3 1698 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_val_cmd);
718e3744 1699 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1700 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1701 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1702 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
7cee1bb1 1703 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1704 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1705 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1706 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
4afa50b3 1707 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_val_cmd);
7cee1bb1 1708 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1709 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
4afa50b3 1710 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_val_cmd);
7cee1bb1 1711 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1712 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
3e31cded 1713 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
7cee1bb1 1714 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1715 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
3e31cded 1716 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1717 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1718 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
7cee1bb1 1719 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
3e31cded 1720 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1721 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1722 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1723 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1724 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
7cee1bb1 1725 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
3e31cded 1726 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1727 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
b60668d0
CC
1728 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1729 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
4afa50b3 1730 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_val_cmd);
6ae93c05
DO
1731 install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
1732 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
1733 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
718e3744 1734}
1735
a1ac18c4 1736static int
718e3744 1737if_join_all_router (int sock, struct interface *ifp)
1738{
1739 int ret;
1740
1741 struct ipv6_mreq mreq;
1742
1743 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1744 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1745 mreq.ipv6mr_interface = ifp->ifindex;
1746
1747 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1748 (char *) &mreq, sizeof mreq);
1749 if (ret < 0)
6099b3b5 1750 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
718e3744 1751
1752 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1753
1754 return 0;
1755}
1756
a1ac18c4 1757static int
718e3744 1758if_leave_all_router (int sock, struct interface *ifp)
1759{
1760 int ret;
1761
1762 struct ipv6_mreq mreq;
1763
1764 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1765 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1766 mreq.ipv6mr_interface = ifp->ifindex;
1767
1768 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1769 (char *) &mreq, sizeof mreq);
1770 if (ret < 0)
6099b3b5 1771 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
718e3744 1772
1773 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1774
1775 return 0;
1776}
1777
1778#else
1779void
a1ac18c4 1780rtadv_init (void)
718e3744 1781{
1782 /* Empty.*/;
1783}
1784#endif /* RTADV && HAVE_IPV6 */