blob: 0bcdafb08494ab776ca733224dfb0acbe088d883 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Router advertisement
vincent7cee1bb2005-03-25 13:08:53 +00002 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
paul718e3742002-12-13 20:15:29 +00003 * 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"
pauledd7c242003-06-04 13:59:38 +000033#include "privs.h"
paul718e3742002-12-13 20:15:29 +000034
35#include "zebra/interface.h"
36#include "zebra/rtadv.h"
37#include "zebra/debug.h"
paul537d8ea2003-08-27 06:45:32 +000038#include "zebra/rib.h"
gdt4b5e1352003-12-03 17:54:34 +000039#include "zebra/zserv.h"
paul718e3742002-12-13 20:15:29 +000040
pauledd7c242003-06-04 13:59:38 +000041extern struct zebra_privs_t zserv_privs;
42
paul718e3742002-12-13 20:15:29 +000043#if defined (HAVE_IPV6) && defined (RTADV)
44
hassofa2b17e2004-03-04 17:45:00 +000045#ifdef OPEN_BSD
46#include <netinet/icmp6.h>
47#endif
48
paul718e3742002-12-13 20:15:29 +000049/* 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
paulb21b19c2003-06-15 01:28:29 +000060extern struct zebra_t zebrad;
61
vincent7cee1bb2005-03-25 13:08:53 +000062enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
63 RTADV_TIMER_MSEC, RTADV_READ};
paul718e3742002-12-13 20:15:29 +000064
paula1ac18c2005-06-28 17:17:12 +000065static void rtadv_event (enum rtadv_event, int);
paul718e3742002-12-13 20:15:29 +000066
paula1ac18c2005-06-28 17:17:12 +000067static int if_join_all_router (int, struct interface *);
68static int if_leave_all_router (int, struct interface *);
paul718e3742002-12-13 20:15:29 +000069
70/* Structure which hold status of router advertisement. */
71struct rtadv
72{
73 int sock;
74
75 int adv_if_count;
vincent7cee1bb2005-03-25 13:08:53 +000076 int adv_msec_if_count;
paul718e3742002-12-13 20:15:29 +000077
78 struct thread *ra_read;
79 struct thread *ra_timer;
80};
81
82struct rtadv *rtadv = NULL;
83
paula1ac18c2005-06-28 17:17:12 +000084static struct rtadv *
85rtadv_new (void)
paul718e3742002-12-13 20:15:29 +000086{
Stephen Hemminger393deb92008-08-18 14:13:29 -070087 return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));
paul718e3742002-12-13 20:15:29 +000088}
89
paula1ac18c2005-06-28 17:17:12 +000090static void
paul718e3742002-12-13 20:15:29 +000091rtadv_free (struct rtadv *rtadv)
92{
93 XFREE (MTYPE_TMP, rtadv);
94}
95
paula1ac18c2005-06-28 17:17:12 +000096static int
paul718e3742002-12-13 20:15:29 +000097rtadv_recv_packet (int sock, u_char *buf, int buflen,
98 struct sockaddr_in6 *from, unsigned int *ifindex,
99 int *hoplimit)
100{
101 int ret;
102 struct msghdr msg;
103 struct iovec iov;
104 struct cmsghdr *cmsgptr;
105 struct in6_addr dst;
106
107 char adata[1024];
108
109 /* Fill in message and iovec. */
110 msg.msg_name = (void *) from;
111 msg.msg_namelen = sizeof (struct sockaddr_in6);
112 msg.msg_iov = &iov;
113 msg.msg_iovlen = 1;
114 msg.msg_control = (void *) adata;
115 msg.msg_controllen = sizeof adata;
116 iov.iov_base = buf;
117 iov.iov_len = buflen;
118
119 /* If recvmsg fail return minus value. */
120 ret = recvmsg (sock, &msg, 0);
121 if (ret < 0)
122 return ret;
123
ajsb99760a2005-01-04 16:24:43 +0000124 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
paul718e3742002-12-13 20:15:29 +0000125 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
126 {
127 /* I want interface index which this packet comes from. */
128 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
129 cmsgptr->cmsg_type == IPV6_PKTINFO)
130 {
131 struct in6_pktinfo *ptr;
132
133 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
134 *ifindex = ptr->ipi6_ifindex;
135 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
136 }
137
138 /* Incoming packet's hop limit. */
139 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
140 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
141 *hoplimit = *((int *) CMSG_DATA (cmsgptr));
142 }
143 return ret;
144}
145
146#define RTADV_MSG_SIZE 4096
147
148/* Send router advertisement packet. */
paula1ac18c2005-06-28 17:17:12 +0000149static void
paul718e3742002-12-13 20:15:29 +0000150rtadv_send_packet (int sock, struct interface *ifp)
151{
152 struct msghdr msg;
153 struct iovec iov;
154 struct cmsghdr *cmsgptr;
155 struct in6_pktinfo *pkt;
156 struct sockaddr_in6 addr;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000157#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000158 struct sockaddr_dl *sdl;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000159#endif /* HAVE_STRUCT_SOCKADDR_DL */
gdt57492d52004-08-11 18:06:38 +0000160 static void *adata = NULL;
paul718e3742002-12-13 20:15:29 +0000161 unsigned char buf[RTADV_MSG_SIZE];
162 struct nd_router_advert *rtadv;
163 int ret;
164 int len = 0;
165 struct zebra_if *zif;
paul1eb8ef22005-04-07 07:30:20 +0000166 struct rtadv_prefix *rprefix;
paul718e3742002-12-13 20:15:29 +0000167 u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
hasso52dc7ee2004-09-23 19:18:23 +0000168 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000169
gdt57492d52004-08-11 18:06:38 +0000170 /*
171 * Allocate control message bufffer. This is dynamic because
172 * CMSG_SPACE is not guaranteed not to call a function. Note that
173 * the size will be different on different architectures due to
174 * differing alignment rules.
175 */
176 if (adata == NULL)
177 {
178 /* XXX Free on shutdown. */
179 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
180
181 if (adata == NULL)
182 zlog_err("rtadv_send_packet: can't malloc control data\n");
183 }
184
paul718e3742002-12-13 20:15:29 +0000185 /* Logging of packet. */
186 if (IS_ZEBRA_DEBUG_PACKET)
ajsb6178002004-12-07 21:12:56 +0000187 zlog_debug ("Router advertisement send to %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000188
189 /* Fill in sockaddr_in6. */
190 memset (&addr, 0, sizeof (struct sockaddr_in6));
191 addr.sin6_family = AF_INET6;
192#ifdef SIN6_LEN
193 addr.sin6_len = sizeof (struct sockaddr_in6);
194#endif /* SIN6_LEN */
195 addr.sin6_port = htons (IPPROTO_ICMPV6);
196 memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
197
198 /* Fetch interface information. */
199 zif = ifp->info;
200
201 /* Make router advertisement message. */
202 rtadv = (struct nd_router_advert *) buf;
203
204 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
205 rtadv->nd_ra_code = 0;
206 rtadv->nd_ra_cksum = 0;
207
208 rtadv->nd_ra_curhoplimit = 64;
Chris Caputob60668d2009-05-03 04:40:57 +0000209
210 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
211 rtadv->nd_ra_flags_reserved =
212 zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
213 rtadv->nd_ra_flags_reserved <<= 3;
214
paul718e3742002-12-13 20:15:29 +0000215 if (zif->rtadv.AdvManagedFlag)
216 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
217 if (zif->rtadv.AdvOtherConfigFlag)
218 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
vincent7cee1bb2005-03-25 13:08:53 +0000219 if (zif->rtadv.AdvHomeAgentFlag)
220 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
paul718e3742002-12-13 20:15:29 +0000221 rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
222 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
223 rtadv->nd_ra_retransmit = htonl (0);
224
225 len = sizeof (struct nd_router_advert);
226
vincent7cee1bb2005-03-25 13:08:53 +0000227 if (zif->rtadv.AdvHomeAgentFlag)
228 {
229 struct nd_opt_homeagent_info *ndopt_hai =
230 (struct nd_opt_homeagent_info *)(buf + len);
231 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
232 ndopt_hai->nd_opt_hai_len = 1;
233 ndopt_hai->nd_opt_hai_reserved = 0;
234 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
235 ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);
236 len += sizeof(struct nd_opt_homeagent_info);
237 }
238
239 if (zif->rtadv.AdvIntervalOption)
240 {
241 struct nd_opt_adv_interval *ndopt_adv =
242 (struct nd_opt_adv_interval *)(buf + len);
243 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
244 ndopt_adv->nd_opt_ai_len = 1;
245 ndopt_adv->nd_opt_ai_reserved = 0;
246 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
247 len += sizeof(struct nd_opt_adv_interval);
248 }
249
paul718e3742002-12-13 20:15:29 +0000250 /* Fill in prefix. */
paul1eb8ef22005-04-07 07:30:20 +0000251 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +0000252 {
253 struct nd_opt_prefix_info *pinfo;
paul718e3742002-12-13 20:15:29 +0000254
255 pinfo = (struct nd_opt_prefix_info *) (buf + len);
256
257 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
258 pinfo->nd_opt_pi_len = 4;
259 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
260
261 pinfo->nd_opt_pi_flags_reserved = 0;
262 if (rprefix->AdvOnLinkFlag)
263 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
264 if (rprefix->AdvAutonomousFlag)
265 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
vincent7cee1bb2005-03-25 13:08:53 +0000266 if (rprefix->AdvRouterAddressFlag)
267 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
paul718e3742002-12-13 20:15:29 +0000268
269 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
270 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
271 pinfo->nd_opt_pi_reserved2 = 0;
272
273 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
274 sizeof (struct in6_addr));
275
276#ifdef DEBUG
277 {
278 u_char buf[INET6_ADDRSTRLEN];
279
ajsb6178002004-12-07 21:12:56 +0000280 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
hasso3e31cde2004-05-18 11:58:59 +0000281 buf, INET6_ADDRSTRLEN));
paul718e3742002-12-13 20:15:29 +0000282
283 }
284#endif /* DEBUG */
285
286 len += sizeof (struct nd_opt_prefix_info);
287 }
288
289 /* Hardware address. */
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000290#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000291 sdl = &ifp->sdl;
292 if (sdl != NULL && sdl->sdl_alen != 0)
293 {
294 buf[len++] = ND_OPT_SOURCE_LINKADDR;
David Ward50adf782009-08-31 10:42:06 -0400295
296 /* Option length should be rounded up to next octet if
297 the link address does not end on an octet boundary. */
298 buf[len++] = (sdl->sdl_alen + 9) >> 3;
paul718e3742002-12-13 20:15:29 +0000299
300 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
301 len += sdl->sdl_alen;
David Ward50adf782009-08-31 10:42:06 -0400302
303 /* Pad option to end on an octet boundary. */
304 memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
305 len += -(sdl->sdl_alen + 2) & 0x7;
paul718e3742002-12-13 20:15:29 +0000306 }
307#else
308 if (ifp->hw_addr_len != 0)
309 {
310 buf[len++] = ND_OPT_SOURCE_LINKADDR;
David Ward50adf782009-08-31 10:42:06 -0400311
312 /* Option length should be rounded up to next octet if
313 the link address does not end on an octet boundary. */
314 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
paul718e3742002-12-13 20:15:29 +0000315
316 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
317 len += ifp->hw_addr_len;
David Ward50adf782009-08-31 10:42:06 -0400318
319 /* Pad option to end on an octet boundary. */
320 memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
321 len += -(ifp->hw_addr_len + 2) & 0x7;
paul718e3742002-12-13 20:15:29 +0000322 }
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000323#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000324
325 msg.msg_name = (void *) &addr;
326 msg.msg_namelen = sizeof (struct sockaddr_in6);
327 msg.msg_iov = &iov;
328 msg.msg_iovlen = 1;
329 msg.msg_control = (void *) adata;
gdtf841e022004-08-11 19:20:01 +0000330 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
gdt57492d52004-08-11 18:06:38 +0000331 msg.msg_flags = 0;
paul718e3742002-12-13 20:15:29 +0000332 iov.iov_base = buf;
333 iov.iov_len = len;
334
ajsb99760a2005-01-04 16:24:43 +0000335 cmsgptr = ZCMSG_FIRSTHDR(&msg);
gdt57492d52004-08-11 18:06:38 +0000336 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
paul718e3742002-12-13 20:15:29 +0000337 cmsgptr->cmsg_level = IPPROTO_IPV6;
338 cmsgptr->cmsg_type = IPV6_PKTINFO;
gdt80893812004-08-11 15:58:00 +0000339
paul718e3742002-12-13 20:15:29 +0000340 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
341 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
342 pkt->ipi6_ifindex = ifp->ifindex;
343
344 ret = sendmsg (sock, &msg, 0);
gdt9ccabd12004-01-06 18:23:02 +0000345 if (ret < 0)
346 {
347 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
ajs6099b3b2004-11-20 02:06:59 +0000348 errno, safe_strerror(errno));
gdt9ccabd12004-01-06 18:23:02 +0000349 }
paul718e3742002-12-13 20:15:29 +0000350}
351
paula1ac18c2005-06-28 17:17:12 +0000352static int
paul718e3742002-12-13 20:15:29 +0000353rtadv_timer (struct thread *thread)
354{
paul1eb8ef22005-04-07 07:30:20 +0000355 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000356 struct interface *ifp;
357 struct zebra_if *zif;
vincent7cee1bb2005-03-25 13:08:53 +0000358 int period;
paul718e3742002-12-13 20:15:29 +0000359
360 rtadv->ra_timer = NULL;
vincent7cee1bb2005-03-25 13:08:53 +0000361 if (rtadv->adv_msec_if_count == 0)
362 {
363 period = 1000; /* 1 s */
364 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
365 }
366 else
367 {
368 period = 10; /* 10 ms */
369 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
370 }
paul718e3742002-12-13 20:15:29 +0000371
paul1eb8ef22005-04-07 07:30:20 +0000372 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
paul718e3742002-12-13 20:15:29 +0000373 {
paul718e3742002-12-13 20:15:29 +0000374 if (if_is_loopback (ifp))
375 continue;
376
377 zif = ifp->info;
378
379 if (zif->rtadv.AdvSendAdvertisements)
vincent7cee1bb2005-03-25 13:08:53 +0000380 {
381 zif->rtadv.AdvIntervalTimer -= period;
382 if (zif->rtadv.AdvIntervalTimer <= 0)
383 {
384 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
385 rtadv_send_packet (rtadv->sock, ifp);
386 }
387 }
paul718e3742002-12-13 20:15:29 +0000388 }
389 return 0;
390}
391
paula1ac18c2005-06-28 17:17:12 +0000392static void
paul718e3742002-12-13 20:15:29 +0000393rtadv_process_solicit (struct interface *ifp)
394{
395 zlog_info ("Router solicitation received on %s", ifp->name);
396
397 rtadv_send_packet (rtadv->sock, ifp);
398}
399
paula1ac18c2005-06-28 17:17:12 +0000400static void
401rtadv_process_advert (void)
paul718e3742002-12-13 20:15:29 +0000402{
403 zlog_info ("Router advertisement received");
404}
405
paula1ac18c2005-06-28 17:17:12 +0000406static void
hassofce954f2004-10-07 20:29:24 +0000407rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
paul718e3742002-12-13 20:15:29 +0000408{
409 struct icmp6_hdr *icmph;
410 struct interface *ifp;
411 struct zebra_if *zif;
412
413 /* Interface search. */
414 ifp = if_lookup_by_index (ifindex);
415 if (ifp == NULL)
416 {
417 zlog_warn ("Unknown interface index: %d", ifindex);
418 return;
419 }
420
421 if (if_is_loopback (ifp))
422 return;
423
424 /* Check interface configuration. */
425 zif = ifp->info;
426 if (! zif->rtadv.AdvSendAdvertisements)
427 return;
428
429 /* ICMP message length check. */
430 if (len < sizeof (struct icmp6_hdr))
431 {
432 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
433 return;
434 }
435
436 icmph = (struct icmp6_hdr *) buf;
437
438 /* ICMP message type check. */
439 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
440 icmph->icmp6_type != ND_ROUTER_ADVERT)
441 {
442 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
443 return;
444 }
445
446 /* Hoplimit check. */
447 if (hoplimit >= 0 && hoplimit != 255)
448 {
449 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
450 hoplimit);
451 return;
452 }
453
454 /* Check ICMP message type. */
455 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
456 rtadv_process_solicit (ifp);
457 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
458 rtadv_process_advert ();
459
460 return;
461}
462
paula1ac18c2005-06-28 17:17:12 +0000463static int
paul718e3742002-12-13 20:15:29 +0000464rtadv_read (struct thread *thread)
465{
466 int sock;
467 int len;
468 u_char buf[RTADV_MSG_SIZE];
469 struct sockaddr_in6 from;
470 unsigned int ifindex;
471 int hoplimit = -1;
472
473 sock = THREAD_FD (thread);
474 rtadv->ra_read = NULL;
475
476 /* Register myself. */
477 rtadv_event (RTADV_READ, sock);
478
479 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
480
481 if (len < 0)
482 {
ajs6099b3b2004-11-20 02:06:59 +0000483 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000484 return len;
485 }
486
hassofce954f2004-10-07 20:29:24 +0000487 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
paul718e3742002-12-13 20:15:29 +0000488
489 return 0;
490}
491
paula1ac18c2005-06-28 17:17:12 +0000492static int
paul718e3742002-12-13 20:15:29 +0000493rtadv_make_socket (void)
494{
495 int sock;
496 int ret;
497 struct icmp6_filter filter;
498
pauledd7c242003-06-04 13:59:38 +0000499 if ( zserv_privs.change (ZPRIVS_RAISE) )
500 zlog_err ("rtadv_make_socket: could not raise privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000501 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000502
paul718e3742002-12-13 20:15:29 +0000503 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
504
pauledd7c242003-06-04 13:59:38 +0000505 if ( zserv_privs.change (ZPRIVS_LOWER) )
506 zlog_err ("rtadv_make_socket: could not lower privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000507 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000508
paul718e3742002-12-13 20:15:29 +0000509 /* When we can't make ICMPV6 socket simply back. Router
510 advertisement feature will not be supported. */
511 if (sock < 0)
512 return -1;
513
514 ret = setsockopt_ipv6_pktinfo (sock, 1);
515 if (ret < 0)
516 return ret;
paul718e3742002-12-13 20:15:29 +0000517 ret = setsockopt_ipv6_multicast_loop (sock, 0);
518 if (ret < 0)
519 return ret;
520 ret = setsockopt_ipv6_unicast_hops (sock, 255);
521 if (ret < 0)
522 return ret;
523 ret = setsockopt_ipv6_multicast_hops (sock, 255);
524 if (ret < 0)
525 return ret;
526 ret = setsockopt_ipv6_hoplimit (sock, 1);
527 if (ret < 0)
528 return ret;
529
530 ICMP6_FILTER_SETBLOCKALL(&filter);
531 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
532 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
533
534 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
535 sizeof (struct icmp6_filter));
536 if (ret < 0)
537 {
ajs6099b3b2004-11-20 02:06:59 +0000538 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000539 return ret;
540 }
541
542 return sock;
543}
544
paula1ac18c2005-06-28 17:17:12 +0000545static struct rtadv_prefix *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800546rtadv_prefix_new (void)
paul718e3742002-12-13 20:15:29 +0000547{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700548 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
paul718e3742002-12-13 20:15:29 +0000549}
550
paula1ac18c2005-06-28 17:17:12 +0000551static void
paul718e3742002-12-13 20:15:29 +0000552rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
553{
554 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
555}
556
paula1ac18c2005-06-28 17:17:12 +0000557static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000558rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000559{
hasso52dc7ee2004-09-23 19:18:23 +0000560 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000561 struct rtadv_prefix *rprefix;
562
paul1eb8ef22005-04-07 07:30:20 +0000563 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
564 if (prefix_same (&rprefix->prefix, p))
565 return rprefix;
paul718e3742002-12-13 20:15:29 +0000566 return NULL;
567}
568
paula1ac18c2005-06-28 17:17:12 +0000569static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000570rtadv_prefix_get (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000571{
572 struct rtadv_prefix *rprefix;
573
574 rprefix = rtadv_prefix_lookup (rplist, p);
575 if (rprefix)
576 return rprefix;
577
578 rprefix = rtadv_prefix_new ();
579 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
580 listnode_add (rplist, rprefix);
581
582 return rprefix;
583}
584
paula1ac18c2005-06-28 17:17:12 +0000585static void
paul718e3742002-12-13 20:15:29 +0000586rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
587{
588 struct rtadv_prefix *rprefix;
589
590 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
591
592 /* Set parameters. */
593 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
594 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
595 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
596 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
vincent7cee1bb2005-03-25 13:08:53 +0000597 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
paul718e3742002-12-13 20:15:29 +0000598}
599
paula1ac18c2005-06-28 17:17:12 +0000600static int
paul718e3742002-12-13 20:15:29 +0000601rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
602{
603 struct rtadv_prefix *rprefix;
604
605 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
606 if (rprefix != NULL)
607 {
608 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
609 rtadv_prefix_free (rprefix);
610 return 1;
611 }
612 else
613 return 0;
614}
615
616DEFUN (ipv6_nd_suppress_ra,
617 ipv6_nd_suppress_ra_cmd,
618 "ipv6 nd suppress-ra",
hasso3e31cde2004-05-18 11:58:59 +0000619 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000620 "Neighbor discovery\n"
621 "Suppress Router Advertisement\n")
622{
623 struct interface *ifp;
624 struct zebra_if *zif;
625
626 ifp = vty->index;
627 zif = ifp->info;
628
629 if (if_is_loopback (ifp))
630 {
631 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
632 return CMD_WARNING;
633 }
634
635 if (zif->rtadv.AdvSendAdvertisements)
636 {
637 zif->rtadv.AdvSendAdvertisements = 0;
638 zif->rtadv.AdvIntervalTimer = 0;
639 rtadv->adv_if_count--;
640
641 if_leave_all_router (rtadv->sock, ifp);
642
643 if (rtadv->adv_if_count == 0)
644 rtadv_event (RTADV_STOP, 0);
645 }
646
647 return CMD_SUCCESS;
648}
649
paul718e3742002-12-13 20:15:29 +0000650DEFUN (no_ipv6_nd_suppress_ra,
651 no_ipv6_nd_suppress_ra_cmd,
652 "no ipv6 nd suppress-ra",
653 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000654 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000655 "Neighbor discovery\n"
656 "Suppress Router Advertisement\n")
657{
658 struct interface *ifp;
659 struct zebra_if *zif;
660
661 ifp = vty->index;
662 zif = ifp->info;
663
664 if (if_is_loopback (ifp))
665 {
666 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
667 return CMD_WARNING;
668 }
669
670 if (! zif->rtadv.AdvSendAdvertisements)
671 {
672 zif->rtadv.AdvSendAdvertisements = 1;
673 zif->rtadv.AdvIntervalTimer = 0;
674 rtadv->adv_if_count++;
675
676 if_join_all_router (rtadv->sock, ifp);
677
678 if (rtadv->adv_if_count == 1)
679 rtadv_event (RTADV_START, rtadv->sock);
680 }
681
682 return CMD_SUCCESS;
683}
684
vincent7cee1bb2005-03-25 13:08:53 +0000685DEFUN (ipv6_nd_ra_interval_msec,
686 ipv6_nd_ra_interval_msec_cmd,
687 "ipv6 nd ra-interval msec MILLISECONDS",
688 "Interface IPv6 config commands\n"
689 "Neighbor discovery\n"
690 "Router Advertisement interval\n"
691 "Router Advertisement interval in milliseconds\n")
692{
693 int interval;
694 struct interface *ifp;
695 struct zebra_if *zif;
696
697 ifp = (struct interface *) vty->index;
698 zif = ifp->info;
699
700 interval = atoi (argv[0]);
701
702 if (interval <= 0)
703 {
704 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
705 return CMD_WARNING;
706 }
707
708 if (zif->rtadv.MaxRtrAdvInterval % 1000)
709 rtadv->adv_msec_if_count--;
710
711 if (interval % 1000)
712 rtadv->adv_msec_if_count++;
713
714 zif->rtadv.MaxRtrAdvInterval = interval;
715 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
716 zif->rtadv.AdvIntervalTimer = 0;
717
718 return CMD_SUCCESS;
719}
720
paul718e3742002-12-13 20:15:29 +0000721DEFUN (ipv6_nd_ra_interval,
722 ipv6_nd_ra_interval_cmd,
723 "ipv6 nd ra-interval SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000724 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000725 "Neighbor discovery\n"
726 "Router Advertisement interval\n"
727 "Router Advertisement interval in seconds\n")
728{
729 int interval;
730 struct interface *ifp;
731 struct zebra_if *zif;
732
733 ifp = (struct interface *) vty->index;
734 zif = ifp->info;
735
736 interval = atoi (argv[0]);
737
vincent7cee1bb2005-03-25 13:08:53 +0000738 if (interval <= 0)
paul718e3742002-12-13 20:15:29 +0000739 {
740 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
741 return CMD_WARNING;
742 }
743
vincent7cee1bb2005-03-25 13:08:53 +0000744 if (zif->rtadv.MaxRtrAdvInterval % 1000)
745 rtadv->adv_msec_if_count--;
746
747 /* convert to milliseconds */
748 interval = interval * 1000;
749
paul718e3742002-12-13 20:15:29 +0000750 zif->rtadv.MaxRtrAdvInterval = interval;
751 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
752 zif->rtadv.AdvIntervalTimer = 0;
753
754 return CMD_SUCCESS;
755}
756
757DEFUN (no_ipv6_nd_ra_interval,
758 no_ipv6_nd_ra_interval_cmd,
759 "no ipv6 nd ra-interval",
760 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000761 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000762 "Neighbor discovery\n"
763 "Router Advertisement interval\n")
764{
765 struct interface *ifp;
766 struct zebra_if *zif;
767
768 ifp = (struct interface *) vty->index;
769 zif = ifp->info;
770
vincent7cee1bb2005-03-25 13:08:53 +0000771 if (zif->rtadv.MaxRtrAdvInterval % 1000)
772 rtadv->adv_msec_if_count--;
773
paul718e3742002-12-13 20:15:29 +0000774 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
775 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
776 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
777
778 return CMD_SUCCESS;
779}
780
781DEFUN (ipv6_nd_ra_lifetime,
782 ipv6_nd_ra_lifetime_cmd,
783 "ipv6 nd ra-lifetime SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000784 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000785 "Neighbor discovery\n"
786 "Router lifetime\n"
787 "Router lifetime in seconds\n")
788{
789 int lifetime;
790 struct interface *ifp;
791 struct zebra_if *zif;
792
793 ifp = (struct interface *) vty->index;
794 zif = ifp->info;
795
796 lifetime = atoi (argv[0]);
797
798 if (lifetime < 0 || lifetime > 0xffff)
799 {
800 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
801 return CMD_WARNING;
802 }
803
804 zif->rtadv.AdvDefaultLifetime = lifetime;
805
806 return CMD_SUCCESS;
807}
808
809DEFUN (no_ipv6_nd_ra_lifetime,
810 no_ipv6_nd_ra_lifetime_cmd,
811 "no ipv6 nd ra-lifetime",
812 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000813 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000814 "Neighbor discovery\n"
815 "Router lifetime\n")
816{
817 struct interface *ifp;
818 struct zebra_if *zif;
819
820 ifp = (struct interface *) vty->index;
821 zif = ifp->info;
822
823 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
824
825 return CMD_SUCCESS;
826}
827
828DEFUN (ipv6_nd_reachable_time,
829 ipv6_nd_reachable_time_cmd,
830 "ipv6 nd reachable-time MILLISECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000831 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000832 "Neighbor discovery\n"
833 "Reachable time\n"
834 "Reachable time in milliseconds\n")
835{
836 u_int32_t rtime;
837 struct interface *ifp;
838 struct zebra_if *zif;
839
840 ifp = (struct interface *) vty->index;
841 zif = ifp->info;
842
843 rtime = (u_int32_t) atol (argv[0]);
844
845 if (rtime > RTADV_MAX_REACHABLE_TIME)
846 {
847 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
848 return CMD_WARNING;
849 }
850
851 zif->rtadv.AdvReachableTime = rtime;
852
853 return CMD_SUCCESS;
854}
855
856DEFUN (no_ipv6_nd_reachable_time,
857 no_ipv6_nd_reachable_time_cmd,
858 "no ipv6 nd reachable-time",
859 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000860 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000861 "Neighbor discovery\n"
862 "Reachable time\n")
863{
864 struct interface *ifp;
865 struct zebra_if *zif;
866
867 ifp = (struct interface *) vty->index;
868 zif = ifp->info;
869
870 zif->rtadv.AdvReachableTime = 0;
871
872 return CMD_SUCCESS;
873}
874
vincent7cee1bb2005-03-25 13:08:53 +0000875DEFUN (ipv6_nd_homeagent_preference,
876 ipv6_nd_homeagent_preference_cmd,
877 "ipv6 nd home-agent-preference PREFERENCE",
878 "Interface IPv6 config commands\n"
879 "Neighbor discovery\n"
880 "Home Agent preference\n"
881 "Home Agent preference value 0..65535\n")
882{
883 u_int32_t hapref;
884 struct interface *ifp;
885 struct zebra_if *zif;
886
887 ifp = (struct interface *) vty->index;
888 zif = ifp->info;
889
890 hapref = (u_int32_t) atol (argv[0]);
891
892 if (hapref > 65535)
893 {
894 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
895 return CMD_WARNING;
896 }
897
898 zif->rtadv.HomeAgentPreference = hapref;
899
900 return CMD_SUCCESS;
901}
902
903DEFUN (no_ipv6_nd_homeagent_preference,
904 no_ipv6_nd_homeagent_preference_cmd,
905 "no ipv6 nd home-agent-preference",
906 NO_STR
907 "Interface IPv6 config commands\n"
908 "Neighbor discovery\n"
909 "Home Agent preference\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.HomeAgentPreference = 0;
918
919 return CMD_SUCCESS;
920}
921
922DEFUN (ipv6_nd_homeagent_lifetime,
923 ipv6_nd_homeagent_lifetime_cmd,
924 "ipv6 nd home-agent-lifetime SECONDS",
925 "Interface IPv6 config commands\n"
926 "Neighbor discovery\n"
927 "Home Agent lifetime\n"
928 "Home Agent lifetime in seconds\n")
929{
930 u_int32_t ha_ltime;
931 struct interface *ifp;
932 struct zebra_if *zif;
933
934 ifp = (struct interface *) vty->index;
935 zif = ifp->info;
936
937 ha_ltime = (u_int32_t) atol (argv[0]);
938
939 if (ha_ltime > RTADV_MAX_HALIFETIME)
940 {
941 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
942 return CMD_WARNING;
943 }
944
945 zif->rtadv.HomeAgentLifetime = ha_ltime;
946
947 return CMD_SUCCESS;
948}
949
950DEFUN (no_ipv6_nd_homeagent_lifetime,
951 no_ipv6_nd_homeagent_lifetime_cmd,
952 "no ipv6 nd home-agent-lifetime",
953 NO_STR
954 "Interface IPv6 config commands\n"
955 "Neighbor discovery\n"
956 "Home Agent lifetime\n")
957{
958 struct interface *ifp;
959 struct zebra_if *zif;
960
961 ifp = (struct interface *) vty->index;
962 zif = ifp->info;
963
964 zif->rtadv.HomeAgentLifetime = 0;
965
966 return CMD_SUCCESS;
967}
968
paul718e3742002-12-13 20:15:29 +0000969DEFUN (ipv6_nd_managed_config_flag,
970 ipv6_nd_managed_config_flag_cmd,
971 "ipv6 nd managed-config-flag",
hasso3e31cde2004-05-18 11:58:59 +0000972 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000973 "Neighbor discovery\n"
974 "Managed address configuration flag\n")
975{
976 struct interface *ifp;
977 struct zebra_if *zif;
978
979 ifp = (struct interface *) vty->index;
980 zif = ifp->info;
981
982 zif->rtadv.AdvManagedFlag = 1;
983
984 return CMD_SUCCESS;
985}
986
987DEFUN (no_ipv6_nd_managed_config_flag,
988 no_ipv6_nd_managed_config_flag_cmd,
989 "no ipv6 nd managed-config-flag",
990 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000991 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000992 "Neighbor discovery\n"
993 "Managed address configuration flag\n")
994{
995 struct interface *ifp;
996 struct zebra_if *zif;
997
998 ifp = (struct interface *) vty->index;
999 zif = ifp->info;
1000
1001 zif->rtadv.AdvManagedFlag = 0;
1002
1003 return CMD_SUCCESS;
1004}
1005
vincent7cee1bb2005-03-25 13:08:53 +00001006DEFUN (ipv6_nd_homeagent_config_flag,
1007 ipv6_nd_homeagent_config_flag_cmd,
1008 "ipv6 nd home-agent-config-flag",
1009 "Interface IPv6 config commands\n"
1010 "Neighbor discovery\n"
1011 "Home Agent configuration flag\n")
1012{
1013 struct interface *ifp;
1014 struct zebra_if *zif;
1015
1016 ifp = (struct interface *) vty->index;
1017 zif = ifp->info;
1018
1019 zif->rtadv.AdvHomeAgentFlag = 1;
1020
1021 return CMD_SUCCESS;
1022}
1023
1024DEFUN (no_ipv6_nd_homeagent_config_flag,
1025 no_ipv6_nd_homeagent_config_flag_cmd,
1026 "no ipv6 nd home-agent-config-flag",
1027 NO_STR
1028 "Interface IPv6 config commands\n"
1029 "Neighbor discovery\n"
1030 "Home Agent configuration flag\n")
1031{
1032 struct interface *ifp;
1033 struct zebra_if *zif;
1034
1035 ifp = (struct interface *) vty->index;
1036 zif = ifp->info;
1037
1038 zif->rtadv.AdvHomeAgentFlag = 0;
1039
1040 return CMD_SUCCESS;
1041}
1042
1043DEFUN (ipv6_nd_adv_interval_config_option,
1044 ipv6_nd_adv_interval_config_option_cmd,
1045 "ipv6 nd adv-interval-option",
1046 "Interface IPv6 config commands\n"
1047 "Neighbor discovery\n"
1048 "Advertisement Interval Option\n")
1049{
1050 struct interface *ifp;
1051 struct zebra_if *zif;
1052
1053 ifp = (struct interface *) vty->index;
1054 zif = ifp->info;
1055
1056 zif->rtadv.AdvIntervalOption = 1;
1057
1058 return CMD_SUCCESS;
1059}
1060
1061DEFUN (no_ipv6_nd_adv_interval_config_option,
1062 no_ipv6_nd_adv_interval_config_option_cmd,
1063 "no ipv6 nd adv-interval-option",
1064 NO_STR
1065 "Interface IPv6 config commands\n"
1066 "Neighbor discovery\n"
1067 "Advertisement Interval Option\n")
1068{
1069 struct interface *ifp;
1070 struct zebra_if *zif;
1071
1072 ifp = (struct interface *) vty->index;
1073 zif = ifp->info;
1074
1075 zif->rtadv.AdvIntervalOption = 0;
1076
1077 return CMD_SUCCESS;
1078}
1079
paul718e3742002-12-13 20:15:29 +00001080DEFUN (ipv6_nd_other_config_flag,
1081 ipv6_nd_other_config_flag_cmd,
1082 "ipv6 nd other-config-flag",
hasso3e31cde2004-05-18 11:58:59 +00001083 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001084 "Neighbor discovery\n"
1085 "Other statefull configuration flag\n")
1086{
1087 struct interface *ifp;
1088 struct zebra_if *zif;
1089
1090 ifp = (struct interface *) vty->index;
1091 zif = ifp->info;
1092
1093 zif->rtadv.AdvOtherConfigFlag = 1;
1094
1095 return CMD_SUCCESS;
1096}
1097
1098DEFUN (no_ipv6_nd_other_config_flag,
1099 no_ipv6_nd_other_config_flag_cmd,
1100 "no ipv6 nd other-config-flag",
1101 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001102 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001103 "Neighbor discovery\n"
1104 "Other statefull configuration flag\n")
1105{
1106 struct interface *ifp;
1107 struct zebra_if *zif;
1108
1109 ifp = (struct interface *) vty->index;
1110 zif = ifp->info;
1111
1112 zif->rtadv.AdvOtherConfigFlag = 0;
1113
1114 return CMD_SUCCESS;
1115}
1116
hasso3e31cde2004-05-18 11:58:59 +00001117DEFUN (ipv6_nd_prefix,
1118 ipv6_nd_prefix_cmd,
1119 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
vincent7cee1bb2005-03-25 13:08:53 +00001120 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
hasso3e31cde2004-05-18 11:58:59 +00001121 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001122 "Neighbor discovery\n"
1123 "Prefix information\n"
1124 "IPv6 prefix\n"
1125 "Valid lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001126 "Infinite valid lifetime\n"
paul718e3742002-12-13 20:15:29 +00001127 "Preferred lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001128 "Infinite preferred lifetime\n"
1129 "Do not use prefix for onlink determination\n"
vincent7cee1bb2005-03-25 13:08:53 +00001130 "Do not use prefix for autoconfiguration\n"
1131 "Set Router Address flag\n")
paul718e3742002-12-13 20:15:29 +00001132{
1133 int i;
1134 int ret;
hasso3e31cde2004-05-18 11:58:59 +00001135 int cursor = 1;
paul718e3742002-12-13 20:15:29 +00001136 struct interface *ifp;
1137 struct zebra_if *zebra_if;
1138 struct rtadv_prefix rp;
1139
1140 ifp = (struct interface *) vty->index;
1141 zebra_if = ifp->info;
1142
1143 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1144 if (!ret)
1145 {
1146 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1147 return CMD_WARNING;
1148 }
hasso3e31cde2004-05-18 11:58:59 +00001149 rp.AdvOnLinkFlag = 1;
1150 rp.AdvAutonomousFlag = 1;
vincent7cee1bb2005-03-25 13:08:53 +00001151 rp.AdvRouterAddressFlag = 0;
hasso3e31cde2004-05-18 11:58:59 +00001152 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1153 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
paul718e3742002-12-13 20:15:29 +00001154
hasso3e31cde2004-05-18 11:58:59 +00001155 if (argc > 1)
paul718e3742002-12-13 20:15:29 +00001156 {
hasso3e31cde2004-05-18 11:58:59 +00001157 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
paul718e3742002-12-13 20:15:29 +00001158 {
hasso3e31cde2004-05-18 11:58:59 +00001159 if ( strncmp (argv[1], "i", 1) == 0)
1160 rp.AdvValidLifetime = UINT32_MAX;
1161 else
1162 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1163 (char **)NULL, 10);
1164
1165 if ( strncmp (argv[2], "i", 1) == 0)
1166 rp.AdvPreferredLifetime = UINT32_MAX;
1167 else
1168 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1169 (char **)NULL, 10);
1170
1171 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1172 {
1173 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1174 return CMD_WARNING;
1175 }
1176 cursor = cursor + 2;
paul718e3742002-12-13 20:15:29 +00001177 }
hasso3e31cde2004-05-18 11:58:59 +00001178 if (argc > cursor)
paul718e3742002-12-13 20:15:29 +00001179 {
hasso3e31cde2004-05-18 11:58:59 +00001180 for (i = cursor; i < argc; i++)
1181 {
1182 if (strncmp (argv[i], "of", 2) == 0)
1183 rp.AdvOnLinkFlag = 0;
1184 if (strncmp (argv[i], "no", 2) == 0)
1185 rp.AdvAutonomousFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +00001186 if (strncmp (argv[i], "ro", 2) == 0)
1187 rp.AdvRouterAddressFlag = 1;
hasso3e31cde2004-05-18 11:58:59 +00001188 }
paul718e3742002-12-13 20:15:29 +00001189 }
1190 }
1191
1192 rtadv_prefix_set (zebra_if, &rp);
1193
1194 return CMD_SUCCESS;
1195}
1196
hasso3e31cde2004-05-18 11:58:59 +00001197ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001198 ipv6_nd_prefix_val_nortaddr_cmd,
1199 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1200 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1201 "Interface IPv6 config commands\n"
1202 "Neighbor discovery\n"
1203 "Prefix information\n"
1204 "IPv6 prefix\n"
1205 "Valid lifetime in seconds\n"
1206 "Infinite valid lifetime\n"
1207 "Preferred lifetime in seconds\n"
1208 "Infinite preferred lifetime\n"
1209 "Do not use prefix for onlink determination\n"
1210 "Do not use prefix for autoconfiguration\n")
1211
1212ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001213 ipv6_nd_prefix_val_rev_cmd,
1214 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1215 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1216 "Interface IPv6 config commands\n"
1217 "Neighbor discovery\n"
1218 "Prefix information\n"
1219 "IPv6 prefix\n"
1220 "Valid lifetime in seconds\n"
1221 "Infinite valid lifetime\n"
1222 "Preferred lifetime in seconds\n"
1223 "Infinite preferred lifetime\n"
1224 "Do not use prefix for autoconfiguration\n"
1225 "Do not use prefix for onlink determination\n")
1226
1227ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001228 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1229 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1230 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1231 "Interface IPv6 config commands\n"
1232 "Neighbor discovery\n"
1233 "Prefix information\n"
1234 "IPv6 prefix\n"
1235 "Valid lifetime in seconds\n"
1236 "Infinite valid lifetime\n"
1237 "Preferred lifetime in seconds\n"
1238 "Infinite preferred lifetime\n"
1239 "Do not use prefix for autoconfiguration\n"
1240 "Do not use prefix for onlink determination\n"
1241 "Set Router Address flag\n")
1242
1243ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001244 ipv6_nd_prefix_val_noauto_cmd,
1245 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1246 "(<0-4294967295>|infinite) (no-autoconfig|)",
1247 "Interface IPv6 config commands\n"
1248 "Neighbor discovery\n"
1249 "Prefix information\n"
1250 "IPv6 prefix\n"
1251 "Valid lifetime in seconds\n"
1252 "Infinite valid lifetime\n"
1253 "Preferred lifetime in seconds\n"
1254 "Infinite preferred lifetime\n"
vincent7cee1bb2005-03-25 13:08:53 +00001255 "Do not use prefix for autoconfiguration")
hasso3e31cde2004-05-18 11:58:59 +00001256
1257ALIAS (ipv6_nd_prefix,
1258 ipv6_nd_prefix_val_offlink_cmd,
1259 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1260 "(<0-4294967295>|infinite) (off-link|)",
1261 "Interface IPv6 config commands\n"
1262 "Neighbor discovery\n"
1263 "Prefix information\n"
1264 "IPv6 prefix\n"
1265 "Valid lifetime in seconds\n"
1266 "Infinite valid lifetime\n"
1267 "Preferred lifetime in seconds\n"
1268 "Infinite preferred lifetime\n"
1269 "Do not use prefix for onlink determination\n")
1270
1271ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001272 ipv6_nd_prefix_val_rtaddr_cmd,
1273 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1274 "(<0-4294967295>|infinite) (router-address|)",
1275 "Interface IPv6 config commands\n"
1276 "Neighbor discovery\n"
1277 "Prefix information\n"
1278 "IPv6 prefix\n"
1279 "Valid lifetime in seconds\n"
1280 "Infinite valid lifetime\n"
1281 "Preferred lifetime in seconds\n"
1282 "Infinite preferred lifetime\n"
1283 "Set Router Address flag\n")
1284
1285ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001286 ipv6_nd_prefix_val_cmd,
1287 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1288 "(<0-4294967295>|infinite)",
1289 "Interface IPv6 config commands\n"
1290 "Neighbor discovery\n"
1291 "Prefix information\n"
1292 "IPv6 prefix\n"
1293 "Valid lifetime in seconds\n"
1294 "Infinite valid lifetime\n"
1295 "Preferred lifetime in seconds\n"
1296 "Infinite preferred lifetime\n")
1297
1298ALIAS (ipv6_nd_prefix,
1299 ipv6_nd_prefix_noval_cmd,
1300 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1301 "Interface IPv6 config commands\n"
1302 "Neighbor discovery\n"
1303 "Prefix information\n"
1304 "IPv6 prefix\n"
1305 "Do not use prefix for autoconfiguration\n"
1306 "Do not use prefix for onlink determination\n")
1307
1308ALIAS (ipv6_nd_prefix,
1309 ipv6_nd_prefix_noval_rev_cmd,
1310 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1311 "Interface IPv6 config commands\n"
1312 "Neighbor discovery\n"
1313 "Prefix information\n"
1314 "IPv6 prefix\n"
1315 "Do not use prefix for onlink determination\n"
1316 "Do not use prefix for autoconfiguration\n")
1317
1318ALIAS (ipv6_nd_prefix,
1319 ipv6_nd_prefix_noval_noauto_cmd,
1320 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1321 "Interface IPv6 config commands\n"
1322 "Neighbor discovery\n"
1323 "Prefix information\n"
1324 "IPv6 prefix\n"
1325 "Do not use prefix for autoconfiguration\n")
1326
1327ALIAS (ipv6_nd_prefix,
1328 ipv6_nd_prefix_noval_offlink_cmd,
1329 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1330 "Interface IPv6 config commands\n"
1331 "Neighbor discovery\n"
1332 "Prefix information\n"
1333 "IPv6 prefix\n"
1334 "Do not use prefix for onlink determination\n")
1335
1336ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001337 ipv6_nd_prefix_noval_rtaddr_cmd,
1338 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1339 "Interface IPv6 config commands\n"
1340 "Neighbor discovery\n"
1341 "Prefix information\n"
1342 "IPv6 prefix\n"
1343 "Set Router Address flag\n")
1344
1345ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001346 ipv6_nd_prefix_prefix_cmd,
1347 "ipv6 nd prefix X:X::X:X/M",
1348 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001349 "Neighbor discovery\n"
1350 "Prefix information\n"
1351 "IPv6 prefix\n")
1352
hasso3e31cde2004-05-18 11:58:59 +00001353DEFUN (no_ipv6_nd_prefix,
1354 no_ipv6_nd_prefix_cmd,
1355 "no ipv6 nd prefix IPV6PREFIX",
paul718e3742002-12-13 20:15:29 +00001356 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001357 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001358 "Neighbor discovery\n"
1359 "Prefix information\n"
1360 "IPv6 prefix\n")
1361{
1362 int ret;
1363 struct interface *ifp;
1364 struct zebra_if *zebra_if;
1365 struct rtadv_prefix rp;
1366
1367 ifp = (struct interface *) vty->index;
1368 zebra_if = ifp->info;
1369
1370 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1371 if (!ret)
1372 {
1373 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1374 return CMD_WARNING;
1375 }
1376
1377 ret = rtadv_prefix_reset (zebra_if, &rp);
1378 if (!ret)
1379 {
1380 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1381 return CMD_WARNING;
1382 }
1383
1384 return CMD_SUCCESS;
1385}
Chris Caputob60668d2009-05-03 04:40:57 +00001386
1387DEFUN (ipv6_nd_router_preference,
1388 ipv6_nd_router_preference_cmd,
1389 "ipv6 nd router-preference (high|medium|low)",
1390 "Interface IPv6 config commands\n"
1391 "Neighbor discovery\n"
1392 "Default router preference\n"
1393 "High default router preference\n"
1394 "Low default router preference\n"
1395 "Medium default router preference (default)\n")
1396{
1397 struct interface *ifp;
1398 struct zebra_if *zif;
1399 int i = 0;
1400
1401 ifp = (struct interface *) vty->index;
1402 zif = ifp->info;
1403
1404 while (0 != rtadv_pref_strs[i])
1405 {
1406 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1407 {
1408 zif->rtadv.DefaultPreference = i;
1409 return CMD_SUCCESS;
1410 }
1411 i++;
1412 }
1413
1414 return CMD_ERR_NO_MATCH;
1415}
1416
1417DEFUN (no_ipv6_nd_router_preference,
1418 no_ipv6_nd_router_preference_cmd,
1419 "no ipv6 nd router-preference",
1420 NO_STR
1421 "Interface IPv6 config commands\n"
1422 "Neighbor discovery\n"
1423 "Default router preference\n")
1424{
1425 struct interface *ifp;
1426 struct zebra_if *zif;
1427
1428 ifp = (struct interface *) vty->index;
1429 zif = ifp->info;
1430
1431 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1432
1433 return CMD_SUCCESS;
1434}
1435
paul718e3742002-12-13 20:15:29 +00001436/* Write configuration about router advertisement. */
1437void
1438rtadv_config_write (struct vty *vty, struct interface *ifp)
1439{
1440 struct zebra_if *zif;
hasso52dc7ee2004-09-23 19:18:23 +00001441 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001442 struct rtadv_prefix *rprefix;
1443 u_char buf[INET6_ADDRSTRLEN];
vincent7cee1bb2005-03-25 13:08:53 +00001444 int interval;
paul718e3742002-12-13 20:15:29 +00001445
1446 if (! rtadv)
1447 return;
1448
1449 zif = ifp->info;
1450
1451 if (! if_is_loopback (ifp))
1452 {
1453 if (zif->rtadv.AdvSendAdvertisements)
1454 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1455 else
1456 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1457 }
1458
vincent7cee1bb2005-03-25 13:08:53 +00001459
1460 interval = zif->rtadv.MaxRtrAdvInterval;
1461 if (interval % 1000)
1462 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1463 VTY_NEWLINE);
1464 else
1465 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1466 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
paul718e3742002-12-13 20:15:29 +00001467 VTY_NEWLINE);
1468
1469 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1470 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1471 VTY_NEWLINE);
1472
1473 if (zif->rtadv.AdvReachableTime)
1474 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1475 VTY_NEWLINE);
1476
1477 if (zif->rtadv.AdvManagedFlag)
1478 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1479
1480 if (zif->rtadv.AdvOtherConfigFlag)
1481 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1482
Chris Caputob60668d2009-05-03 04:40:57 +00001483 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1484 vty_out (vty, " ipv6 nd router-preference %s%s",
1485 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1486 VTY_NEWLINE);
1487
paul1eb8ef22005-04-07 07:30:20 +00001488 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +00001489 {
hasso3e31cde2004-05-18 11:58:59 +00001490 vty_out (vty, " ipv6 nd prefix %s/%d",
paul718e3742002-12-13 20:15:29 +00001491 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
hassoc9e52be2004-09-26 16:09:34 +00001492 (char *) buf, INET6_ADDRSTRLEN),
hasso3e31cde2004-05-18 11:58:59 +00001493 rprefix->prefix.prefixlen);
1494 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1495 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1496 {
1497 if (rprefix->AdvValidLifetime == UINT32_MAX)
1498 vty_out (vty, " infinite");
1499 else
1500 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1501 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1502 vty_out (vty, " infinite");
1503 else
1504 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1505 }
1506 if (!rprefix->AdvOnLinkFlag)
1507 vty_out (vty, " off-link");
1508 if (!rprefix->AdvAutonomousFlag)
1509 vty_out (vty, " no-autoconfig");
vincent7cee1bb2005-03-25 13:08:53 +00001510 if (rprefix->AdvRouterAddressFlag)
1511 vty_out (vty, " router-address");
paul718e3742002-12-13 20:15:29 +00001512 vty_out (vty, "%s", VTY_NEWLINE);
1513 }
1514}
1515
paul718e3742002-12-13 20:15:29 +00001516
paula1ac18c2005-06-28 17:17:12 +00001517static void
paul718e3742002-12-13 20:15:29 +00001518rtadv_event (enum rtadv_event event, int val)
1519{
1520 switch (event)
1521 {
1522 case RTADV_START:
1523 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001524 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001525 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001526 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1527 NULL, 0);
paul718e3742002-12-13 20:15:29 +00001528 break;
1529 case RTADV_STOP:
1530 if (rtadv->ra_timer)
1531 {
1532 thread_cancel (rtadv->ra_timer);
1533 rtadv->ra_timer = NULL;
1534 }
1535 if (rtadv->ra_read)
1536 {
1537 thread_cancel (rtadv->ra_read);
1538 rtadv->ra_read = NULL;
1539 }
1540 break;
1541 case RTADV_TIMER:
1542 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001543 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1544 val);
paul718e3742002-12-13 20:15:29 +00001545 break;
vincent7cee1bb2005-03-25 13:08:53 +00001546 case RTADV_TIMER_MSEC:
1547 if (! rtadv->ra_timer)
1548 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1549 NULL, val);
1550 break;
paul718e3742002-12-13 20:15:29 +00001551 case RTADV_READ:
1552 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001553 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001554 break;
1555 default:
1556 break;
1557 }
1558 return;
1559}
1560
1561void
paula1ac18c2005-06-28 17:17:12 +00001562rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001563{
1564 int sock;
1565
1566 sock = rtadv_make_socket ();
1567 if (sock < 0)
1568 return;
1569
1570 rtadv = rtadv_new ();
1571 rtadv->sock = sock;
1572
1573 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1574 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
paul718e3742002-12-13 20:15:29 +00001575 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001576 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
paul718e3742002-12-13 20:15:29 +00001577 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1578 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1579 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1580 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1581 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1582 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1583 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1584 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1585 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001586 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1587 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1588 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1589 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1590 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1591 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1592 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1593 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001594 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001595 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1596 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001597 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1598 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1599 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001600 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001601 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1602 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1603 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1604 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1605 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001606 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001607 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1608 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
Chris Caputob60668d2009-05-03 04:40:57 +00001609 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1610 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
paul718e3742002-12-13 20:15:29 +00001611}
1612
paula1ac18c2005-06-28 17:17:12 +00001613static int
paul718e3742002-12-13 20:15:29 +00001614if_join_all_router (int sock, struct interface *ifp)
1615{
1616 int ret;
1617
1618 struct ipv6_mreq mreq;
1619
1620 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1621 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1622 mreq.ipv6mr_interface = ifp->ifindex;
1623
1624 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1625 (char *) &mreq, sizeof mreq);
1626 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001627 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001628
1629 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1630
1631 return 0;
1632}
1633
paula1ac18c2005-06-28 17:17:12 +00001634static int
paul718e3742002-12-13 20:15:29 +00001635if_leave_all_router (int sock, struct interface *ifp)
1636{
1637 int ret;
1638
1639 struct ipv6_mreq mreq;
1640
1641 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1642 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1643 mreq.ipv6mr_interface = ifp->ifindex;
1644
1645 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1646 (char *) &mreq, sizeof mreq);
1647 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001648 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001649
1650 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1651
1652 return 0;
1653}
1654
1655#else
1656void
paula1ac18c2005-06-28 17:17:12 +00001657rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001658{
1659 /* Empty.*/;
1660}
1661#endif /* RTADV && HAVE_IPV6 */