blob: ff96648a15d2d22359513a30431f5c9c121669f4 [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;
295 buf[len++] = (sdl->sdl_alen + 2) >> 3;
296
297 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
298 len += sdl->sdl_alen;
299 }
300#else
301 if (ifp->hw_addr_len != 0)
302 {
303 buf[len++] = ND_OPT_SOURCE_LINKADDR;
304 buf[len++] = (ifp->hw_addr_len + 2) >> 3;
305
306 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
307 len += ifp->hw_addr_len;
308 }
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000309#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000310
311 msg.msg_name = (void *) &addr;
312 msg.msg_namelen = sizeof (struct sockaddr_in6);
313 msg.msg_iov = &iov;
314 msg.msg_iovlen = 1;
315 msg.msg_control = (void *) adata;
gdtf841e022004-08-11 19:20:01 +0000316 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
gdt57492d52004-08-11 18:06:38 +0000317 msg.msg_flags = 0;
paul718e3742002-12-13 20:15:29 +0000318 iov.iov_base = buf;
319 iov.iov_len = len;
320
ajsb99760a2005-01-04 16:24:43 +0000321 cmsgptr = ZCMSG_FIRSTHDR(&msg);
gdt57492d52004-08-11 18:06:38 +0000322 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
paul718e3742002-12-13 20:15:29 +0000323 cmsgptr->cmsg_level = IPPROTO_IPV6;
324 cmsgptr->cmsg_type = IPV6_PKTINFO;
gdt80893812004-08-11 15:58:00 +0000325
paul718e3742002-12-13 20:15:29 +0000326 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
327 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
328 pkt->ipi6_ifindex = ifp->ifindex;
329
330 ret = sendmsg (sock, &msg, 0);
gdt9ccabd12004-01-06 18:23:02 +0000331 if (ret < 0)
332 {
333 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
ajs6099b3b2004-11-20 02:06:59 +0000334 errno, safe_strerror(errno));
gdt9ccabd12004-01-06 18:23:02 +0000335 }
paul718e3742002-12-13 20:15:29 +0000336}
337
paula1ac18c2005-06-28 17:17:12 +0000338static int
paul718e3742002-12-13 20:15:29 +0000339rtadv_timer (struct thread *thread)
340{
paul1eb8ef22005-04-07 07:30:20 +0000341 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000342 struct interface *ifp;
343 struct zebra_if *zif;
vincent7cee1bb2005-03-25 13:08:53 +0000344 int period;
paul718e3742002-12-13 20:15:29 +0000345
346 rtadv->ra_timer = NULL;
vincent7cee1bb2005-03-25 13:08:53 +0000347 if (rtadv->adv_msec_if_count == 0)
348 {
349 period = 1000; /* 1 s */
350 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
351 }
352 else
353 {
354 period = 10; /* 10 ms */
355 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
356 }
paul718e3742002-12-13 20:15:29 +0000357
paul1eb8ef22005-04-07 07:30:20 +0000358 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
paul718e3742002-12-13 20:15:29 +0000359 {
paul718e3742002-12-13 20:15:29 +0000360 if (if_is_loopback (ifp))
361 continue;
362
363 zif = ifp->info;
364
365 if (zif->rtadv.AdvSendAdvertisements)
vincent7cee1bb2005-03-25 13:08:53 +0000366 {
367 zif->rtadv.AdvIntervalTimer -= period;
368 if (zif->rtadv.AdvIntervalTimer <= 0)
369 {
370 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
371 rtadv_send_packet (rtadv->sock, ifp);
372 }
373 }
paul718e3742002-12-13 20:15:29 +0000374 }
375 return 0;
376}
377
paula1ac18c2005-06-28 17:17:12 +0000378static void
paul718e3742002-12-13 20:15:29 +0000379rtadv_process_solicit (struct interface *ifp)
380{
381 zlog_info ("Router solicitation received on %s", ifp->name);
382
383 rtadv_send_packet (rtadv->sock, ifp);
384}
385
paula1ac18c2005-06-28 17:17:12 +0000386static void
387rtadv_process_advert (void)
paul718e3742002-12-13 20:15:29 +0000388{
389 zlog_info ("Router advertisement received");
390}
391
paula1ac18c2005-06-28 17:17:12 +0000392static void
hassofce954f2004-10-07 20:29:24 +0000393rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
paul718e3742002-12-13 20:15:29 +0000394{
395 struct icmp6_hdr *icmph;
396 struct interface *ifp;
397 struct zebra_if *zif;
398
399 /* Interface search. */
400 ifp = if_lookup_by_index (ifindex);
401 if (ifp == NULL)
402 {
403 zlog_warn ("Unknown interface index: %d", ifindex);
404 return;
405 }
406
407 if (if_is_loopback (ifp))
408 return;
409
410 /* Check interface configuration. */
411 zif = ifp->info;
412 if (! zif->rtadv.AdvSendAdvertisements)
413 return;
414
415 /* ICMP message length check. */
416 if (len < sizeof (struct icmp6_hdr))
417 {
418 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
419 return;
420 }
421
422 icmph = (struct icmp6_hdr *) buf;
423
424 /* ICMP message type check. */
425 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
426 icmph->icmp6_type != ND_ROUTER_ADVERT)
427 {
428 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
429 return;
430 }
431
432 /* Hoplimit check. */
433 if (hoplimit >= 0 && hoplimit != 255)
434 {
435 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
436 hoplimit);
437 return;
438 }
439
440 /* Check ICMP message type. */
441 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
442 rtadv_process_solicit (ifp);
443 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
444 rtadv_process_advert ();
445
446 return;
447}
448
paula1ac18c2005-06-28 17:17:12 +0000449static int
paul718e3742002-12-13 20:15:29 +0000450rtadv_read (struct thread *thread)
451{
452 int sock;
453 int len;
454 u_char buf[RTADV_MSG_SIZE];
455 struct sockaddr_in6 from;
456 unsigned int ifindex;
457 int hoplimit = -1;
458
459 sock = THREAD_FD (thread);
460 rtadv->ra_read = NULL;
461
462 /* Register myself. */
463 rtadv_event (RTADV_READ, sock);
464
465 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
466
467 if (len < 0)
468 {
ajs6099b3b2004-11-20 02:06:59 +0000469 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000470 return len;
471 }
472
hassofce954f2004-10-07 20:29:24 +0000473 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
paul718e3742002-12-13 20:15:29 +0000474
475 return 0;
476}
477
paula1ac18c2005-06-28 17:17:12 +0000478static int
paul718e3742002-12-13 20:15:29 +0000479rtadv_make_socket (void)
480{
481 int sock;
482 int ret;
483 struct icmp6_filter filter;
484
pauledd7c242003-06-04 13:59:38 +0000485 if ( zserv_privs.change (ZPRIVS_RAISE) )
486 zlog_err ("rtadv_make_socket: could not raise privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000487 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000488
paul718e3742002-12-13 20:15:29 +0000489 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
490
pauledd7c242003-06-04 13:59:38 +0000491 if ( zserv_privs.change (ZPRIVS_LOWER) )
492 zlog_err ("rtadv_make_socket: could not lower privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000493 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000494
paul718e3742002-12-13 20:15:29 +0000495 /* When we can't make ICMPV6 socket simply back. Router
496 advertisement feature will not be supported. */
497 if (sock < 0)
498 return -1;
499
500 ret = setsockopt_ipv6_pktinfo (sock, 1);
501 if (ret < 0)
502 return ret;
paul718e3742002-12-13 20:15:29 +0000503 ret = setsockopt_ipv6_multicast_loop (sock, 0);
504 if (ret < 0)
505 return ret;
506 ret = setsockopt_ipv6_unicast_hops (sock, 255);
507 if (ret < 0)
508 return ret;
509 ret = setsockopt_ipv6_multicast_hops (sock, 255);
510 if (ret < 0)
511 return ret;
512 ret = setsockopt_ipv6_hoplimit (sock, 1);
513 if (ret < 0)
514 return ret;
515
516 ICMP6_FILTER_SETBLOCKALL(&filter);
517 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
518 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
519
520 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
521 sizeof (struct icmp6_filter));
522 if (ret < 0)
523 {
ajs6099b3b2004-11-20 02:06:59 +0000524 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000525 return ret;
526 }
527
528 return sock;
529}
530
paula1ac18c2005-06-28 17:17:12 +0000531static struct rtadv_prefix *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800532rtadv_prefix_new (void)
paul718e3742002-12-13 20:15:29 +0000533{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700534 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
paul718e3742002-12-13 20:15:29 +0000535}
536
paula1ac18c2005-06-28 17:17:12 +0000537static void
paul718e3742002-12-13 20:15:29 +0000538rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
539{
540 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
541}
542
paula1ac18c2005-06-28 17:17:12 +0000543static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000544rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000545{
hasso52dc7ee2004-09-23 19:18:23 +0000546 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000547 struct rtadv_prefix *rprefix;
548
paul1eb8ef22005-04-07 07:30:20 +0000549 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
550 if (prefix_same (&rprefix->prefix, p))
551 return rprefix;
paul718e3742002-12-13 20:15:29 +0000552 return NULL;
553}
554
paula1ac18c2005-06-28 17:17:12 +0000555static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000556rtadv_prefix_get (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000557{
558 struct rtadv_prefix *rprefix;
559
560 rprefix = rtadv_prefix_lookup (rplist, p);
561 if (rprefix)
562 return rprefix;
563
564 rprefix = rtadv_prefix_new ();
565 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
566 listnode_add (rplist, rprefix);
567
568 return rprefix;
569}
570
paula1ac18c2005-06-28 17:17:12 +0000571static void
paul718e3742002-12-13 20:15:29 +0000572rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
573{
574 struct rtadv_prefix *rprefix;
575
576 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
577
578 /* Set parameters. */
579 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
580 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
581 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
582 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
vincent7cee1bb2005-03-25 13:08:53 +0000583 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
paul718e3742002-12-13 20:15:29 +0000584}
585
paula1ac18c2005-06-28 17:17:12 +0000586static int
paul718e3742002-12-13 20:15:29 +0000587rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
588{
589 struct rtadv_prefix *rprefix;
590
591 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
592 if (rprefix != NULL)
593 {
594 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
595 rtadv_prefix_free (rprefix);
596 return 1;
597 }
598 else
599 return 0;
600}
601
602DEFUN (ipv6_nd_suppress_ra,
603 ipv6_nd_suppress_ra_cmd,
604 "ipv6 nd suppress-ra",
hasso3e31cde2004-05-18 11:58:59 +0000605 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000606 "Neighbor discovery\n"
607 "Suppress Router Advertisement\n")
608{
609 struct interface *ifp;
610 struct zebra_if *zif;
611
612 ifp = vty->index;
613 zif = ifp->info;
614
615 if (if_is_loopback (ifp))
616 {
617 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
618 return CMD_WARNING;
619 }
620
621 if (zif->rtadv.AdvSendAdvertisements)
622 {
623 zif->rtadv.AdvSendAdvertisements = 0;
624 zif->rtadv.AdvIntervalTimer = 0;
625 rtadv->adv_if_count--;
626
627 if_leave_all_router (rtadv->sock, ifp);
628
629 if (rtadv->adv_if_count == 0)
630 rtadv_event (RTADV_STOP, 0);
631 }
632
633 return CMD_SUCCESS;
634}
635
paul718e3742002-12-13 20:15:29 +0000636DEFUN (no_ipv6_nd_suppress_ra,
637 no_ipv6_nd_suppress_ra_cmd,
638 "no ipv6 nd suppress-ra",
639 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000640 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000641 "Neighbor discovery\n"
642 "Suppress Router Advertisement\n")
643{
644 struct interface *ifp;
645 struct zebra_if *zif;
646
647 ifp = vty->index;
648 zif = ifp->info;
649
650 if (if_is_loopback (ifp))
651 {
652 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
653 return CMD_WARNING;
654 }
655
656 if (! zif->rtadv.AdvSendAdvertisements)
657 {
658 zif->rtadv.AdvSendAdvertisements = 1;
659 zif->rtadv.AdvIntervalTimer = 0;
660 rtadv->adv_if_count++;
661
662 if_join_all_router (rtadv->sock, ifp);
663
664 if (rtadv->adv_if_count == 1)
665 rtadv_event (RTADV_START, rtadv->sock);
666 }
667
668 return CMD_SUCCESS;
669}
670
vincent7cee1bb2005-03-25 13:08:53 +0000671DEFUN (ipv6_nd_ra_interval_msec,
672 ipv6_nd_ra_interval_msec_cmd,
673 "ipv6 nd ra-interval msec MILLISECONDS",
674 "Interface IPv6 config commands\n"
675 "Neighbor discovery\n"
676 "Router Advertisement interval\n"
677 "Router Advertisement interval in milliseconds\n")
678{
679 int interval;
680 struct interface *ifp;
681 struct zebra_if *zif;
682
683 ifp = (struct interface *) vty->index;
684 zif = ifp->info;
685
686 interval = atoi (argv[0]);
687
688 if (interval <= 0)
689 {
690 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
691 return CMD_WARNING;
692 }
693
694 if (zif->rtadv.MaxRtrAdvInterval % 1000)
695 rtadv->adv_msec_if_count--;
696
697 if (interval % 1000)
698 rtadv->adv_msec_if_count++;
699
700 zif->rtadv.MaxRtrAdvInterval = interval;
701 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
702 zif->rtadv.AdvIntervalTimer = 0;
703
704 return CMD_SUCCESS;
705}
706
paul718e3742002-12-13 20:15:29 +0000707DEFUN (ipv6_nd_ra_interval,
708 ipv6_nd_ra_interval_cmd,
709 "ipv6 nd ra-interval SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000710 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000711 "Neighbor discovery\n"
712 "Router Advertisement interval\n"
713 "Router Advertisement interval in seconds\n")
714{
715 int interval;
716 struct interface *ifp;
717 struct zebra_if *zif;
718
719 ifp = (struct interface *) vty->index;
720 zif = ifp->info;
721
722 interval = atoi (argv[0]);
723
vincent7cee1bb2005-03-25 13:08:53 +0000724 if (interval <= 0)
paul718e3742002-12-13 20:15:29 +0000725 {
726 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
727 return CMD_WARNING;
728 }
729
vincent7cee1bb2005-03-25 13:08:53 +0000730 if (zif->rtadv.MaxRtrAdvInterval % 1000)
731 rtadv->adv_msec_if_count--;
732
733 /* convert to milliseconds */
734 interval = interval * 1000;
735
paul718e3742002-12-13 20:15:29 +0000736 zif->rtadv.MaxRtrAdvInterval = interval;
737 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
738 zif->rtadv.AdvIntervalTimer = 0;
739
740 return CMD_SUCCESS;
741}
742
743DEFUN (no_ipv6_nd_ra_interval,
744 no_ipv6_nd_ra_interval_cmd,
745 "no ipv6 nd ra-interval",
746 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000747 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000748 "Neighbor discovery\n"
749 "Router Advertisement interval\n")
750{
751 struct interface *ifp;
752 struct zebra_if *zif;
753
754 ifp = (struct interface *) vty->index;
755 zif = ifp->info;
756
vincent7cee1bb2005-03-25 13:08:53 +0000757 if (zif->rtadv.MaxRtrAdvInterval % 1000)
758 rtadv->adv_msec_if_count--;
759
paul718e3742002-12-13 20:15:29 +0000760 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
761 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
762 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
763
764 return CMD_SUCCESS;
765}
766
767DEFUN (ipv6_nd_ra_lifetime,
768 ipv6_nd_ra_lifetime_cmd,
769 "ipv6 nd ra-lifetime SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000770 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000771 "Neighbor discovery\n"
772 "Router lifetime\n"
773 "Router lifetime in seconds\n")
774{
775 int lifetime;
776 struct interface *ifp;
777 struct zebra_if *zif;
778
779 ifp = (struct interface *) vty->index;
780 zif = ifp->info;
781
782 lifetime = atoi (argv[0]);
783
784 if (lifetime < 0 || lifetime > 0xffff)
785 {
786 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
787 return CMD_WARNING;
788 }
789
790 zif->rtadv.AdvDefaultLifetime = lifetime;
791
792 return CMD_SUCCESS;
793}
794
795DEFUN (no_ipv6_nd_ra_lifetime,
796 no_ipv6_nd_ra_lifetime_cmd,
797 "no ipv6 nd ra-lifetime",
798 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000799 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000800 "Neighbor discovery\n"
801 "Router lifetime\n")
802{
803 struct interface *ifp;
804 struct zebra_if *zif;
805
806 ifp = (struct interface *) vty->index;
807 zif = ifp->info;
808
809 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
810
811 return CMD_SUCCESS;
812}
813
814DEFUN (ipv6_nd_reachable_time,
815 ipv6_nd_reachable_time_cmd,
816 "ipv6 nd reachable-time MILLISECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000817 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000818 "Neighbor discovery\n"
819 "Reachable time\n"
820 "Reachable time in milliseconds\n")
821{
822 u_int32_t rtime;
823 struct interface *ifp;
824 struct zebra_if *zif;
825
826 ifp = (struct interface *) vty->index;
827 zif = ifp->info;
828
829 rtime = (u_int32_t) atol (argv[0]);
830
831 if (rtime > RTADV_MAX_REACHABLE_TIME)
832 {
833 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
834 return CMD_WARNING;
835 }
836
837 zif->rtadv.AdvReachableTime = rtime;
838
839 return CMD_SUCCESS;
840}
841
842DEFUN (no_ipv6_nd_reachable_time,
843 no_ipv6_nd_reachable_time_cmd,
844 "no ipv6 nd reachable-time",
845 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000846 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000847 "Neighbor discovery\n"
848 "Reachable time\n")
849{
850 struct interface *ifp;
851 struct zebra_if *zif;
852
853 ifp = (struct interface *) vty->index;
854 zif = ifp->info;
855
856 zif->rtadv.AdvReachableTime = 0;
857
858 return CMD_SUCCESS;
859}
860
vincent7cee1bb2005-03-25 13:08:53 +0000861DEFUN (ipv6_nd_homeagent_preference,
862 ipv6_nd_homeagent_preference_cmd,
863 "ipv6 nd home-agent-preference PREFERENCE",
864 "Interface IPv6 config commands\n"
865 "Neighbor discovery\n"
866 "Home Agent preference\n"
867 "Home Agent preference value 0..65535\n")
868{
869 u_int32_t hapref;
870 struct interface *ifp;
871 struct zebra_if *zif;
872
873 ifp = (struct interface *) vty->index;
874 zif = ifp->info;
875
876 hapref = (u_int32_t) atol (argv[0]);
877
878 if (hapref > 65535)
879 {
880 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
881 return CMD_WARNING;
882 }
883
884 zif->rtadv.HomeAgentPreference = hapref;
885
886 return CMD_SUCCESS;
887}
888
889DEFUN (no_ipv6_nd_homeagent_preference,
890 no_ipv6_nd_homeagent_preference_cmd,
891 "no ipv6 nd home-agent-preference",
892 NO_STR
893 "Interface IPv6 config commands\n"
894 "Neighbor discovery\n"
895 "Home Agent preference\n")
896{
897 struct interface *ifp;
898 struct zebra_if *zif;
899
900 ifp = (struct interface *) vty->index;
901 zif = ifp->info;
902
903 zif->rtadv.HomeAgentPreference = 0;
904
905 return CMD_SUCCESS;
906}
907
908DEFUN (ipv6_nd_homeagent_lifetime,
909 ipv6_nd_homeagent_lifetime_cmd,
910 "ipv6 nd home-agent-lifetime SECONDS",
911 "Interface IPv6 config commands\n"
912 "Neighbor discovery\n"
913 "Home Agent lifetime\n"
914 "Home Agent lifetime in seconds\n")
915{
916 u_int32_t ha_ltime;
917 struct interface *ifp;
918 struct zebra_if *zif;
919
920 ifp = (struct interface *) vty->index;
921 zif = ifp->info;
922
923 ha_ltime = (u_int32_t) atol (argv[0]);
924
925 if (ha_ltime > RTADV_MAX_HALIFETIME)
926 {
927 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
928 return CMD_WARNING;
929 }
930
931 zif->rtadv.HomeAgentLifetime = ha_ltime;
932
933 return CMD_SUCCESS;
934}
935
936DEFUN (no_ipv6_nd_homeagent_lifetime,
937 no_ipv6_nd_homeagent_lifetime_cmd,
938 "no ipv6 nd home-agent-lifetime",
939 NO_STR
940 "Interface IPv6 config commands\n"
941 "Neighbor discovery\n"
942 "Home Agent lifetime\n")
943{
944 struct interface *ifp;
945 struct zebra_if *zif;
946
947 ifp = (struct interface *) vty->index;
948 zif = ifp->info;
949
950 zif->rtadv.HomeAgentLifetime = 0;
951
952 return CMD_SUCCESS;
953}
954
paul718e3742002-12-13 20:15:29 +0000955DEFUN (ipv6_nd_managed_config_flag,
956 ipv6_nd_managed_config_flag_cmd,
957 "ipv6 nd managed-config-flag",
hasso3e31cde2004-05-18 11:58:59 +0000958 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000959 "Neighbor discovery\n"
960 "Managed address configuration flag\n")
961{
962 struct interface *ifp;
963 struct zebra_if *zif;
964
965 ifp = (struct interface *) vty->index;
966 zif = ifp->info;
967
968 zif->rtadv.AdvManagedFlag = 1;
969
970 return CMD_SUCCESS;
971}
972
973DEFUN (no_ipv6_nd_managed_config_flag,
974 no_ipv6_nd_managed_config_flag_cmd,
975 "no ipv6 nd managed-config-flag",
976 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000977 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000978 "Neighbor discovery\n"
979 "Managed address configuration flag\n")
980{
981 struct interface *ifp;
982 struct zebra_if *zif;
983
984 ifp = (struct interface *) vty->index;
985 zif = ifp->info;
986
987 zif->rtadv.AdvManagedFlag = 0;
988
989 return CMD_SUCCESS;
990}
991
vincent7cee1bb2005-03-25 13:08:53 +0000992DEFUN (ipv6_nd_homeagent_config_flag,
993 ipv6_nd_homeagent_config_flag_cmd,
994 "ipv6 nd home-agent-config-flag",
995 "Interface IPv6 config commands\n"
996 "Neighbor discovery\n"
997 "Home Agent configuration flag\n")
998{
999 struct interface *ifp;
1000 struct zebra_if *zif;
1001
1002 ifp = (struct interface *) vty->index;
1003 zif = ifp->info;
1004
1005 zif->rtadv.AdvHomeAgentFlag = 1;
1006
1007 return CMD_SUCCESS;
1008}
1009
1010DEFUN (no_ipv6_nd_homeagent_config_flag,
1011 no_ipv6_nd_homeagent_config_flag_cmd,
1012 "no ipv6 nd home-agent-config-flag",
1013 NO_STR
1014 "Interface IPv6 config commands\n"
1015 "Neighbor discovery\n"
1016 "Home Agent configuration flag\n")
1017{
1018 struct interface *ifp;
1019 struct zebra_if *zif;
1020
1021 ifp = (struct interface *) vty->index;
1022 zif = ifp->info;
1023
1024 zif->rtadv.AdvHomeAgentFlag = 0;
1025
1026 return CMD_SUCCESS;
1027}
1028
1029DEFUN (ipv6_nd_adv_interval_config_option,
1030 ipv6_nd_adv_interval_config_option_cmd,
1031 "ipv6 nd adv-interval-option",
1032 "Interface IPv6 config commands\n"
1033 "Neighbor discovery\n"
1034 "Advertisement Interval Option\n")
1035{
1036 struct interface *ifp;
1037 struct zebra_if *zif;
1038
1039 ifp = (struct interface *) vty->index;
1040 zif = ifp->info;
1041
1042 zif->rtadv.AdvIntervalOption = 1;
1043
1044 return CMD_SUCCESS;
1045}
1046
1047DEFUN (no_ipv6_nd_adv_interval_config_option,
1048 no_ipv6_nd_adv_interval_config_option_cmd,
1049 "no ipv6 nd adv-interval-option",
1050 NO_STR
1051 "Interface IPv6 config commands\n"
1052 "Neighbor discovery\n"
1053 "Advertisement Interval Option\n")
1054{
1055 struct interface *ifp;
1056 struct zebra_if *zif;
1057
1058 ifp = (struct interface *) vty->index;
1059 zif = ifp->info;
1060
1061 zif->rtadv.AdvIntervalOption = 0;
1062
1063 return CMD_SUCCESS;
1064}
1065
paul718e3742002-12-13 20:15:29 +00001066DEFUN (ipv6_nd_other_config_flag,
1067 ipv6_nd_other_config_flag_cmd,
1068 "ipv6 nd other-config-flag",
hasso3e31cde2004-05-18 11:58:59 +00001069 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001070 "Neighbor discovery\n"
1071 "Other statefull configuration flag\n")
1072{
1073 struct interface *ifp;
1074 struct zebra_if *zif;
1075
1076 ifp = (struct interface *) vty->index;
1077 zif = ifp->info;
1078
1079 zif->rtadv.AdvOtherConfigFlag = 1;
1080
1081 return CMD_SUCCESS;
1082}
1083
1084DEFUN (no_ipv6_nd_other_config_flag,
1085 no_ipv6_nd_other_config_flag_cmd,
1086 "no ipv6 nd other-config-flag",
1087 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001088 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001089 "Neighbor discovery\n"
1090 "Other statefull configuration flag\n")
1091{
1092 struct interface *ifp;
1093 struct zebra_if *zif;
1094
1095 ifp = (struct interface *) vty->index;
1096 zif = ifp->info;
1097
1098 zif->rtadv.AdvOtherConfigFlag = 0;
1099
1100 return CMD_SUCCESS;
1101}
1102
hasso3e31cde2004-05-18 11:58:59 +00001103DEFUN (ipv6_nd_prefix,
1104 ipv6_nd_prefix_cmd,
1105 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
vincent7cee1bb2005-03-25 13:08:53 +00001106 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
hasso3e31cde2004-05-18 11:58:59 +00001107 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001108 "Neighbor discovery\n"
1109 "Prefix information\n"
1110 "IPv6 prefix\n"
1111 "Valid lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001112 "Infinite valid lifetime\n"
paul718e3742002-12-13 20:15:29 +00001113 "Preferred lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001114 "Infinite preferred lifetime\n"
1115 "Do not use prefix for onlink determination\n"
vincent7cee1bb2005-03-25 13:08:53 +00001116 "Do not use prefix for autoconfiguration\n"
1117 "Set Router Address flag\n")
paul718e3742002-12-13 20:15:29 +00001118{
1119 int i;
1120 int ret;
hasso3e31cde2004-05-18 11:58:59 +00001121 int cursor = 1;
paul718e3742002-12-13 20:15:29 +00001122 struct interface *ifp;
1123 struct zebra_if *zebra_if;
1124 struct rtadv_prefix rp;
1125
1126 ifp = (struct interface *) vty->index;
1127 zebra_if = ifp->info;
1128
1129 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1130 if (!ret)
1131 {
1132 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1133 return CMD_WARNING;
1134 }
hasso3e31cde2004-05-18 11:58:59 +00001135 rp.AdvOnLinkFlag = 1;
1136 rp.AdvAutonomousFlag = 1;
vincent7cee1bb2005-03-25 13:08:53 +00001137 rp.AdvRouterAddressFlag = 0;
hasso3e31cde2004-05-18 11:58:59 +00001138 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1139 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
paul718e3742002-12-13 20:15:29 +00001140
hasso3e31cde2004-05-18 11:58:59 +00001141 if (argc > 1)
paul718e3742002-12-13 20:15:29 +00001142 {
hasso3e31cde2004-05-18 11:58:59 +00001143 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
paul718e3742002-12-13 20:15:29 +00001144 {
hasso3e31cde2004-05-18 11:58:59 +00001145 if ( strncmp (argv[1], "i", 1) == 0)
1146 rp.AdvValidLifetime = UINT32_MAX;
1147 else
1148 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1149 (char **)NULL, 10);
1150
1151 if ( strncmp (argv[2], "i", 1) == 0)
1152 rp.AdvPreferredLifetime = UINT32_MAX;
1153 else
1154 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1155 (char **)NULL, 10);
1156
1157 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1158 {
1159 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1160 return CMD_WARNING;
1161 }
1162 cursor = cursor + 2;
paul718e3742002-12-13 20:15:29 +00001163 }
hasso3e31cde2004-05-18 11:58:59 +00001164 if (argc > cursor)
paul718e3742002-12-13 20:15:29 +00001165 {
hasso3e31cde2004-05-18 11:58:59 +00001166 for (i = cursor; i < argc; i++)
1167 {
1168 if (strncmp (argv[i], "of", 2) == 0)
1169 rp.AdvOnLinkFlag = 0;
1170 if (strncmp (argv[i], "no", 2) == 0)
1171 rp.AdvAutonomousFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +00001172 if (strncmp (argv[i], "ro", 2) == 0)
1173 rp.AdvRouterAddressFlag = 1;
hasso3e31cde2004-05-18 11:58:59 +00001174 }
paul718e3742002-12-13 20:15:29 +00001175 }
1176 }
1177
1178 rtadv_prefix_set (zebra_if, &rp);
1179
1180 return CMD_SUCCESS;
1181}
1182
hasso3e31cde2004-05-18 11:58:59 +00001183ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001184 ipv6_nd_prefix_val_nortaddr_cmd,
1185 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1186 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1187 "Interface IPv6 config commands\n"
1188 "Neighbor discovery\n"
1189 "Prefix information\n"
1190 "IPv6 prefix\n"
1191 "Valid lifetime in seconds\n"
1192 "Infinite valid lifetime\n"
1193 "Preferred lifetime in seconds\n"
1194 "Infinite preferred lifetime\n"
1195 "Do not use prefix for onlink determination\n"
1196 "Do not use prefix for autoconfiguration\n")
1197
1198ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001199 ipv6_nd_prefix_val_rev_cmd,
1200 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1201 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1202 "Interface IPv6 config commands\n"
1203 "Neighbor discovery\n"
1204 "Prefix information\n"
1205 "IPv6 prefix\n"
1206 "Valid lifetime in seconds\n"
1207 "Infinite valid lifetime\n"
1208 "Preferred lifetime in seconds\n"
1209 "Infinite preferred lifetime\n"
1210 "Do not use prefix for autoconfiguration\n"
1211 "Do not use prefix for onlink determination\n")
1212
1213ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001214 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1215 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1216 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1217 "Interface IPv6 config commands\n"
1218 "Neighbor discovery\n"
1219 "Prefix information\n"
1220 "IPv6 prefix\n"
1221 "Valid lifetime in seconds\n"
1222 "Infinite valid lifetime\n"
1223 "Preferred lifetime in seconds\n"
1224 "Infinite preferred lifetime\n"
1225 "Do not use prefix for autoconfiguration\n"
1226 "Do not use prefix for onlink determination\n"
1227 "Set Router Address flag\n")
1228
1229ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001230 ipv6_nd_prefix_val_noauto_cmd,
1231 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1232 "(<0-4294967295>|infinite) (no-autoconfig|)",
1233 "Interface IPv6 config commands\n"
1234 "Neighbor discovery\n"
1235 "Prefix information\n"
1236 "IPv6 prefix\n"
1237 "Valid lifetime in seconds\n"
1238 "Infinite valid lifetime\n"
1239 "Preferred lifetime in seconds\n"
1240 "Infinite preferred lifetime\n"
vincent7cee1bb2005-03-25 13:08:53 +00001241 "Do not use prefix for autoconfiguration")
hasso3e31cde2004-05-18 11:58:59 +00001242
1243ALIAS (ipv6_nd_prefix,
1244 ipv6_nd_prefix_val_offlink_cmd,
1245 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1246 "(<0-4294967295>|infinite) (off-link|)",
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"
1255 "Do not use prefix for onlink determination\n")
1256
1257ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001258 ipv6_nd_prefix_val_rtaddr_cmd,
1259 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1260 "(<0-4294967295>|infinite) (router-address|)",
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 "Set Router Address flag\n")
1270
1271ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001272 ipv6_nd_prefix_val_cmd,
1273 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1274 "(<0-4294967295>|infinite)",
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
1284ALIAS (ipv6_nd_prefix,
1285 ipv6_nd_prefix_noval_cmd,
1286 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1287 "Interface IPv6 config commands\n"
1288 "Neighbor discovery\n"
1289 "Prefix information\n"
1290 "IPv6 prefix\n"
1291 "Do not use prefix for autoconfiguration\n"
1292 "Do not use prefix for onlink determination\n")
1293
1294ALIAS (ipv6_nd_prefix,
1295 ipv6_nd_prefix_noval_rev_cmd,
1296 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1297 "Interface IPv6 config commands\n"
1298 "Neighbor discovery\n"
1299 "Prefix information\n"
1300 "IPv6 prefix\n"
1301 "Do not use prefix for onlink determination\n"
1302 "Do not use prefix for autoconfiguration\n")
1303
1304ALIAS (ipv6_nd_prefix,
1305 ipv6_nd_prefix_noval_noauto_cmd,
1306 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1307 "Interface IPv6 config commands\n"
1308 "Neighbor discovery\n"
1309 "Prefix information\n"
1310 "IPv6 prefix\n"
1311 "Do not use prefix for autoconfiguration\n")
1312
1313ALIAS (ipv6_nd_prefix,
1314 ipv6_nd_prefix_noval_offlink_cmd,
1315 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1316 "Interface IPv6 config commands\n"
1317 "Neighbor discovery\n"
1318 "Prefix information\n"
1319 "IPv6 prefix\n"
1320 "Do not use prefix for onlink determination\n")
1321
1322ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001323 ipv6_nd_prefix_noval_rtaddr_cmd,
1324 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1325 "Interface IPv6 config commands\n"
1326 "Neighbor discovery\n"
1327 "Prefix information\n"
1328 "IPv6 prefix\n"
1329 "Set Router Address flag\n")
1330
1331ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001332 ipv6_nd_prefix_prefix_cmd,
1333 "ipv6 nd prefix X:X::X:X/M",
1334 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001335 "Neighbor discovery\n"
1336 "Prefix information\n"
1337 "IPv6 prefix\n")
1338
hasso3e31cde2004-05-18 11:58:59 +00001339DEFUN (no_ipv6_nd_prefix,
1340 no_ipv6_nd_prefix_cmd,
1341 "no ipv6 nd prefix IPV6PREFIX",
paul718e3742002-12-13 20:15:29 +00001342 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001343 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001344 "Neighbor discovery\n"
1345 "Prefix information\n"
1346 "IPv6 prefix\n")
1347{
1348 int ret;
1349 struct interface *ifp;
1350 struct zebra_if *zebra_if;
1351 struct rtadv_prefix rp;
1352
1353 ifp = (struct interface *) vty->index;
1354 zebra_if = ifp->info;
1355
1356 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1357 if (!ret)
1358 {
1359 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1360 return CMD_WARNING;
1361 }
1362
1363 ret = rtadv_prefix_reset (zebra_if, &rp);
1364 if (!ret)
1365 {
1366 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1367 return CMD_WARNING;
1368 }
1369
1370 return CMD_SUCCESS;
1371}
Chris Caputob60668d2009-05-03 04:40:57 +00001372
1373DEFUN (ipv6_nd_router_preference,
1374 ipv6_nd_router_preference_cmd,
1375 "ipv6 nd router-preference (high|medium|low)",
1376 "Interface IPv6 config commands\n"
1377 "Neighbor discovery\n"
1378 "Default router preference\n"
1379 "High default router preference\n"
1380 "Low default router preference\n"
1381 "Medium default router preference (default)\n")
1382{
1383 struct interface *ifp;
1384 struct zebra_if *zif;
1385 int i = 0;
1386
1387 ifp = (struct interface *) vty->index;
1388 zif = ifp->info;
1389
1390 while (0 != rtadv_pref_strs[i])
1391 {
1392 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1393 {
1394 zif->rtadv.DefaultPreference = i;
1395 return CMD_SUCCESS;
1396 }
1397 i++;
1398 }
1399
1400 return CMD_ERR_NO_MATCH;
1401}
1402
1403DEFUN (no_ipv6_nd_router_preference,
1404 no_ipv6_nd_router_preference_cmd,
1405 "no ipv6 nd router-preference",
1406 NO_STR
1407 "Interface IPv6 config commands\n"
1408 "Neighbor discovery\n"
1409 "Default router preference\n")
1410{
1411 struct interface *ifp;
1412 struct zebra_if *zif;
1413
1414 ifp = (struct interface *) vty->index;
1415 zif = ifp->info;
1416
1417 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1418
1419 return CMD_SUCCESS;
1420}
1421
paul718e3742002-12-13 20:15:29 +00001422/* Write configuration about router advertisement. */
1423void
1424rtadv_config_write (struct vty *vty, struct interface *ifp)
1425{
1426 struct zebra_if *zif;
hasso52dc7ee2004-09-23 19:18:23 +00001427 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001428 struct rtadv_prefix *rprefix;
1429 u_char buf[INET6_ADDRSTRLEN];
vincent7cee1bb2005-03-25 13:08:53 +00001430 int interval;
paul718e3742002-12-13 20:15:29 +00001431
1432 if (! rtadv)
1433 return;
1434
1435 zif = ifp->info;
1436
1437 if (! if_is_loopback (ifp))
1438 {
1439 if (zif->rtadv.AdvSendAdvertisements)
1440 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1441 else
1442 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1443 }
1444
vincent7cee1bb2005-03-25 13:08:53 +00001445
1446 interval = zif->rtadv.MaxRtrAdvInterval;
1447 if (interval % 1000)
1448 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1449 VTY_NEWLINE);
1450 else
1451 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1452 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
paul718e3742002-12-13 20:15:29 +00001453 VTY_NEWLINE);
1454
1455 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1456 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1457 VTY_NEWLINE);
1458
1459 if (zif->rtadv.AdvReachableTime)
1460 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1461 VTY_NEWLINE);
1462
1463 if (zif->rtadv.AdvManagedFlag)
1464 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1465
1466 if (zif->rtadv.AdvOtherConfigFlag)
1467 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1468
Chris Caputob60668d2009-05-03 04:40:57 +00001469 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1470 vty_out (vty, " ipv6 nd router-preference %s%s",
1471 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1472 VTY_NEWLINE);
1473
paul1eb8ef22005-04-07 07:30:20 +00001474 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +00001475 {
hasso3e31cde2004-05-18 11:58:59 +00001476 vty_out (vty, " ipv6 nd prefix %s/%d",
paul718e3742002-12-13 20:15:29 +00001477 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
hassoc9e52be2004-09-26 16:09:34 +00001478 (char *) buf, INET6_ADDRSTRLEN),
hasso3e31cde2004-05-18 11:58:59 +00001479 rprefix->prefix.prefixlen);
1480 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1481 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1482 {
1483 if (rprefix->AdvValidLifetime == UINT32_MAX)
1484 vty_out (vty, " infinite");
1485 else
1486 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1487 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1488 vty_out (vty, " infinite");
1489 else
1490 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1491 }
1492 if (!rprefix->AdvOnLinkFlag)
1493 vty_out (vty, " off-link");
1494 if (!rprefix->AdvAutonomousFlag)
1495 vty_out (vty, " no-autoconfig");
vincent7cee1bb2005-03-25 13:08:53 +00001496 if (rprefix->AdvRouterAddressFlag)
1497 vty_out (vty, " router-address");
paul718e3742002-12-13 20:15:29 +00001498 vty_out (vty, "%s", VTY_NEWLINE);
1499 }
1500}
1501
paul718e3742002-12-13 20:15:29 +00001502
paula1ac18c2005-06-28 17:17:12 +00001503static void
paul718e3742002-12-13 20:15:29 +00001504rtadv_event (enum rtadv_event event, int val)
1505{
1506 switch (event)
1507 {
1508 case RTADV_START:
1509 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001510 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001511 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001512 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1513 NULL, 0);
paul718e3742002-12-13 20:15:29 +00001514 break;
1515 case RTADV_STOP:
1516 if (rtadv->ra_timer)
1517 {
1518 thread_cancel (rtadv->ra_timer);
1519 rtadv->ra_timer = NULL;
1520 }
1521 if (rtadv->ra_read)
1522 {
1523 thread_cancel (rtadv->ra_read);
1524 rtadv->ra_read = NULL;
1525 }
1526 break;
1527 case RTADV_TIMER:
1528 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001529 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1530 val);
paul718e3742002-12-13 20:15:29 +00001531 break;
vincent7cee1bb2005-03-25 13:08:53 +00001532 case RTADV_TIMER_MSEC:
1533 if (! rtadv->ra_timer)
1534 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1535 NULL, val);
1536 break;
paul718e3742002-12-13 20:15:29 +00001537 case RTADV_READ:
1538 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001539 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001540 break;
1541 default:
1542 break;
1543 }
1544 return;
1545}
1546
1547void
paula1ac18c2005-06-28 17:17:12 +00001548rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001549{
1550 int sock;
1551
1552 sock = rtadv_make_socket ();
1553 if (sock < 0)
1554 return;
1555
1556 rtadv = rtadv_new ();
1557 rtadv->sock = sock;
1558
1559 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1560 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
paul718e3742002-12-13 20:15:29 +00001561 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001562 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
paul718e3742002-12-13 20:15:29 +00001563 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1564 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1565 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1566 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1567 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1568 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1569 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1570 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1571 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001572 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1573 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1574 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1575 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1576 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1577 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1578 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1579 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001580 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001581 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1582 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001583 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1584 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1585 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001586 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001587 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1588 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1589 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1590 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1591 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001592 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001593 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1594 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
Chris Caputob60668d2009-05-03 04:40:57 +00001595 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1596 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
paul718e3742002-12-13 20:15:29 +00001597}
1598
paula1ac18c2005-06-28 17:17:12 +00001599static int
paul718e3742002-12-13 20:15:29 +00001600if_join_all_router (int sock, struct interface *ifp)
1601{
1602 int ret;
1603
1604 struct ipv6_mreq mreq;
1605
1606 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1607 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1608 mreq.ipv6mr_interface = ifp->ifindex;
1609
1610 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1611 (char *) &mreq, sizeof mreq);
1612 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001613 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001614
1615 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1616
1617 return 0;
1618}
1619
paula1ac18c2005-06-28 17:17:12 +00001620static int
paul718e3742002-12-13 20:15:29 +00001621if_leave_all_router (int sock, struct interface *ifp)
1622{
1623 int ret;
1624
1625 struct ipv6_mreq mreq;
1626
1627 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1628 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1629 mreq.ipv6mr_interface = ifp->ifindex;
1630
1631 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1632 (char *) &mreq, sizeof mreq);
1633 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001634 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001635
1636 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1637
1638 return 0;
1639}
1640
1641#else
1642void
paula1ac18c2005-06-28 17:17:12 +00001643rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001644{
1645 /* Empty.*/;
1646}
1647#endif /* RTADV && HAVE_IPV6 */