blob: dd2be8126cfb8af14e488e45f139517f06cb2d2f [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;
209 rtadv->nd_ra_flags_reserved = 0;
210 if (zif->rtadv.AdvManagedFlag)
211 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
212 if (zif->rtadv.AdvOtherConfigFlag)
213 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
vincent7cee1bb2005-03-25 13:08:53 +0000214 if (zif->rtadv.AdvHomeAgentFlag)
215 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
paul718e3742002-12-13 20:15:29 +0000216 rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
217 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
218 rtadv->nd_ra_retransmit = htonl (0);
219
220 len = sizeof (struct nd_router_advert);
221
vincent7cee1bb2005-03-25 13:08:53 +0000222 if (zif->rtadv.AdvHomeAgentFlag)
223 {
224 struct nd_opt_homeagent_info *ndopt_hai =
225 (struct nd_opt_homeagent_info *)(buf + len);
226 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
227 ndopt_hai->nd_opt_hai_len = 1;
228 ndopt_hai->nd_opt_hai_reserved = 0;
229 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
230 ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);
231 len += sizeof(struct nd_opt_homeagent_info);
232 }
233
234 if (zif->rtadv.AdvIntervalOption)
235 {
236 struct nd_opt_adv_interval *ndopt_adv =
237 (struct nd_opt_adv_interval *)(buf + len);
238 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
239 ndopt_adv->nd_opt_ai_len = 1;
240 ndopt_adv->nd_opt_ai_reserved = 0;
241 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
242 len += sizeof(struct nd_opt_adv_interval);
243 }
244
paul718e3742002-12-13 20:15:29 +0000245 /* Fill in prefix. */
paul1eb8ef22005-04-07 07:30:20 +0000246 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +0000247 {
248 struct nd_opt_prefix_info *pinfo;
paul718e3742002-12-13 20:15:29 +0000249
250 pinfo = (struct nd_opt_prefix_info *) (buf + len);
251
252 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
253 pinfo->nd_opt_pi_len = 4;
254 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
255
256 pinfo->nd_opt_pi_flags_reserved = 0;
257 if (rprefix->AdvOnLinkFlag)
258 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
259 if (rprefix->AdvAutonomousFlag)
260 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
vincent7cee1bb2005-03-25 13:08:53 +0000261 if (rprefix->AdvRouterAddressFlag)
262 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
paul718e3742002-12-13 20:15:29 +0000263
264 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
265 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
266 pinfo->nd_opt_pi_reserved2 = 0;
267
268 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
269 sizeof (struct in6_addr));
270
271#ifdef DEBUG
272 {
273 u_char buf[INET6_ADDRSTRLEN];
274
ajsb6178002004-12-07 21:12:56 +0000275 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
hasso3e31cde2004-05-18 11:58:59 +0000276 buf, INET6_ADDRSTRLEN));
paul718e3742002-12-13 20:15:29 +0000277
278 }
279#endif /* DEBUG */
280
281 len += sizeof (struct nd_opt_prefix_info);
282 }
283
284 /* Hardware address. */
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000285#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000286 sdl = &ifp->sdl;
287 if (sdl != NULL && sdl->sdl_alen != 0)
288 {
289 buf[len++] = ND_OPT_SOURCE_LINKADDR;
290 buf[len++] = (sdl->sdl_alen + 2) >> 3;
291
292 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
293 len += sdl->sdl_alen;
294 }
295#else
296 if (ifp->hw_addr_len != 0)
297 {
298 buf[len++] = ND_OPT_SOURCE_LINKADDR;
299 buf[len++] = (ifp->hw_addr_len + 2) >> 3;
300
301 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
302 len += ifp->hw_addr_len;
303 }
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000304#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000305
306 msg.msg_name = (void *) &addr;
307 msg.msg_namelen = sizeof (struct sockaddr_in6);
308 msg.msg_iov = &iov;
309 msg.msg_iovlen = 1;
310 msg.msg_control = (void *) adata;
gdtf841e022004-08-11 19:20:01 +0000311 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
gdt57492d52004-08-11 18:06:38 +0000312 msg.msg_flags = 0;
paul718e3742002-12-13 20:15:29 +0000313 iov.iov_base = buf;
314 iov.iov_len = len;
315
ajsb99760a2005-01-04 16:24:43 +0000316 cmsgptr = ZCMSG_FIRSTHDR(&msg);
gdt57492d52004-08-11 18:06:38 +0000317 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
paul718e3742002-12-13 20:15:29 +0000318 cmsgptr->cmsg_level = IPPROTO_IPV6;
319 cmsgptr->cmsg_type = IPV6_PKTINFO;
gdt80893812004-08-11 15:58:00 +0000320
paul718e3742002-12-13 20:15:29 +0000321 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
322 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
323 pkt->ipi6_ifindex = ifp->ifindex;
324
325 ret = sendmsg (sock, &msg, 0);
gdt9ccabd12004-01-06 18:23:02 +0000326 if (ret < 0)
327 {
328 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
ajs6099b3b2004-11-20 02:06:59 +0000329 errno, safe_strerror(errno));
gdt9ccabd12004-01-06 18:23:02 +0000330 }
paul718e3742002-12-13 20:15:29 +0000331}
332
paula1ac18c2005-06-28 17:17:12 +0000333static int
paul718e3742002-12-13 20:15:29 +0000334rtadv_timer (struct thread *thread)
335{
paul1eb8ef22005-04-07 07:30:20 +0000336 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000337 struct interface *ifp;
338 struct zebra_if *zif;
vincent7cee1bb2005-03-25 13:08:53 +0000339 int period;
paul718e3742002-12-13 20:15:29 +0000340
341 rtadv->ra_timer = NULL;
vincent7cee1bb2005-03-25 13:08:53 +0000342 if (rtadv->adv_msec_if_count == 0)
343 {
344 period = 1000; /* 1 s */
345 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
346 }
347 else
348 {
349 period = 10; /* 10 ms */
350 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
351 }
paul718e3742002-12-13 20:15:29 +0000352
paul1eb8ef22005-04-07 07:30:20 +0000353 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
paul718e3742002-12-13 20:15:29 +0000354 {
paul718e3742002-12-13 20:15:29 +0000355 if (if_is_loopback (ifp))
356 continue;
357
358 zif = ifp->info;
359
360 if (zif->rtadv.AdvSendAdvertisements)
vincent7cee1bb2005-03-25 13:08:53 +0000361 {
362 zif->rtadv.AdvIntervalTimer -= period;
363 if (zif->rtadv.AdvIntervalTimer <= 0)
364 {
365 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
366 rtadv_send_packet (rtadv->sock, ifp);
367 }
368 }
paul718e3742002-12-13 20:15:29 +0000369 }
370 return 0;
371}
372
paula1ac18c2005-06-28 17:17:12 +0000373static void
paul718e3742002-12-13 20:15:29 +0000374rtadv_process_solicit (struct interface *ifp)
375{
376 zlog_info ("Router solicitation received on %s", ifp->name);
377
378 rtadv_send_packet (rtadv->sock, ifp);
379}
380
paula1ac18c2005-06-28 17:17:12 +0000381static void
382rtadv_process_advert (void)
paul718e3742002-12-13 20:15:29 +0000383{
384 zlog_info ("Router advertisement received");
385}
386
paula1ac18c2005-06-28 17:17:12 +0000387static void
hassofce954f2004-10-07 20:29:24 +0000388rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
paul718e3742002-12-13 20:15:29 +0000389{
390 struct icmp6_hdr *icmph;
391 struct interface *ifp;
392 struct zebra_if *zif;
393
394 /* Interface search. */
395 ifp = if_lookup_by_index (ifindex);
396 if (ifp == NULL)
397 {
398 zlog_warn ("Unknown interface index: %d", ifindex);
399 return;
400 }
401
402 if (if_is_loopback (ifp))
403 return;
404
405 /* Check interface configuration. */
406 zif = ifp->info;
407 if (! zif->rtadv.AdvSendAdvertisements)
408 return;
409
410 /* ICMP message length check. */
411 if (len < sizeof (struct icmp6_hdr))
412 {
413 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
414 return;
415 }
416
417 icmph = (struct icmp6_hdr *) buf;
418
419 /* ICMP message type check. */
420 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
421 icmph->icmp6_type != ND_ROUTER_ADVERT)
422 {
423 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
424 return;
425 }
426
427 /* Hoplimit check. */
428 if (hoplimit >= 0 && hoplimit != 255)
429 {
430 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
431 hoplimit);
432 return;
433 }
434
435 /* Check ICMP message type. */
436 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
437 rtadv_process_solicit (ifp);
438 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
439 rtadv_process_advert ();
440
441 return;
442}
443
paula1ac18c2005-06-28 17:17:12 +0000444static int
paul718e3742002-12-13 20:15:29 +0000445rtadv_read (struct thread *thread)
446{
447 int sock;
448 int len;
449 u_char buf[RTADV_MSG_SIZE];
450 struct sockaddr_in6 from;
451 unsigned int ifindex;
452 int hoplimit = -1;
453
454 sock = THREAD_FD (thread);
455 rtadv->ra_read = NULL;
456
457 /* Register myself. */
458 rtadv_event (RTADV_READ, sock);
459
460 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
461
462 if (len < 0)
463 {
ajs6099b3b2004-11-20 02:06:59 +0000464 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000465 return len;
466 }
467
hassofce954f2004-10-07 20:29:24 +0000468 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
paul718e3742002-12-13 20:15:29 +0000469
470 return 0;
471}
472
paula1ac18c2005-06-28 17:17:12 +0000473static int
paul718e3742002-12-13 20:15:29 +0000474rtadv_make_socket (void)
475{
476 int sock;
477 int ret;
478 struct icmp6_filter filter;
479
pauledd7c242003-06-04 13:59:38 +0000480 if ( zserv_privs.change (ZPRIVS_RAISE) )
481 zlog_err ("rtadv_make_socket: could not raise privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000482 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000483
paul718e3742002-12-13 20:15:29 +0000484 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
485
pauledd7c242003-06-04 13:59:38 +0000486 if ( zserv_privs.change (ZPRIVS_LOWER) )
487 zlog_err ("rtadv_make_socket: could not lower privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000488 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000489
paul718e3742002-12-13 20:15:29 +0000490 /* When we can't make ICMPV6 socket simply back. Router
491 advertisement feature will not be supported. */
492 if (sock < 0)
493 return -1;
494
495 ret = setsockopt_ipv6_pktinfo (sock, 1);
496 if (ret < 0)
497 return ret;
paul718e3742002-12-13 20:15:29 +0000498 ret = setsockopt_ipv6_multicast_loop (sock, 0);
499 if (ret < 0)
500 return ret;
501 ret = setsockopt_ipv6_unicast_hops (sock, 255);
502 if (ret < 0)
503 return ret;
504 ret = setsockopt_ipv6_multicast_hops (sock, 255);
505 if (ret < 0)
506 return ret;
507 ret = setsockopt_ipv6_hoplimit (sock, 1);
508 if (ret < 0)
509 return ret;
510
511 ICMP6_FILTER_SETBLOCKALL(&filter);
512 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
513 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
514
515 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
516 sizeof (struct icmp6_filter));
517 if (ret < 0)
518 {
ajs6099b3b2004-11-20 02:06:59 +0000519 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000520 return ret;
521 }
522
523 return sock;
524}
525
paula1ac18c2005-06-28 17:17:12 +0000526static struct rtadv_prefix *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800527rtadv_prefix_new (void)
paul718e3742002-12-13 20:15:29 +0000528{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700529 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
paul718e3742002-12-13 20:15:29 +0000530}
531
paula1ac18c2005-06-28 17:17:12 +0000532static void
paul718e3742002-12-13 20:15:29 +0000533rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
534{
535 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
536}
537
paula1ac18c2005-06-28 17:17:12 +0000538static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000539rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000540{
hasso52dc7ee2004-09-23 19:18:23 +0000541 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000542 struct rtadv_prefix *rprefix;
543
paul1eb8ef22005-04-07 07:30:20 +0000544 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
545 if (prefix_same (&rprefix->prefix, p))
546 return rprefix;
paul718e3742002-12-13 20:15:29 +0000547 return NULL;
548}
549
paula1ac18c2005-06-28 17:17:12 +0000550static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000551rtadv_prefix_get (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000552{
553 struct rtadv_prefix *rprefix;
554
555 rprefix = rtadv_prefix_lookup (rplist, p);
556 if (rprefix)
557 return rprefix;
558
559 rprefix = rtadv_prefix_new ();
560 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
561 listnode_add (rplist, rprefix);
562
563 return rprefix;
564}
565
paula1ac18c2005-06-28 17:17:12 +0000566static void
paul718e3742002-12-13 20:15:29 +0000567rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
568{
569 struct rtadv_prefix *rprefix;
570
571 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
572
573 /* Set parameters. */
574 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
575 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
576 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
577 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
vincent7cee1bb2005-03-25 13:08:53 +0000578 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
paul718e3742002-12-13 20:15:29 +0000579}
580
paula1ac18c2005-06-28 17:17:12 +0000581static int
paul718e3742002-12-13 20:15:29 +0000582rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
583{
584 struct rtadv_prefix *rprefix;
585
586 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
587 if (rprefix != NULL)
588 {
589 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
590 rtadv_prefix_free (rprefix);
591 return 1;
592 }
593 else
594 return 0;
595}
596
597DEFUN (ipv6_nd_suppress_ra,
598 ipv6_nd_suppress_ra_cmd,
599 "ipv6 nd suppress-ra",
hasso3e31cde2004-05-18 11:58:59 +0000600 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000601 "Neighbor discovery\n"
602 "Suppress Router Advertisement\n")
603{
604 struct interface *ifp;
605 struct zebra_if *zif;
606
607 ifp = vty->index;
608 zif = ifp->info;
609
610 if (if_is_loopback (ifp))
611 {
612 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
613 return CMD_WARNING;
614 }
615
616 if (zif->rtadv.AdvSendAdvertisements)
617 {
618 zif->rtadv.AdvSendAdvertisements = 0;
619 zif->rtadv.AdvIntervalTimer = 0;
620 rtadv->adv_if_count--;
621
622 if_leave_all_router (rtadv->sock, ifp);
623
624 if (rtadv->adv_if_count == 0)
625 rtadv_event (RTADV_STOP, 0);
626 }
627
628 return CMD_SUCCESS;
629}
630
paul718e3742002-12-13 20:15:29 +0000631DEFUN (no_ipv6_nd_suppress_ra,
632 no_ipv6_nd_suppress_ra_cmd,
633 "no ipv6 nd suppress-ra",
634 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000635 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000636 "Neighbor discovery\n"
637 "Suppress Router Advertisement\n")
638{
639 struct interface *ifp;
640 struct zebra_if *zif;
641
642 ifp = vty->index;
643 zif = ifp->info;
644
645 if (if_is_loopback (ifp))
646 {
647 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
648 return CMD_WARNING;
649 }
650
651 if (! zif->rtadv.AdvSendAdvertisements)
652 {
653 zif->rtadv.AdvSendAdvertisements = 1;
654 zif->rtadv.AdvIntervalTimer = 0;
655 rtadv->adv_if_count++;
656
657 if_join_all_router (rtadv->sock, ifp);
658
659 if (rtadv->adv_if_count == 1)
660 rtadv_event (RTADV_START, rtadv->sock);
661 }
662
663 return CMD_SUCCESS;
664}
665
vincent7cee1bb2005-03-25 13:08:53 +0000666DEFUN (ipv6_nd_ra_interval_msec,
667 ipv6_nd_ra_interval_msec_cmd,
668 "ipv6 nd ra-interval msec MILLISECONDS",
669 "Interface IPv6 config commands\n"
670 "Neighbor discovery\n"
671 "Router Advertisement interval\n"
672 "Router Advertisement interval in milliseconds\n")
673{
674 int interval;
675 struct interface *ifp;
676 struct zebra_if *zif;
677
678 ifp = (struct interface *) vty->index;
679 zif = ifp->info;
680
681 interval = atoi (argv[0]);
682
683 if (interval <= 0)
684 {
685 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
686 return CMD_WARNING;
687 }
688
689 if (zif->rtadv.MaxRtrAdvInterval % 1000)
690 rtadv->adv_msec_if_count--;
691
692 if (interval % 1000)
693 rtadv->adv_msec_if_count++;
694
695 zif->rtadv.MaxRtrAdvInterval = interval;
696 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
697 zif->rtadv.AdvIntervalTimer = 0;
698
699 return CMD_SUCCESS;
700}
701
paul718e3742002-12-13 20:15:29 +0000702DEFUN (ipv6_nd_ra_interval,
703 ipv6_nd_ra_interval_cmd,
704 "ipv6 nd ra-interval SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000705 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000706 "Neighbor discovery\n"
707 "Router Advertisement interval\n"
708 "Router Advertisement interval in seconds\n")
709{
710 int interval;
711 struct interface *ifp;
712 struct zebra_if *zif;
713
714 ifp = (struct interface *) vty->index;
715 zif = ifp->info;
716
717 interval = atoi (argv[0]);
718
vincent7cee1bb2005-03-25 13:08:53 +0000719 if (interval <= 0)
paul718e3742002-12-13 20:15:29 +0000720 {
721 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
722 return CMD_WARNING;
723 }
724
vincent7cee1bb2005-03-25 13:08:53 +0000725 if (zif->rtadv.MaxRtrAdvInterval % 1000)
726 rtadv->adv_msec_if_count--;
727
728 /* convert to milliseconds */
729 interval = interval * 1000;
730
paul718e3742002-12-13 20:15:29 +0000731 zif->rtadv.MaxRtrAdvInterval = interval;
732 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
733 zif->rtadv.AdvIntervalTimer = 0;
734
735 return CMD_SUCCESS;
736}
737
738DEFUN (no_ipv6_nd_ra_interval,
739 no_ipv6_nd_ra_interval_cmd,
740 "no ipv6 nd ra-interval",
741 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000742 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000743 "Neighbor discovery\n"
744 "Router Advertisement interval\n")
745{
746 struct interface *ifp;
747 struct zebra_if *zif;
748
749 ifp = (struct interface *) vty->index;
750 zif = ifp->info;
751
vincent7cee1bb2005-03-25 13:08:53 +0000752 if (zif->rtadv.MaxRtrAdvInterval % 1000)
753 rtadv->adv_msec_if_count--;
754
paul718e3742002-12-13 20:15:29 +0000755 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
756 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
757 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
758
759 return CMD_SUCCESS;
760}
761
762DEFUN (ipv6_nd_ra_lifetime,
763 ipv6_nd_ra_lifetime_cmd,
764 "ipv6 nd ra-lifetime SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000765 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000766 "Neighbor discovery\n"
767 "Router lifetime\n"
768 "Router lifetime in seconds\n")
769{
770 int lifetime;
771 struct interface *ifp;
772 struct zebra_if *zif;
773
774 ifp = (struct interface *) vty->index;
775 zif = ifp->info;
776
777 lifetime = atoi (argv[0]);
778
779 if (lifetime < 0 || lifetime > 0xffff)
780 {
781 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
782 return CMD_WARNING;
783 }
784
785 zif->rtadv.AdvDefaultLifetime = lifetime;
786
787 return CMD_SUCCESS;
788}
789
790DEFUN (no_ipv6_nd_ra_lifetime,
791 no_ipv6_nd_ra_lifetime_cmd,
792 "no ipv6 nd ra-lifetime",
793 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000794 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000795 "Neighbor discovery\n"
796 "Router lifetime\n")
797{
798 struct interface *ifp;
799 struct zebra_if *zif;
800
801 ifp = (struct interface *) vty->index;
802 zif = ifp->info;
803
804 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
805
806 return CMD_SUCCESS;
807}
808
809DEFUN (ipv6_nd_reachable_time,
810 ipv6_nd_reachable_time_cmd,
811 "ipv6 nd reachable-time MILLISECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000812 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000813 "Neighbor discovery\n"
814 "Reachable time\n"
815 "Reachable time in milliseconds\n")
816{
817 u_int32_t rtime;
818 struct interface *ifp;
819 struct zebra_if *zif;
820
821 ifp = (struct interface *) vty->index;
822 zif = ifp->info;
823
824 rtime = (u_int32_t) atol (argv[0]);
825
826 if (rtime > RTADV_MAX_REACHABLE_TIME)
827 {
828 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
829 return CMD_WARNING;
830 }
831
832 zif->rtadv.AdvReachableTime = rtime;
833
834 return CMD_SUCCESS;
835}
836
837DEFUN (no_ipv6_nd_reachable_time,
838 no_ipv6_nd_reachable_time_cmd,
839 "no ipv6 nd reachable-time",
840 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000841 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000842 "Neighbor discovery\n"
843 "Reachable time\n")
844{
845 struct interface *ifp;
846 struct zebra_if *zif;
847
848 ifp = (struct interface *) vty->index;
849 zif = ifp->info;
850
851 zif->rtadv.AdvReachableTime = 0;
852
853 return CMD_SUCCESS;
854}
855
vincent7cee1bb2005-03-25 13:08:53 +0000856DEFUN (ipv6_nd_homeagent_preference,
857 ipv6_nd_homeagent_preference_cmd,
858 "ipv6 nd home-agent-preference PREFERENCE",
859 "Interface IPv6 config commands\n"
860 "Neighbor discovery\n"
861 "Home Agent preference\n"
862 "Home Agent preference value 0..65535\n")
863{
864 u_int32_t hapref;
865 struct interface *ifp;
866 struct zebra_if *zif;
867
868 ifp = (struct interface *) vty->index;
869 zif = ifp->info;
870
871 hapref = (u_int32_t) atol (argv[0]);
872
873 if (hapref > 65535)
874 {
875 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
876 return CMD_WARNING;
877 }
878
879 zif->rtadv.HomeAgentPreference = hapref;
880
881 return CMD_SUCCESS;
882}
883
884DEFUN (no_ipv6_nd_homeagent_preference,
885 no_ipv6_nd_homeagent_preference_cmd,
886 "no ipv6 nd home-agent-preference",
887 NO_STR
888 "Interface IPv6 config commands\n"
889 "Neighbor discovery\n"
890 "Home Agent preference\n")
891{
892 struct interface *ifp;
893 struct zebra_if *zif;
894
895 ifp = (struct interface *) vty->index;
896 zif = ifp->info;
897
898 zif->rtadv.HomeAgentPreference = 0;
899
900 return CMD_SUCCESS;
901}
902
903DEFUN (ipv6_nd_homeagent_lifetime,
904 ipv6_nd_homeagent_lifetime_cmd,
905 "ipv6 nd home-agent-lifetime SECONDS",
906 "Interface IPv6 config commands\n"
907 "Neighbor discovery\n"
908 "Home Agent lifetime\n"
909 "Home Agent lifetime in seconds\n")
910{
911 u_int32_t ha_ltime;
912 struct interface *ifp;
913 struct zebra_if *zif;
914
915 ifp = (struct interface *) vty->index;
916 zif = ifp->info;
917
918 ha_ltime = (u_int32_t) atol (argv[0]);
919
920 if (ha_ltime > RTADV_MAX_HALIFETIME)
921 {
922 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
923 return CMD_WARNING;
924 }
925
926 zif->rtadv.HomeAgentLifetime = ha_ltime;
927
928 return CMD_SUCCESS;
929}
930
931DEFUN (no_ipv6_nd_homeagent_lifetime,
932 no_ipv6_nd_homeagent_lifetime_cmd,
933 "no ipv6 nd home-agent-lifetime",
934 NO_STR
935 "Interface IPv6 config commands\n"
936 "Neighbor discovery\n"
937 "Home Agent lifetime\n")
938{
939 struct interface *ifp;
940 struct zebra_if *zif;
941
942 ifp = (struct interface *) vty->index;
943 zif = ifp->info;
944
945 zif->rtadv.HomeAgentLifetime = 0;
946
947 return CMD_SUCCESS;
948}
949
paul718e3742002-12-13 20:15:29 +0000950DEFUN (ipv6_nd_managed_config_flag,
951 ipv6_nd_managed_config_flag_cmd,
952 "ipv6 nd managed-config-flag",
hasso3e31cde2004-05-18 11:58:59 +0000953 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000954 "Neighbor discovery\n"
955 "Managed address configuration flag\n")
956{
957 struct interface *ifp;
958 struct zebra_if *zif;
959
960 ifp = (struct interface *) vty->index;
961 zif = ifp->info;
962
963 zif->rtadv.AdvManagedFlag = 1;
964
965 return CMD_SUCCESS;
966}
967
968DEFUN (no_ipv6_nd_managed_config_flag,
969 no_ipv6_nd_managed_config_flag_cmd,
970 "no ipv6 nd managed-config-flag",
971 NO_STR
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 = 0;
983
984 return CMD_SUCCESS;
985}
986
vincent7cee1bb2005-03-25 13:08:53 +0000987DEFUN (ipv6_nd_homeagent_config_flag,
988 ipv6_nd_homeagent_config_flag_cmd,
989 "ipv6 nd home-agent-config-flag",
990 "Interface IPv6 config commands\n"
991 "Neighbor discovery\n"
992 "Home Agent configuration flag\n")
993{
994 struct interface *ifp;
995 struct zebra_if *zif;
996
997 ifp = (struct interface *) vty->index;
998 zif = ifp->info;
999
1000 zif->rtadv.AdvHomeAgentFlag = 1;
1001
1002 return CMD_SUCCESS;
1003}
1004
1005DEFUN (no_ipv6_nd_homeagent_config_flag,
1006 no_ipv6_nd_homeagent_config_flag_cmd,
1007 "no ipv6 nd home-agent-config-flag",
1008 NO_STR
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 = 0;
1020
1021 return CMD_SUCCESS;
1022}
1023
1024DEFUN (ipv6_nd_adv_interval_config_option,
1025 ipv6_nd_adv_interval_config_option_cmd,
1026 "ipv6 nd adv-interval-option",
1027 "Interface IPv6 config commands\n"
1028 "Neighbor discovery\n"
1029 "Advertisement Interval Option\n")
1030{
1031 struct interface *ifp;
1032 struct zebra_if *zif;
1033
1034 ifp = (struct interface *) vty->index;
1035 zif = ifp->info;
1036
1037 zif->rtadv.AdvIntervalOption = 1;
1038
1039 return CMD_SUCCESS;
1040}
1041
1042DEFUN (no_ipv6_nd_adv_interval_config_option,
1043 no_ipv6_nd_adv_interval_config_option_cmd,
1044 "no ipv6 nd adv-interval-option",
1045 NO_STR
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 = 0;
1057
1058 return CMD_SUCCESS;
1059}
1060
paul718e3742002-12-13 20:15:29 +00001061DEFUN (ipv6_nd_other_config_flag,
1062 ipv6_nd_other_config_flag_cmd,
1063 "ipv6 nd other-config-flag",
hasso3e31cde2004-05-18 11:58:59 +00001064 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001065 "Neighbor discovery\n"
1066 "Other statefull configuration flag\n")
1067{
1068 struct interface *ifp;
1069 struct zebra_if *zif;
1070
1071 ifp = (struct interface *) vty->index;
1072 zif = ifp->info;
1073
1074 zif->rtadv.AdvOtherConfigFlag = 1;
1075
1076 return CMD_SUCCESS;
1077}
1078
1079DEFUN (no_ipv6_nd_other_config_flag,
1080 no_ipv6_nd_other_config_flag_cmd,
1081 "no ipv6 nd other-config-flag",
1082 NO_STR
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 = 0;
1094
1095 return CMD_SUCCESS;
1096}
1097
hasso3e31cde2004-05-18 11:58:59 +00001098DEFUN (ipv6_nd_prefix,
1099 ipv6_nd_prefix_cmd,
1100 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
vincent7cee1bb2005-03-25 13:08:53 +00001101 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
hasso3e31cde2004-05-18 11:58:59 +00001102 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001103 "Neighbor discovery\n"
1104 "Prefix information\n"
1105 "IPv6 prefix\n"
1106 "Valid lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001107 "Infinite valid lifetime\n"
paul718e3742002-12-13 20:15:29 +00001108 "Preferred lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001109 "Infinite preferred lifetime\n"
1110 "Do not use prefix for onlink determination\n"
vincent7cee1bb2005-03-25 13:08:53 +00001111 "Do not use prefix for autoconfiguration\n"
1112 "Set Router Address flag\n")
paul718e3742002-12-13 20:15:29 +00001113{
1114 int i;
1115 int ret;
hasso3e31cde2004-05-18 11:58:59 +00001116 int cursor = 1;
paul718e3742002-12-13 20:15:29 +00001117 struct interface *ifp;
1118 struct zebra_if *zebra_if;
1119 struct rtadv_prefix rp;
1120
1121 ifp = (struct interface *) vty->index;
1122 zebra_if = ifp->info;
1123
1124 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1125 if (!ret)
1126 {
1127 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1128 return CMD_WARNING;
1129 }
hasso3e31cde2004-05-18 11:58:59 +00001130 rp.AdvOnLinkFlag = 1;
1131 rp.AdvAutonomousFlag = 1;
vincent7cee1bb2005-03-25 13:08:53 +00001132 rp.AdvRouterAddressFlag = 0;
hasso3e31cde2004-05-18 11:58:59 +00001133 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1134 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
paul718e3742002-12-13 20:15:29 +00001135
hasso3e31cde2004-05-18 11:58:59 +00001136 if (argc > 1)
paul718e3742002-12-13 20:15:29 +00001137 {
hasso3e31cde2004-05-18 11:58:59 +00001138 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
paul718e3742002-12-13 20:15:29 +00001139 {
hasso3e31cde2004-05-18 11:58:59 +00001140 if ( strncmp (argv[1], "i", 1) == 0)
1141 rp.AdvValidLifetime = UINT32_MAX;
1142 else
1143 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1144 (char **)NULL, 10);
1145
1146 if ( strncmp (argv[2], "i", 1) == 0)
1147 rp.AdvPreferredLifetime = UINT32_MAX;
1148 else
1149 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1150 (char **)NULL, 10);
1151
1152 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1153 {
1154 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1155 return CMD_WARNING;
1156 }
1157 cursor = cursor + 2;
paul718e3742002-12-13 20:15:29 +00001158 }
hasso3e31cde2004-05-18 11:58:59 +00001159 if (argc > cursor)
paul718e3742002-12-13 20:15:29 +00001160 {
hasso3e31cde2004-05-18 11:58:59 +00001161 for (i = cursor; i < argc; i++)
1162 {
1163 if (strncmp (argv[i], "of", 2) == 0)
1164 rp.AdvOnLinkFlag = 0;
1165 if (strncmp (argv[i], "no", 2) == 0)
1166 rp.AdvAutonomousFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +00001167 if (strncmp (argv[i], "ro", 2) == 0)
1168 rp.AdvRouterAddressFlag = 1;
hasso3e31cde2004-05-18 11:58:59 +00001169 }
paul718e3742002-12-13 20:15:29 +00001170 }
1171 }
1172
1173 rtadv_prefix_set (zebra_if, &rp);
1174
1175 return CMD_SUCCESS;
1176}
1177
hasso3e31cde2004-05-18 11:58:59 +00001178ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001179 ipv6_nd_prefix_val_nortaddr_cmd,
1180 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1181 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1182 "Interface IPv6 config commands\n"
1183 "Neighbor discovery\n"
1184 "Prefix information\n"
1185 "IPv6 prefix\n"
1186 "Valid lifetime in seconds\n"
1187 "Infinite valid lifetime\n"
1188 "Preferred lifetime in seconds\n"
1189 "Infinite preferred lifetime\n"
1190 "Do not use prefix for onlink determination\n"
1191 "Do not use prefix for autoconfiguration\n")
1192
1193ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001194 ipv6_nd_prefix_val_rev_cmd,
1195 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1196 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1197 "Interface IPv6 config commands\n"
1198 "Neighbor discovery\n"
1199 "Prefix information\n"
1200 "IPv6 prefix\n"
1201 "Valid lifetime in seconds\n"
1202 "Infinite valid lifetime\n"
1203 "Preferred lifetime in seconds\n"
1204 "Infinite preferred lifetime\n"
1205 "Do not use prefix for autoconfiguration\n"
1206 "Do not use prefix for onlink determination\n")
1207
1208ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001209 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1210 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1211 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1212 "Interface IPv6 config commands\n"
1213 "Neighbor discovery\n"
1214 "Prefix information\n"
1215 "IPv6 prefix\n"
1216 "Valid lifetime in seconds\n"
1217 "Infinite valid lifetime\n"
1218 "Preferred lifetime in seconds\n"
1219 "Infinite preferred lifetime\n"
1220 "Do not use prefix for autoconfiguration\n"
1221 "Do not use prefix for onlink determination\n"
1222 "Set Router Address flag\n")
1223
1224ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001225 ipv6_nd_prefix_val_noauto_cmd,
1226 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1227 "(<0-4294967295>|infinite) (no-autoconfig|)",
1228 "Interface IPv6 config commands\n"
1229 "Neighbor discovery\n"
1230 "Prefix information\n"
1231 "IPv6 prefix\n"
1232 "Valid lifetime in seconds\n"
1233 "Infinite valid lifetime\n"
1234 "Preferred lifetime in seconds\n"
1235 "Infinite preferred lifetime\n"
vincent7cee1bb2005-03-25 13:08:53 +00001236 "Do not use prefix for autoconfiguration")
hasso3e31cde2004-05-18 11:58:59 +00001237
1238ALIAS (ipv6_nd_prefix,
1239 ipv6_nd_prefix_val_offlink_cmd,
1240 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1241 "(<0-4294967295>|infinite) (off-link|)",
1242 "Interface IPv6 config commands\n"
1243 "Neighbor discovery\n"
1244 "Prefix information\n"
1245 "IPv6 prefix\n"
1246 "Valid lifetime in seconds\n"
1247 "Infinite valid lifetime\n"
1248 "Preferred lifetime in seconds\n"
1249 "Infinite preferred lifetime\n"
1250 "Do not use prefix for onlink determination\n")
1251
1252ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001253 ipv6_nd_prefix_val_rtaddr_cmd,
1254 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1255 "(<0-4294967295>|infinite) (router-address|)",
1256 "Interface IPv6 config commands\n"
1257 "Neighbor discovery\n"
1258 "Prefix information\n"
1259 "IPv6 prefix\n"
1260 "Valid lifetime in seconds\n"
1261 "Infinite valid lifetime\n"
1262 "Preferred lifetime in seconds\n"
1263 "Infinite preferred lifetime\n"
1264 "Set Router Address flag\n")
1265
1266ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001267 ipv6_nd_prefix_val_cmd,
1268 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1269 "(<0-4294967295>|infinite)",
1270 "Interface IPv6 config commands\n"
1271 "Neighbor discovery\n"
1272 "Prefix information\n"
1273 "IPv6 prefix\n"
1274 "Valid lifetime in seconds\n"
1275 "Infinite valid lifetime\n"
1276 "Preferred lifetime in seconds\n"
1277 "Infinite preferred lifetime\n")
1278
1279ALIAS (ipv6_nd_prefix,
1280 ipv6_nd_prefix_noval_cmd,
1281 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1282 "Interface IPv6 config commands\n"
1283 "Neighbor discovery\n"
1284 "Prefix information\n"
1285 "IPv6 prefix\n"
1286 "Do not use prefix for autoconfiguration\n"
1287 "Do not use prefix for onlink determination\n")
1288
1289ALIAS (ipv6_nd_prefix,
1290 ipv6_nd_prefix_noval_rev_cmd,
1291 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1292 "Interface IPv6 config commands\n"
1293 "Neighbor discovery\n"
1294 "Prefix information\n"
1295 "IPv6 prefix\n"
1296 "Do not use prefix for onlink determination\n"
1297 "Do not use prefix for autoconfiguration\n")
1298
1299ALIAS (ipv6_nd_prefix,
1300 ipv6_nd_prefix_noval_noauto_cmd,
1301 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1302 "Interface IPv6 config commands\n"
1303 "Neighbor discovery\n"
1304 "Prefix information\n"
1305 "IPv6 prefix\n"
1306 "Do not use prefix for autoconfiguration\n")
1307
1308ALIAS (ipv6_nd_prefix,
1309 ipv6_nd_prefix_noval_offlink_cmd,
1310 "ipv6 nd prefix X:X::X:X/M (off-link|)",
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
1317ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001318 ipv6_nd_prefix_noval_rtaddr_cmd,
1319 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1320 "Interface IPv6 config commands\n"
1321 "Neighbor discovery\n"
1322 "Prefix information\n"
1323 "IPv6 prefix\n"
1324 "Set Router Address flag\n")
1325
1326ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001327 ipv6_nd_prefix_prefix_cmd,
1328 "ipv6 nd prefix X:X::X:X/M",
1329 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001330 "Neighbor discovery\n"
1331 "Prefix information\n"
1332 "IPv6 prefix\n")
1333
hasso3e31cde2004-05-18 11:58:59 +00001334DEFUN (no_ipv6_nd_prefix,
1335 no_ipv6_nd_prefix_cmd,
1336 "no ipv6 nd prefix IPV6PREFIX",
paul718e3742002-12-13 20:15:29 +00001337 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001338 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001339 "Neighbor discovery\n"
1340 "Prefix information\n"
1341 "IPv6 prefix\n")
1342{
1343 int ret;
1344 struct interface *ifp;
1345 struct zebra_if *zebra_if;
1346 struct rtadv_prefix rp;
1347
1348 ifp = (struct interface *) vty->index;
1349 zebra_if = ifp->info;
1350
1351 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1352 if (!ret)
1353 {
1354 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1355 return CMD_WARNING;
1356 }
1357
1358 ret = rtadv_prefix_reset (zebra_if, &rp);
1359 if (!ret)
1360 {
1361 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1362 return CMD_WARNING;
1363 }
1364
1365 return CMD_SUCCESS;
1366}
paul718e3742002-12-13 20:15:29 +00001367/* Write configuration about router advertisement. */
1368void
1369rtadv_config_write (struct vty *vty, struct interface *ifp)
1370{
1371 struct zebra_if *zif;
hasso52dc7ee2004-09-23 19:18:23 +00001372 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001373 struct rtadv_prefix *rprefix;
1374 u_char buf[INET6_ADDRSTRLEN];
vincent7cee1bb2005-03-25 13:08:53 +00001375 int interval;
paul718e3742002-12-13 20:15:29 +00001376
1377 if (! rtadv)
1378 return;
1379
1380 zif = ifp->info;
1381
1382 if (! if_is_loopback (ifp))
1383 {
1384 if (zif->rtadv.AdvSendAdvertisements)
1385 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1386 else
1387 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1388 }
1389
vincent7cee1bb2005-03-25 13:08:53 +00001390
1391 interval = zif->rtadv.MaxRtrAdvInterval;
1392 if (interval % 1000)
1393 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1394 VTY_NEWLINE);
1395 else
1396 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1397 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
paul718e3742002-12-13 20:15:29 +00001398 VTY_NEWLINE);
1399
1400 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1401 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1402 VTY_NEWLINE);
1403
1404 if (zif->rtadv.AdvReachableTime)
1405 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1406 VTY_NEWLINE);
1407
1408 if (zif->rtadv.AdvManagedFlag)
1409 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1410
1411 if (zif->rtadv.AdvOtherConfigFlag)
1412 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1413
paul1eb8ef22005-04-07 07:30:20 +00001414 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +00001415 {
hasso3e31cde2004-05-18 11:58:59 +00001416 vty_out (vty, " ipv6 nd prefix %s/%d",
paul718e3742002-12-13 20:15:29 +00001417 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
hassoc9e52be2004-09-26 16:09:34 +00001418 (char *) buf, INET6_ADDRSTRLEN),
hasso3e31cde2004-05-18 11:58:59 +00001419 rprefix->prefix.prefixlen);
1420 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1421 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1422 {
1423 if (rprefix->AdvValidLifetime == UINT32_MAX)
1424 vty_out (vty, " infinite");
1425 else
1426 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1427 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1428 vty_out (vty, " infinite");
1429 else
1430 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1431 }
1432 if (!rprefix->AdvOnLinkFlag)
1433 vty_out (vty, " off-link");
1434 if (!rprefix->AdvAutonomousFlag)
1435 vty_out (vty, " no-autoconfig");
vincent7cee1bb2005-03-25 13:08:53 +00001436 if (rprefix->AdvRouterAddressFlag)
1437 vty_out (vty, " router-address");
paul718e3742002-12-13 20:15:29 +00001438 vty_out (vty, "%s", VTY_NEWLINE);
1439 }
1440}
1441
paul718e3742002-12-13 20:15:29 +00001442
paula1ac18c2005-06-28 17:17:12 +00001443static void
paul718e3742002-12-13 20:15:29 +00001444rtadv_event (enum rtadv_event event, int val)
1445{
1446 switch (event)
1447 {
1448 case RTADV_START:
1449 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001450 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001451 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001452 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1453 NULL, 0);
paul718e3742002-12-13 20:15:29 +00001454 break;
1455 case RTADV_STOP:
1456 if (rtadv->ra_timer)
1457 {
1458 thread_cancel (rtadv->ra_timer);
1459 rtadv->ra_timer = NULL;
1460 }
1461 if (rtadv->ra_read)
1462 {
1463 thread_cancel (rtadv->ra_read);
1464 rtadv->ra_read = NULL;
1465 }
1466 break;
1467 case RTADV_TIMER:
1468 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001469 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1470 val);
paul718e3742002-12-13 20:15:29 +00001471 break;
vincent7cee1bb2005-03-25 13:08:53 +00001472 case RTADV_TIMER_MSEC:
1473 if (! rtadv->ra_timer)
1474 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1475 NULL, val);
1476 break;
paul718e3742002-12-13 20:15:29 +00001477 case RTADV_READ:
1478 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001479 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001480 break;
1481 default:
1482 break;
1483 }
1484 return;
1485}
1486
1487void
paula1ac18c2005-06-28 17:17:12 +00001488rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001489{
1490 int sock;
1491
1492 sock = rtadv_make_socket ();
1493 if (sock < 0)
1494 return;
1495
1496 rtadv = rtadv_new ();
1497 rtadv->sock = sock;
1498
1499 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1500 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
paul718e3742002-12-13 20:15:29 +00001501 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001502 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
paul718e3742002-12-13 20:15:29 +00001503 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1504 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1505 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1506 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1507 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1508 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1509 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1510 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1511 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001512 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1513 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1514 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1515 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1516 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1517 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1518 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1519 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001520 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001521 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1522 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001523 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1524 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1525 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001526 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001527 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1528 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1529 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1530 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1531 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001532 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001533 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1534 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
paul718e3742002-12-13 20:15:29 +00001535}
1536
paula1ac18c2005-06-28 17:17:12 +00001537static int
paul718e3742002-12-13 20:15:29 +00001538if_join_all_router (int sock, struct interface *ifp)
1539{
1540 int ret;
1541
1542 struct ipv6_mreq mreq;
1543
1544 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1545 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1546 mreq.ipv6mr_interface = ifp->ifindex;
1547
1548 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1549 (char *) &mreq, sizeof mreq);
1550 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001551 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001552
1553 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1554
1555 return 0;
1556}
1557
paula1ac18c2005-06-28 17:17:12 +00001558static int
paul718e3742002-12-13 20:15:29 +00001559if_leave_all_router (int sock, struct interface *ifp)
1560{
1561 int ret;
1562
1563 struct ipv6_mreq mreq;
1564
1565 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1566 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1567 mreq.ipv6mr_interface = ifp->ifindex;
1568
1569 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1570 (char *) &mreq, sizeof mreq);
1571 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001572 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001573
1574 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1575
1576 return 0;
1577}
1578
1579#else
1580void
paula1ac18c2005-06-28 17:17:12 +00001581rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001582{
1583 /* Empty.*/;
1584}
1585#endif /* RTADV && HAVE_IPV6 */