blob: 8cc3c4cbebddab071c5a80aa27f78f04aad3da17 [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 int
paul718e3742002-12-13 20:15:29 +000091rtadv_recv_packet (int sock, u_char *buf, int buflen,
92 struct sockaddr_in6 *from, unsigned int *ifindex,
93 int *hoplimit)
94{
95 int ret;
96 struct msghdr msg;
97 struct iovec iov;
98 struct cmsghdr *cmsgptr;
99 struct in6_addr dst;
100
101 char adata[1024];
102
103 /* Fill in message and iovec. */
104 msg.msg_name = (void *) from;
105 msg.msg_namelen = sizeof (struct sockaddr_in6);
106 msg.msg_iov = &iov;
107 msg.msg_iovlen = 1;
108 msg.msg_control = (void *) adata;
109 msg.msg_controllen = sizeof adata;
110 iov.iov_base = buf;
111 iov.iov_len = buflen;
112
113 /* If recvmsg fail return minus value. */
114 ret = recvmsg (sock, &msg, 0);
115 if (ret < 0)
116 return ret;
117
ajsb99760a2005-01-04 16:24:43 +0000118 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
paul718e3742002-12-13 20:15:29 +0000119 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
120 {
121 /* I want interface index which this packet comes from. */
122 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
123 cmsgptr->cmsg_type == IPV6_PKTINFO)
124 {
125 struct in6_pktinfo *ptr;
126
127 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
128 *ifindex = ptr->ipi6_ifindex;
129 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
130 }
131
132 /* Incoming packet's hop limit. */
133 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
134 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
Stephen Hemmingerb0b709a2009-12-08 13:26:14 +0300135 {
136 int *hoptr = (int *) CMSG_DATA (cmsgptr);
137 *hoplimit = *hoptr;
138 }
paul718e3742002-12-13 20:15:29 +0000139 }
140 return ret;
141}
142
143#define RTADV_MSG_SIZE 4096
144
145/* Send router advertisement packet. */
paula1ac18c2005-06-28 17:17:12 +0000146static void
paul718e3742002-12-13 20:15:29 +0000147rtadv_send_packet (int sock, struct interface *ifp)
148{
149 struct msghdr msg;
150 struct iovec iov;
151 struct cmsghdr *cmsgptr;
152 struct in6_pktinfo *pkt;
153 struct sockaddr_in6 addr;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000154#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000155 struct sockaddr_dl *sdl;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000156#endif /* HAVE_STRUCT_SOCKADDR_DL */
gdt57492d52004-08-11 18:06:38 +0000157 static void *adata = NULL;
paul718e3742002-12-13 20:15:29 +0000158 unsigned char buf[RTADV_MSG_SIZE];
159 struct nd_router_advert *rtadv;
160 int ret;
161 int len = 0;
162 struct zebra_if *zif;
paul1eb8ef22005-04-07 07:30:20 +0000163 struct rtadv_prefix *rprefix;
paul718e3742002-12-13 20:15:29 +0000164 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 +0000165 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000166
gdt57492d52004-08-11 18:06:38 +0000167 /*
168 * Allocate control message bufffer. This is dynamic because
169 * CMSG_SPACE is not guaranteed not to call a function. Note that
170 * the size will be different on different architectures due to
171 * differing alignment rules.
172 */
173 if (adata == NULL)
174 {
175 /* XXX Free on shutdown. */
176 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
177
178 if (adata == NULL)
179 zlog_err("rtadv_send_packet: can't malloc control data\n");
180 }
181
paul718e3742002-12-13 20:15:29 +0000182 /* Logging of packet. */
183 if (IS_ZEBRA_DEBUG_PACKET)
ajsb6178002004-12-07 21:12:56 +0000184 zlog_debug ("Router advertisement send to %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000185
186 /* Fill in sockaddr_in6. */
187 memset (&addr, 0, sizeof (struct sockaddr_in6));
188 addr.sin6_family = AF_INET6;
189#ifdef SIN6_LEN
190 addr.sin6_len = sizeof (struct sockaddr_in6);
191#endif /* SIN6_LEN */
192 addr.sin6_port = htons (IPPROTO_ICMPV6);
193 memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
194
195 /* Fetch interface information. */
196 zif = ifp->info;
197
198 /* Make router advertisement message. */
199 rtadv = (struct nd_router_advert *) buf;
200
201 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
202 rtadv->nd_ra_code = 0;
203 rtadv->nd_ra_cksum = 0;
204
205 rtadv->nd_ra_curhoplimit = 64;
Chris Caputob60668d2009-05-03 04:40:57 +0000206
207 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
208 rtadv->nd_ra_flags_reserved =
209 zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
210 rtadv->nd_ra_flags_reserved <<= 3;
211
paul718e3742002-12-13 20:15:29 +0000212 if (zif->rtadv.AdvManagedFlag)
213 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
214 if (zif->rtadv.AdvOtherConfigFlag)
215 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
vincent7cee1bb2005-03-25 13:08:53 +0000216 if (zif->rtadv.AdvHomeAgentFlag)
217 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
paul718e3742002-12-13 20:15:29 +0000218 rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
219 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
220 rtadv->nd_ra_retransmit = htonl (0);
221
222 len = sizeof (struct nd_router_advert);
223
vincent7cee1bb2005-03-25 13:08:53 +0000224 if (zif->rtadv.AdvHomeAgentFlag)
225 {
226 struct nd_opt_homeagent_info *ndopt_hai =
227 (struct nd_opt_homeagent_info *)(buf + len);
228 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
229 ndopt_hai->nd_opt_hai_len = 1;
230 ndopt_hai->nd_opt_hai_reserved = 0;
231 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
232 ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);
233 len += sizeof(struct nd_opt_homeagent_info);
234 }
235
236 if (zif->rtadv.AdvIntervalOption)
237 {
238 struct nd_opt_adv_interval *ndopt_adv =
239 (struct nd_opt_adv_interval *)(buf + len);
240 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
241 ndopt_adv->nd_opt_ai_len = 1;
242 ndopt_adv->nd_opt_ai_reserved = 0;
243 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
244 len += sizeof(struct nd_opt_adv_interval);
245 }
246
paul718e3742002-12-13 20:15:29 +0000247 /* Fill in prefix. */
paul1eb8ef22005-04-07 07:30:20 +0000248 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +0000249 {
250 struct nd_opt_prefix_info *pinfo;
paul718e3742002-12-13 20:15:29 +0000251
252 pinfo = (struct nd_opt_prefix_info *) (buf + len);
253
254 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
255 pinfo->nd_opt_pi_len = 4;
256 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
257
258 pinfo->nd_opt_pi_flags_reserved = 0;
259 if (rprefix->AdvOnLinkFlag)
260 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
261 if (rprefix->AdvAutonomousFlag)
262 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
vincent7cee1bb2005-03-25 13:08:53 +0000263 if (rprefix->AdvRouterAddressFlag)
264 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
paul718e3742002-12-13 20:15:29 +0000265
266 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
267 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
268 pinfo->nd_opt_pi_reserved2 = 0;
269
270 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
271 sizeof (struct in6_addr));
272
273#ifdef DEBUG
274 {
275 u_char buf[INET6_ADDRSTRLEN];
276
ajsb6178002004-12-07 21:12:56 +0000277 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
hasso3e31cde2004-05-18 11:58:59 +0000278 buf, INET6_ADDRSTRLEN));
paul718e3742002-12-13 20:15:29 +0000279
280 }
281#endif /* DEBUG */
282
283 len += sizeof (struct nd_opt_prefix_info);
284 }
285
286 /* Hardware address. */
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000287#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000288 sdl = &ifp->sdl;
289 if (sdl != NULL && sdl->sdl_alen != 0)
290 {
291 buf[len++] = ND_OPT_SOURCE_LINKADDR;
David Ward50adf782009-08-31 10:42:06 -0400292
293 /* Option length should be rounded up to next octet if
294 the link address does not end on an octet boundary. */
295 buf[len++] = (sdl->sdl_alen + 9) >> 3;
paul718e3742002-12-13 20:15:29 +0000296
297 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
298 len += sdl->sdl_alen;
David Ward50adf782009-08-31 10:42:06 -0400299
300 /* Pad option to end on an octet boundary. */
301 memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
302 len += -(sdl->sdl_alen + 2) & 0x7;
paul718e3742002-12-13 20:15:29 +0000303 }
304#else
305 if (ifp->hw_addr_len != 0)
306 {
307 buf[len++] = ND_OPT_SOURCE_LINKADDR;
David Ward50adf782009-08-31 10:42:06 -0400308
309 /* Option length should be rounded up to next octet if
310 the link address does not end on an octet boundary. */
311 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
paul718e3742002-12-13 20:15:29 +0000312
313 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
314 len += ifp->hw_addr_len;
David Ward50adf782009-08-31 10:42:06 -0400315
316 /* Pad option to end on an octet boundary. */
317 memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
318 len += -(ifp->hw_addr_len + 2) & 0x7;
paul718e3742002-12-13 20:15:29 +0000319 }
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000320#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000321
322 msg.msg_name = (void *) &addr;
323 msg.msg_namelen = sizeof (struct sockaddr_in6);
324 msg.msg_iov = &iov;
325 msg.msg_iovlen = 1;
326 msg.msg_control = (void *) adata;
gdtf841e022004-08-11 19:20:01 +0000327 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
gdt57492d52004-08-11 18:06:38 +0000328 msg.msg_flags = 0;
paul718e3742002-12-13 20:15:29 +0000329 iov.iov_base = buf;
330 iov.iov_len = len;
331
ajsb99760a2005-01-04 16:24:43 +0000332 cmsgptr = ZCMSG_FIRSTHDR(&msg);
gdt57492d52004-08-11 18:06:38 +0000333 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
paul718e3742002-12-13 20:15:29 +0000334 cmsgptr->cmsg_level = IPPROTO_IPV6;
335 cmsgptr->cmsg_type = IPV6_PKTINFO;
gdt80893812004-08-11 15:58:00 +0000336
paul718e3742002-12-13 20:15:29 +0000337 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
338 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
339 pkt->ipi6_ifindex = ifp->ifindex;
340
341 ret = sendmsg (sock, &msg, 0);
gdt9ccabd12004-01-06 18:23:02 +0000342 if (ret < 0)
343 {
344 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
ajs6099b3b2004-11-20 02:06:59 +0000345 errno, safe_strerror(errno));
gdt9ccabd12004-01-06 18:23:02 +0000346 }
paul718e3742002-12-13 20:15:29 +0000347}
348
paula1ac18c2005-06-28 17:17:12 +0000349static int
paul718e3742002-12-13 20:15:29 +0000350rtadv_timer (struct thread *thread)
351{
paul1eb8ef22005-04-07 07:30:20 +0000352 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000353 struct interface *ifp;
354 struct zebra_if *zif;
vincent7cee1bb2005-03-25 13:08:53 +0000355 int period;
paul718e3742002-12-13 20:15:29 +0000356
357 rtadv->ra_timer = NULL;
vincent7cee1bb2005-03-25 13:08:53 +0000358 if (rtadv->adv_msec_if_count == 0)
359 {
360 period = 1000; /* 1 s */
361 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
362 }
363 else
364 {
365 period = 10; /* 10 ms */
366 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
367 }
paul718e3742002-12-13 20:15:29 +0000368
paul1eb8ef22005-04-07 07:30:20 +0000369 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
paul718e3742002-12-13 20:15:29 +0000370 {
paul718e3742002-12-13 20:15:29 +0000371 if (if_is_loopback (ifp))
372 continue;
373
374 zif = ifp->info;
375
376 if (zif->rtadv.AdvSendAdvertisements)
vincent7cee1bb2005-03-25 13:08:53 +0000377 {
378 zif->rtadv.AdvIntervalTimer -= period;
379 if (zif->rtadv.AdvIntervalTimer <= 0)
380 {
381 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
382 rtadv_send_packet (rtadv->sock, ifp);
383 }
384 }
paul718e3742002-12-13 20:15:29 +0000385 }
386 return 0;
387}
388
paula1ac18c2005-06-28 17:17:12 +0000389static void
paul718e3742002-12-13 20:15:29 +0000390rtadv_process_solicit (struct interface *ifp)
391{
392 zlog_info ("Router solicitation received on %s", ifp->name);
393
394 rtadv_send_packet (rtadv->sock, ifp);
395}
396
paula1ac18c2005-06-28 17:17:12 +0000397static void
398rtadv_process_advert (void)
paul718e3742002-12-13 20:15:29 +0000399{
400 zlog_info ("Router advertisement received");
401}
402
paula1ac18c2005-06-28 17:17:12 +0000403static void
hassofce954f2004-10-07 20:29:24 +0000404rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
paul718e3742002-12-13 20:15:29 +0000405{
406 struct icmp6_hdr *icmph;
407 struct interface *ifp;
408 struct zebra_if *zif;
409
410 /* Interface search. */
411 ifp = if_lookup_by_index (ifindex);
412 if (ifp == NULL)
413 {
414 zlog_warn ("Unknown interface index: %d", ifindex);
415 return;
416 }
417
418 if (if_is_loopback (ifp))
419 return;
420
421 /* Check interface configuration. */
422 zif = ifp->info;
423 if (! zif->rtadv.AdvSendAdvertisements)
424 return;
425
426 /* ICMP message length check. */
427 if (len < sizeof (struct icmp6_hdr))
428 {
429 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
430 return;
431 }
432
433 icmph = (struct icmp6_hdr *) buf;
434
435 /* ICMP message type check. */
436 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
437 icmph->icmp6_type != ND_ROUTER_ADVERT)
438 {
439 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
440 return;
441 }
442
443 /* Hoplimit check. */
444 if (hoplimit >= 0 && hoplimit != 255)
445 {
446 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
447 hoplimit);
448 return;
449 }
450
451 /* Check ICMP message type. */
452 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
453 rtadv_process_solicit (ifp);
454 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
455 rtadv_process_advert ();
456
457 return;
458}
459
paula1ac18c2005-06-28 17:17:12 +0000460static int
paul718e3742002-12-13 20:15:29 +0000461rtadv_read (struct thread *thread)
462{
463 int sock;
464 int len;
465 u_char buf[RTADV_MSG_SIZE];
466 struct sockaddr_in6 from;
Stephen Hemmingerb0b709a2009-12-08 13:26:14 +0300467 unsigned int ifindex = 0;
paul718e3742002-12-13 20:15:29 +0000468 int hoplimit = -1;
469
470 sock = THREAD_FD (thread);
471 rtadv->ra_read = NULL;
472
473 /* Register myself. */
474 rtadv_event (RTADV_READ, sock);
475
476 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
477
478 if (len < 0)
479 {
ajs6099b3b2004-11-20 02:06:59 +0000480 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000481 return len;
482 }
483
hassofce954f2004-10-07 20:29:24 +0000484 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
paul718e3742002-12-13 20:15:29 +0000485
486 return 0;
487}
488
paula1ac18c2005-06-28 17:17:12 +0000489static int
paul718e3742002-12-13 20:15:29 +0000490rtadv_make_socket (void)
491{
492 int sock;
493 int ret;
494 struct icmp6_filter filter;
495
pauledd7c242003-06-04 13:59:38 +0000496 if ( zserv_privs.change (ZPRIVS_RAISE) )
497 zlog_err ("rtadv_make_socket: could not raise privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000498 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000499
paul718e3742002-12-13 20:15:29 +0000500 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
501
pauledd7c242003-06-04 13:59:38 +0000502 if ( zserv_privs.change (ZPRIVS_LOWER) )
503 zlog_err ("rtadv_make_socket: could not lower privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000504 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000505
paul718e3742002-12-13 20:15:29 +0000506 /* When we can't make ICMPV6 socket simply back. Router
507 advertisement feature will not be supported. */
508 if (sock < 0)
509 return -1;
510
511 ret = setsockopt_ipv6_pktinfo (sock, 1);
512 if (ret < 0)
513 return ret;
paul718e3742002-12-13 20:15:29 +0000514 ret = setsockopt_ipv6_multicast_loop (sock, 0);
515 if (ret < 0)
516 return ret;
517 ret = setsockopt_ipv6_unicast_hops (sock, 255);
518 if (ret < 0)
519 return ret;
520 ret = setsockopt_ipv6_multicast_hops (sock, 255);
521 if (ret < 0)
522 return ret;
523 ret = setsockopt_ipv6_hoplimit (sock, 1);
524 if (ret < 0)
525 return ret;
526
527 ICMP6_FILTER_SETBLOCKALL(&filter);
528 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
529 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
530
531 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
532 sizeof (struct icmp6_filter));
533 if (ret < 0)
534 {
ajs6099b3b2004-11-20 02:06:59 +0000535 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000536 return ret;
537 }
538
539 return sock;
540}
541
paula1ac18c2005-06-28 17:17:12 +0000542static struct rtadv_prefix *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800543rtadv_prefix_new (void)
paul718e3742002-12-13 20:15:29 +0000544{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700545 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
paul718e3742002-12-13 20:15:29 +0000546}
547
paula1ac18c2005-06-28 17:17:12 +0000548static void
paul718e3742002-12-13 20:15:29 +0000549rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
550{
551 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
552}
553
paula1ac18c2005-06-28 17:17:12 +0000554static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000555rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000556{
hasso52dc7ee2004-09-23 19:18:23 +0000557 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000558 struct rtadv_prefix *rprefix;
559
paul1eb8ef22005-04-07 07:30:20 +0000560 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
561 if (prefix_same (&rprefix->prefix, p))
562 return rprefix;
paul718e3742002-12-13 20:15:29 +0000563 return NULL;
564}
565
paula1ac18c2005-06-28 17:17:12 +0000566static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000567rtadv_prefix_get (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000568{
569 struct rtadv_prefix *rprefix;
570
571 rprefix = rtadv_prefix_lookup (rplist, p);
572 if (rprefix)
573 return rprefix;
574
575 rprefix = rtadv_prefix_new ();
576 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
577 listnode_add (rplist, rprefix);
578
579 return rprefix;
580}
581
paula1ac18c2005-06-28 17:17:12 +0000582static void
paul718e3742002-12-13 20:15:29 +0000583rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
584{
585 struct rtadv_prefix *rprefix;
586
587 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
588
589 /* Set parameters. */
590 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
591 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
592 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
593 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
vincent7cee1bb2005-03-25 13:08:53 +0000594 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
paul718e3742002-12-13 20:15:29 +0000595}
596
paula1ac18c2005-06-28 17:17:12 +0000597static int
paul718e3742002-12-13 20:15:29 +0000598rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
599{
600 struct rtadv_prefix *rprefix;
601
602 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
603 if (rprefix != NULL)
604 {
605 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
606 rtadv_prefix_free (rprefix);
607 return 1;
608 }
609 else
610 return 0;
611}
612
613DEFUN (ipv6_nd_suppress_ra,
614 ipv6_nd_suppress_ra_cmd,
615 "ipv6 nd suppress-ra",
hasso3e31cde2004-05-18 11:58:59 +0000616 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000617 "Neighbor discovery\n"
618 "Suppress Router Advertisement\n")
619{
620 struct interface *ifp;
621 struct zebra_if *zif;
622
623 ifp = vty->index;
624 zif = ifp->info;
625
626 if (if_is_loopback (ifp))
627 {
628 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
629 return CMD_WARNING;
630 }
631
632 if (zif->rtadv.AdvSendAdvertisements)
633 {
634 zif->rtadv.AdvSendAdvertisements = 0;
635 zif->rtadv.AdvIntervalTimer = 0;
636 rtadv->adv_if_count--;
637
638 if_leave_all_router (rtadv->sock, ifp);
639
640 if (rtadv->adv_if_count == 0)
641 rtadv_event (RTADV_STOP, 0);
642 }
643
644 return CMD_SUCCESS;
645}
646
paul718e3742002-12-13 20:15:29 +0000647DEFUN (no_ipv6_nd_suppress_ra,
648 no_ipv6_nd_suppress_ra_cmd,
649 "no ipv6 nd suppress-ra",
650 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000651 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000652 "Neighbor discovery\n"
653 "Suppress Router Advertisement\n")
654{
655 struct interface *ifp;
656 struct zebra_if *zif;
657
658 ifp = vty->index;
659 zif = ifp->info;
660
661 if (if_is_loopback (ifp))
662 {
663 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
664 return CMD_WARNING;
665 }
666
667 if (! zif->rtadv.AdvSendAdvertisements)
668 {
669 zif->rtadv.AdvSendAdvertisements = 1;
670 zif->rtadv.AdvIntervalTimer = 0;
671 rtadv->adv_if_count++;
672
673 if_join_all_router (rtadv->sock, ifp);
674
675 if (rtadv->adv_if_count == 1)
676 rtadv_event (RTADV_START, rtadv->sock);
677 }
678
679 return CMD_SUCCESS;
680}
681
vincent7cee1bb2005-03-25 13:08:53 +0000682DEFUN (ipv6_nd_ra_interval_msec,
683 ipv6_nd_ra_interval_msec_cmd,
684 "ipv6 nd ra-interval msec MILLISECONDS",
685 "Interface IPv6 config commands\n"
686 "Neighbor discovery\n"
687 "Router Advertisement interval\n"
688 "Router Advertisement interval in milliseconds\n")
689{
690 int interval;
691 struct interface *ifp;
692 struct zebra_if *zif;
693
694 ifp = (struct interface *) vty->index;
695 zif = ifp->info;
696
697 interval = atoi (argv[0]);
698
699 if (interval <= 0)
700 {
701 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
702 return CMD_WARNING;
703 }
704
705 if (zif->rtadv.MaxRtrAdvInterval % 1000)
706 rtadv->adv_msec_if_count--;
707
708 if (interval % 1000)
709 rtadv->adv_msec_if_count++;
710
711 zif->rtadv.MaxRtrAdvInterval = interval;
712 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
713 zif->rtadv.AdvIntervalTimer = 0;
714
715 return CMD_SUCCESS;
716}
717
paul718e3742002-12-13 20:15:29 +0000718DEFUN (ipv6_nd_ra_interval,
719 ipv6_nd_ra_interval_cmd,
720 "ipv6 nd ra-interval SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000721 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000722 "Neighbor discovery\n"
723 "Router Advertisement interval\n"
724 "Router Advertisement interval in seconds\n")
725{
726 int interval;
727 struct interface *ifp;
728 struct zebra_if *zif;
729
730 ifp = (struct interface *) vty->index;
731 zif = ifp->info;
732
733 interval = atoi (argv[0]);
734
vincent7cee1bb2005-03-25 13:08:53 +0000735 if (interval <= 0)
paul718e3742002-12-13 20:15:29 +0000736 {
737 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
738 return CMD_WARNING;
739 }
740
vincent7cee1bb2005-03-25 13:08:53 +0000741 if (zif->rtadv.MaxRtrAdvInterval % 1000)
742 rtadv->adv_msec_if_count--;
743
744 /* convert to milliseconds */
745 interval = interval * 1000;
746
paul718e3742002-12-13 20:15:29 +0000747 zif->rtadv.MaxRtrAdvInterval = interval;
748 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
749 zif->rtadv.AdvIntervalTimer = 0;
750
751 return CMD_SUCCESS;
752}
753
754DEFUN (no_ipv6_nd_ra_interval,
755 no_ipv6_nd_ra_interval_cmd,
756 "no ipv6 nd ra-interval",
757 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000758 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000759 "Neighbor discovery\n"
760 "Router Advertisement interval\n")
761{
762 struct interface *ifp;
763 struct zebra_if *zif;
764
765 ifp = (struct interface *) vty->index;
766 zif = ifp->info;
767
vincent7cee1bb2005-03-25 13:08:53 +0000768 if (zif->rtadv.MaxRtrAdvInterval % 1000)
769 rtadv->adv_msec_if_count--;
770
paul718e3742002-12-13 20:15:29 +0000771 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
772 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
773 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
774
775 return CMD_SUCCESS;
776}
777
778DEFUN (ipv6_nd_ra_lifetime,
779 ipv6_nd_ra_lifetime_cmd,
780 "ipv6 nd ra-lifetime SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000781 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000782 "Neighbor discovery\n"
783 "Router lifetime\n"
784 "Router lifetime in seconds\n")
785{
786 int lifetime;
787 struct interface *ifp;
788 struct zebra_if *zif;
789
790 ifp = (struct interface *) vty->index;
791 zif = ifp->info;
792
793 lifetime = atoi (argv[0]);
794
795 if (lifetime < 0 || lifetime > 0xffff)
796 {
797 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
798 return CMD_WARNING;
799 }
800
801 zif->rtadv.AdvDefaultLifetime = lifetime;
802
803 return CMD_SUCCESS;
804}
805
806DEFUN (no_ipv6_nd_ra_lifetime,
807 no_ipv6_nd_ra_lifetime_cmd,
808 "no ipv6 nd ra-lifetime",
809 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000810 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000811 "Neighbor discovery\n"
812 "Router lifetime\n")
813{
814 struct interface *ifp;
815 struct zebra_if *zif;
816
817 ifp = (struct interface *) vty->index;
818 zif = ifp->info;
819
820 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
821
822 return CMD_SUCCESS;
823}
824
825DEFUN (ipv6_nd_reachable_time,
826 ipv6_nd_reachable_time_cmd,
827 "ipv6 nd reachable-time MILLISECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000828 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000829 "Neighbor discovery\n"
830 "Reachable time\n"
831 "Reachable time in milliseconds\n")
832{
833 u_int32_t rtime;
834 struct interface *ifp;
835 struct zebra_if *zif;
836
837 ifp = (struct interface *) vty->index;
838 zif = ifp->info;
839
840 rtime = (u_int32_t) atol (argv[0]);
841
842 if (rtime > RTADV_MAX_REACHABLE_TIME)
843 {
844 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
845 return CMD_WARNING;
846 }
847
848 zif->rtadv.AdvReachableTime = rtime;
849
850 return CMD_SUCCESS;
851}
852
853DEFUN (no_ipv6_nd_reachable_time,
854 no_ipv6_nd_reachable_time_cmd,
855 "no ipv6 nd reachable-time",
856 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000857 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000858 "Neighbor discovery\n"
859 "Reachable time\n")
860{
861 struct interface *ifp;
862 struct zebra_if *zif;
863
864 ifp = (struct interface *) vty->index;
865 zif = ifp->info;
866
867 zif->rtadv.AdvReachableTime = 0;
868
869 return CMD_SUCCESS;
870}
871
vincent7cee1bb2005-03-25 13:08:53 +0000872DEFUN (ipv6_nd_homeagent_preference,
873 ipv6_nd_homeagent_preference_cmd,
874 "ipv6 nd home-agent-preference PREFERENCE",
875 "Interface IPv6 config commands\n"
876 "Neighbor discovery\n"
877 "Home Agent preference\n"
878 "Home Agent preference value 0..65535\n")
879{
880 u_int32_t hapref;
881 struct interface *ifp;
882 struct zebra_if *zif;
883
884 ifp = (struct interface *) vty->index;
885 zif = ifp->info;
886
887 hapref = (u_int32_t) atol (argv[0]);
888
889 if (hapref > 65535)
890 {
891 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
892 return CMD_WARNING;
893 }
894
895 zif->rtadv.HomeAgentPreference = hapref;
896
897 return CMD_SUCCESS;
898}
899
900DEFUN (no_ipv6_nd_homeagent_preference,
901 no_ipv6_nd_homeagent_preference_cmd,
902 "no ipv6 nd home-agent-preference",
903 NO_STR
904 "Interface IPv6 config commands\n"
905 "Neighbor discovery\n"
906 "Home Agent preference\n")
907{
908 struct interface *ifp;
909 struct zebra_if *zif;
910
911 ifp = (struct interface *) vty->index;
912 zif = ifp->info;
913
914 zif->rtadv.HomeAgentPreference = 0;
915
916 return CMD_SUCCESS;
917}
918
919DEFUN (ipv6_nd_homeagent_lifetime,
920 ipv6_nd_homeagent_lifetime_cmd,
921 "ipv6 nd home-agent-lifetime SECONDS",
922 "Interface IPv6 config commands\n"
923 "Neighbor discovery\n"
924 "Home Agent lifetime\n"
925 "Home Agent lifetime in seconds\n")
926{
927 u_int32_t ha_ltime;
928 struct interface *ifp;
929 struct zebra_if *zif;
930
931 ifp = (struct interface *) vty->index;
932 zif = ifp->info;
933
934 ha_ltime = (u_int32_t) atol (argv[0]);
935
936 if (ha_ltime > RTADV_MAX_HALIFETIME)
937 {
938 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
939 return CMD_WARNING;
940 }
941
942 zif->rtadv.HomeAgentLifetime = ha_ltime;
943
944 return CMD_SUCCESS;
945}
946
947DEFUN (no_ipv6_nd_homeagent_lifetime,
948 no_ipv6_nd_homeagent_lifetime_cmd,
949 "no ipv6 nd home-agent-lifetime",
950 NO_STR
951 "Interface IPv6 config commands\n"
952 "Neighbor discovery\n"
953 "Home Agent lifetime\n")
954{
955 struct interface *ifp;
956 struct zebra_if *zif;
957
958 ifp = (struct interface *) vty->index;
959 zif = ifp->info;
960
961 zif->rtadv.HomeAgentLifetime = 0;
962
963 return CMD_SUCCESS;
964}
965
paul718e3742002-12-13 20:15:29 +0000966DEFUN (ipv6_nd_managed_config_flag,
967 ipv6_nd_managed_config_flag_cmd,
968 "ipv6 nd managed-config-flag",
hasso3e31cde2004-05-18 11:58:59 +0000969 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000970 "Neighbor discovery\n"
971 "Managed address configuration flag\n")
972{
973 struct interface *ifp;
974 struct zebra_if *zif;
975
976 ifp = (struct interface *) vty->index;
977 zif = ifp->info;
978
979 zif->rtadv.AdvManagedFlag = 1;
980
981 return CMD_SUCCESS;
982}
983
984DEFUN (no_ipv6_nd_managed_config_flag,
985 no_ipv6_nd_managed_config_flag_cmd,
986 "no ipv6 nd managed-config-flag",
987 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000988 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000989 "Neighbor discovery\n"
990 "Managed address configuration flag\n")
991{
992 struct interface *ifp;
993 struct zebra_if *zif;
994
995 ifp = (struct interface *) vty->index;
996 zif = ifp->info;
997
998 zif->rtadv.AdvManagedFlag = 0;
999
1000 return CMD_SUCCESS;
1001}
1002
vincent7cee1bb2005-03-25 13:08:53 +00001003DEFUN (ipv6_nd_homeagent_config_flag,
1004 ipv6_nd_homeagent_config_flag_cmd,
1005 "ipv6 nd home-agent-config-flag",
1006 "Interface IPv6 config commands\n"
1007 "Neighbor discovery\n"
1008 "Home Agent configuration flag\n")
1009{
1010 struct interface *ifp;
1011 struct zebra_if *zif;
1012
1013 ifp = (struct interface *) vty->index;
1014 zif = ifp->info;
1015
1016 zif->rtadv.AdvHomeAgentFlag = 1;
1017
1018 return CMD_SUCCESS;
1019}
1020
1021DEFUN (no_ipv6_nd_homeagent_config_flag,
1022 no_ipv6_nd_homeagent_config_flag_cmd,
1023 "no ipv6 nd home-agent-config-flag",
1024 NO_STR
1025 "Interface IPv6 config commands\n"
1026 "Neighbor discovery\n"
1027 "Home Agent configuration flag\n")
1028{
1029 struct interface *ifp;
1030 struct zebra_if *zif;
1031
1032 ifp = (struct interface *) vty->index;
1033 zif = ifp->info;
1034
1035 zif->rtadv.AdvHomeAgentFlag = 0;
1036
1037 return CMD_SUCCESS;
1038}
1039
1040DEFUN (ipv6_nd_adv_interval_config_option,
1041 ipv6_nd_adv_interval_config_option_cmd,
1042 "ipv6 nd adv-interval-option",
1043 "Interface IPv6 config commands\n"
1044 "Neighbor discovery\n"
1045 "Advertisement Interval Option\n")
1046{
1047 struct interface *ifp;
1048 struct zebra_if *zif;
1049
1050 ifp = (struct interface *) vty->index;
1051 zif = ifp->info;
1052
1053 zif->rtadv.AdvIntervalOption = 1;
1054
1055 return CMD_SUCCESS;
1056}
1057
1058DEFUN (no_ipv6_nd_adv_interval_config_option,
1059 no_ipv6_nd_adv_interval_config_option_cmd,
1060 "no ipv6 nd adv-interval-option",
1061 NO_STR
1062 "Interface IPv6 config commands\n"
1063 "Neighbor discovery\n"
1064 "Advertisement Interval Option\n")
1065{
1066 struct interface *ifp;
1067 struct zebra_if *zif;
1068
1069 ifp = (struct interface *) vty->index;
1070 zif = ifp->info;
1071
1072 zif->rtadv.AdvIntervalOption = 0;
1073
1074 return CMD_SUCCESS;
1075}
1076
paul718e3742002-12-13 20:15:29 +00001077DEFUN (ipv6_nd_other_config_flag,
1078 ipv6_nd_other_config_flag_cmd,
1079 "ipv6 nd other-config-flag",
hasso3e31cde2004-05-18 11:58:59 +00001080 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001081 "Neighbor discovery\n"
1082 "Other statefull configuration flag\n")
1083{
1084 struct interface *ifp;
1085 struct zebra_if *zif;
1086
1087 ifp = (struct interface *) vty->index;
1088 zif = ifp->info;
1089
1090 zif->rtadv.AdvOtherConfigFlag = 1;
1091
1092 return CMD_SUCCESS;
1093}
1094
1095DEFUN (no_ipv6_nd_other_config_flag,
1096 no_ipv6_nd_other_config_flag_cmd,
1097 "no ipv6 nd other-config-flag",
1098 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001099 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001100 "Neighbor discovery\n"
1101 "Other statefull configuration flag\n")
1102{
1103 struct interface *ifp;
1104 struct zebra_if *zif;
1105
1106 ifp = (struct interface *) vty->index;
1107 zif = ifp->info;
1108
1109 zif->rtadv.AdvOtherConfigFlag = 0;
1110
1111 return CMD_SUCCESS;
1112}
1113
hasso3e31cde2004-05-18 11:58:59 +00001114DEFUN (ipv6_nd_prefix,
1115 ipv6_nd_prefix_cmd,
1116 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
vincent7cee1bb2005-03-25 13:08:53 +00001117 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
hasso3e31cde2004-05-18 11:58:59 +00001118 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001119 "Neighbor discovery\n"
1120 "Prefix information\n"
1121 "IPv6 prefix\n"
1122 "Valid lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001123 "Infinite valid lifetime\n"
paul718e3742002-12-13 20:15:29 +00001124 "Preferred lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001125 "Infinite preferred lifetime\n"
1126 "Do not use prefix for onlink determination\n"
vincent7cee1bb2005-03-25 13:08:53 +00001127 "Do not use prefix for autoconfiguration\n"
1128 "Set Router Address flag\n")
paul718e3742002-12-13 20:15:29 +00001129{
1130 int i;
1131 int ret;
hasso3e31cde2004-05-18 11:58:59 +00001132 int cursor = 1;
paul718e3742002-12-13 20:15:29 +00001133 struct interface *ifp;
1134 struct zebra_if *zebra_if;
1135 struct rtadv_prefix rp;
1136
1137 ifp = (struct interface *) vty->index;
1138 zebra_if = ifp->info;
1139
1140 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1141 if (!ret)
1142 {
1143 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1144 return CMD_WARNING;
1145 }
hasso3e31cde2004-05-18 11:58:59 +00001146 rp.AdvOnLinkFlag = 1;
1147 rp.AdvAutonomousFlag = 1;
vincent7cee1bb2005-03-25 13:08:53 +00001148 rp.AdvRouterAddressFlag = 0;
hasso3e31cde2004-05-18 11:58:59 +00001149 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1150 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
paul718e3742002-12-13 20:15:29 +00001151
hasso3e31cde2004-05-18 11:58:59 +00001152 if (argc > 1)
paul718e3742002-12-13 20:15:29 +00001153 {
hasso3e31cde2004-05-18 11:58:59 +00001154 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
paul718e3742002-12-13 20:15:29 +00001155 {
hasso3e31cde2004-05-18 11:58:59 +00001156 if ( strncmp (argv[1], "i", 1) == 0)
1157 rp.AdvValidLifetime = UINT32_MAX;
1158 else
1159 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1160 (char **)NULL, 10);
1161
1162 if ( strncmp (argv[2], "i", 1) == 0)
1163 rp.AdvPreferredLifetime = UINT32_MAX;
1164 else
1165 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1166 (char **)NULL, 10);
1167
1168 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1169 {
1170 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1171 return CMD_WARNING;
1172 }
1173 cursor = cursor + 2;
paul718e3742002-12-13 20:15:29 +00001174 }
hasso3e31cde2004-05-18 11:58:59 +00001175 if (argc > cursor)
paul718e3742002-12-13 20:15:29 +00001176 {
hasso3e31cde2004-05-18 11:58:59 +00001177 for (i = cursor; i < argc; i++)
1178 {
1179 if (strncmp (argv[i], "of", 2) == 0)
1180 rp.AdvOnLinkFlag = 0;
1181 if (strncmp (argv[i], "no", 2) == 0)
1182 rp.AdvAutonomousFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +00001183 if (strncmp (argv[i], "ro", 2) == 0)
1184 rp.AdvRouterAddressFlag = 1;
hasso3e31cde2004-05-18 11:58:59 +00001185 }
paul718e3742002-12-13 20:15:29 +00001186 }
1187 }
1188
1189 rtadv_prefix_set (zebra_if, &rp);
1190
1191 return CMD_SUCCESS;
1192}
1193
hasso3e31cde2004-05-18 11:58:59 +00001194ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001195 ipv6_nd_prefix_val_nortaddr_cmd,
1196 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1197 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1198 "Interface IPv6 config commands\n"
1199 "Neighbor discovery\n"
1200 "Prefix information\n"
1201 "IPv6 prefix\n"
1202 "Valid lifetime in seconds\n"
1203 "Infinite valid lifetime\n"
1204 "Preferred lifetime in seconds\n"
1205 "Infinite preferred lifetime\n"
1206 "Do not use prefix for onlink determination\n"
1207 "Do not use prefix for autoconfiguration\n")
1208
1209ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001210 ipv6_nd_prefix_val_rev_cmd,
1211 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1212 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1213 "Interface IPv6 config commands\n"
1214 "Neighbor discovery\n"
1215 "Prefix information\n"
1216 "IPv6 prefix\n"
1217 "Valid lifetime in seconds\n"
1218 "Infinite valid lifetime\n"
1219 "Preferred lifetime in seconds\n"
1220 "Infinite preferred lifetime\n"
1221 "Do not use prefix for autoconfiguration\n"
1222 "Do not use prefix for onlink determination\n")
1223
1224ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001225 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1226 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1227 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
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"
1236 "Do not use prefix for autoconfiguration\n"
1237 "Do not use prefix for onlink determination\n"
1238 "Set Router Address flag\n")
1239
1240ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001241 ipv6_nd_prefix_val_noauto_cmd,
1242 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1243 "(<0-4294967295>|infinite) (no-autoconfig|)",
1244 "Interface IPv6 config commands\n"
1245 "Neighbor discovery\n"
1246 "Prefix information\n"
1247 "IPv6 prefix\n"
1248 "Valid lifetime in seconds\n"
1249 "Infinite valid lifetime\n"
1250 "Preferred lifetime in seconds\n"
1251 "Infinite preferred lifetime\n"
vincent7cee1bb2005-03-25 13:08:53 +00001252 "Do not use prefix for autoconfiguration")
hasso3e31cde2004-05-18 11:58:59 +00001253
1254ALIAS (ipv6_nd_prefix,
1255 ipv6_nd_prefix_val_offlink_cmd,
1256 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1257 "(<0-4294967295>|infinite) (off-link|)",
1258 "Interface IPv6 config commands\n"
1259 "Neighbor discovery\n"
1260 "Prefix information\n"
1261 "IPv6 prefix\n"
1262 "Valid lifetime in seconds\n"
1263 "Infinite valid lifetime\n"
1264 "Preferred lifetime in seconds\n"
1265 "Infinite preferred lifetime\n"
1266 "Do not use prefix for onlink determination\n")
1267
1268ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001269 ipv6_nd_prefix_val_rtaddr_cmd,
1270 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1271 "(<0-4294967295>|infinite) (router-address|)",
1272 "Interface IPv6 config commands\n"
1273 "Neighbor discovery\n"
1274 "Prefix information\n"
1275 "IPv6 prefix\n"
1276 "Valid lifetime in seconds\n"
1277 "Infinite valid lifetime\n"
1278 "Preferred lifetime in seconds\n"
1279 "Infinite preferred lifetime\n"
1280 "Set Router Address flag\n")
1281
1282ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001283 ipv6_nd_prefix_val_cmd,
1284 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1285 "(<0-4294967295>|infinite)",
1286 "Interface IPv6 config commands\n"
1287 "Neighbor discovery\n"
1288 "Prefix information\n"
1289 "IPv6 prefix\n"
1290 "Valid lifetime in seconds\n"
1291 "Infinite valid lifetime\n"
1292 "Preferred lifetime in seconds\n"
1293 "Infinite preferred lifetime\n")
1294
1295ALIAS (ipv6_nd_prefix,
1296 ipv6_nd_prefix_noval_cmd,
1297 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1298 "Interface IPv6 config commands\n"
1299 "Neighbor discovery\n"
1300 "Prefix information\n"
1301 "IPv6 prefix\n"
1302 "Do not use prefix for autoconfiguration\n"
1303 "Do not use prefix for onlink determination\n")
1304
1305ALIAS (ipv6_nd_prefix,
1306 ipv6_nd_prefix_noval_rev_cmd,
1307 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1308 "Interface IPv6 config commands\n"
1309 "Neighbor discovery\n"
1310 "Prefix information\n"
1311 "IPv6 prefix\n"
1312 "Do not use prefix for onlink determination\n"
1313 "Do not use prefix for autoconfiguration\n")
1314
1315ALIAS (ipv6_nd_prefix,
1316 ipv6_nd_prefix_noval_noauto_cmd,
1317 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1318 "Interface IPv6 config commands\n"
1319 "Neighbor discovery\n"
1320 "Prefix information\n"
1321 "IPv6 prefix\n"
1322 "Do not use prefix for autoconfiguration\n")
1323
1324ALIAS (ipv6_nd_prefix,
1325 ipv6_nd_prefix_noval_offlink_cmd,
1326 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1327 "Interface IPv6 config commands\n"
1328 "Neighbor discovery\n"
1329 "Prefix information\n"
1330 "IPv6 prefix\n"
1331 "Do not use prefix for onlink determination\n")
1332
1333ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001334 ipv6_nd_prefix_noval_rtaddr_cmd,
1335 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1336 "Interface IPv6 config commands\n"
1337 "Neighbor discovery\n"
1338 "Prefix information\n"
1339 "IPv6 prefix\n"
1340 "Set Router Address flag\n")
1341
1342ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001343 ipv6_nd_prefix_prefix_cmd,
1344 "ipv6 nd prefix X:X::X:X/M",
1345 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001346 "Neighbor discovery\n"
1347 "Prefix information\n"
1348 "IPv6 prefix\n")
1349
hasso3e31cde2004-05-18 11:58:59 +00001350DEFUN (no_ipv6_nd_prefix,
1351 no_ipv6_nd_prefix_cmd,
1352 "no ipv6 nd prefix IPV6PREFIX",
paul718e3742002-12-13 20:15:29 +00001353 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001354 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001355 "Neighbor discovery\n"
1356 "Prefix information\n"
1357 "IPv6 prefix\n")
1358{
1359 int ret;
1360 struct interface *ifp;
1361 struct zebra_if *zebra_if;
1362 struct rtadv_prefix rp;
1363
1364 ifp = (struct interface *) vty->index;
1365 zebra_if = ifp->info;
1366
1367 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1368 if (!ret)
1369 {
1370 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1371 return CMD_WARNING;
1372 }
1373
1374 ret = rtadv_prefix_reset (zebra_if, &rp);
1375 if (!ret)
1376 {
1377 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1378 return CMD_WARNING;
1379 }
1380
1381 return CMD_SUCCESS;
1382}
Chris Caputob60668d2009-05-03 04:40:57 +00001383
1384DEFUN (ipv6_nd_router_preference,
1385 ipv6_nd_router_preference_cmd,
1386 "ipv6 nd router-preference (high|medium|low)",
1387 "Interface IPv6 config commands\n"
1388 "Neighbor discovery\n"
1389 "Default router preference\n"
1390 "High default router preference\n"
1391 "Low default router preference\n"
1392 "Medium default router preference (default)\n")
1393{
1394 struct interface *ifp;
1395 struct zebra_if *zif;
1396 int i = 0;
1397
1398 ifp = (struct interface *) vty->index;
1399 zif = ifp->info;
1400
1401 while (0 != rtadv_pref_strs[i])
1402 {
1403 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1404 {
1405 zif->rtadv.DefaultPreference = i;
1406 return CMD_SUCCESS;
1407 }
1408 i++;
1409 }
1410
1411 return CMD_ERR_NO_MATCH;
1412}
1413
1414DEFUN (no_ipv6_nd_router_preference,
1415 no_ipv6_nd_router_preference_cmd,
1416 "no ipv6 nd router-preference",
1417 NO_STR
1418 "Interface IPv6 config commands\n"
1419 "Neighbor discovery\n"
1420 "Default router preference\n")
1421{
1422 struct interface *ifp;
1423 struct zebra_if *zif;
1424
1425 ifp = (struct interface *) vty->index;
1426 zif = ifp->info;
1427
1428 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1429
1430 return CMD_SUCCESS;
1431}
1432
paul718e3742002-12-13 20:15:29 +00001433/* Write configuration about router advertisement. */
1434void
1435rtadv_config_write (struct vty *vty, struct interface *ifp)
1436{
1437 struct zebra_if *zif;
hasso52dc7ee2004-09-23 19:18:23 +00001438 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001439 struct rtadv_prefix *rprefix;
1440 u_char buf[INET6_ADDRSTRLEN];
vincent7cee1bb2005-03-25 13:08:53 +00001441 int interval;
paul718e3742002-12-13 20:15:29 +00001442
1443 if (! rtadv)
1444 return;
1445
1446 zif = ifp->info;
1447
1448 if (! if_is_loopback (ifp))
1449 {
1450 if (zif->rtadv.AdvSendAdvertisements)
1451 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1452 else
1453 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1454 }
1455
vincent7cee1bb2005-03-25 13:08:53 +00001456
1457 interval = zif->rtadv.MaxRtrAdvInterval;
1458 if (interval % 1000)
1459 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1460 VTY_NEWLINE);
1461 else
1462 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1463 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
paul718e3742002-12-13 20:15:29 +00001464 VTY_NEWLINE);
1465
1466 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1467 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1468 VTY_NEWLINE);
1469
1470 if (zif->rtadv.AdvReachableTime)
1471 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1472 VTY_NEWLINE);
1473
1474 if (zif->rtadv.AdvManagedFlag)
1475 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1476
1477 if (zif->rtadv.AdvOtherConfigFlag)
1478 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1479
Chris Caputob60668d2009-05-03 04:40:57 +00001480 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1481 vty_out (vty, " ipv6 nd router-preference %s%s",
1482 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1483 VTY_NEWLINE);
1484
paul1eb8ef22005-04-07 07:30:20 +00001485 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +00001486 {
hasso3e31cde2004-05-18 11:58:59 +00001487 vty_out (vty, " ipv6 nd prefix %s/%d",
paul718e3742002-12-13 20:15:29 +00001488 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
hassoc9e52be2004-09-26 16:09:34 +00001489 (char *) buf, INET6_ADDRSTRLEN),
hasso3e31cde2004-05-18 11:58:59 +00001490 rprefix->prefix.prefixlen);
1491 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1492 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1493 {
1494 if (rprefix->AdvValidLifetime == UINT32_MAX)
1495 vty_out (vty, " infinite");
1496 else
1497 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1498 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1499 vty_out (vty, " infinite");
1500 else
1501 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1502 }
1503 if (!rprefix->AdvOnLinkFlag)
1504 vty_out (vty, " off-link");
1505 if (!rprefix->AdvAutonomousFlag)
1506 vty_out (vty, " no-autoconfig");
vincent7cee1bb2005-03-25 13:08:53 +00001507 if (rprefix->AdvRouterAddressFlag)
1508 vty_out (vty, " router-address");
paul718e3742002-12-13 20:15:29 +00001509 vty_out (vty, "%s", VTY_NEWLINE);
1510 }
1511}
1512
paul718e3742002-12-13 20:15:29 +00001513
paula1ac18c2005-06-28 17:17:12 +00001514static void
paul718e3742002-12-13 20:15:29 +00001515rtadv_event (enum rtadv_event event, int val)
1516{
1517 switch (event)
1518 {
1519 case RTADV_START:
1520 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001521 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001522 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001523 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1524 NULL, 0);
paul718e3742002-12-13 20:15:29 +00001525 break;
1526 case RTADV_STOP:
1527 if (rtadv->ra_timer)
1528 {
1529 thread_cancel (rtadv->ra_timer);
1530 rtadv->ra_timer = NULL;
1531 }
1532 if (rtadv->ra_read)
1533 {
1534 thread_cancel (rtadv->ra_read);
1535 rtadv->ra_read = NULL;
1536 }
1537 break;
1538 case RTADV_TIMER:
1539 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001540 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1541 val);
paul718e3742002-12-13 20:15:29 +00001542 break;
vincent7cee1bb2005-03-25 13:08:53 +00001543 case RTADV_TIMER_MSEC:
1544 if (! rtadv->ra_timer)
1545 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1546 NULL, val);
1547 break;
paul718e3742002-12-13 20:15:29 +00001548 case RTADV_READ:
1549 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001550 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001551 break;
1552 default:
1553 break;
1554 }
1555 return;
1556}
1557
1558void
paula1ac18c2005-06-28 17:17:12 +00001559rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001560{
1561 int sock;
1562
1563 sock = rtadv_make_socket ();
1564 if (sock < 0)
1565 return;
1566
1567 rtadv = rtadv_new ();
1568 rtadv->sock = sock;
1569
1570 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1571 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
paul718e3742002-12-13 20:15:29 +00001572 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001573 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
paul718e3742002-12-13 20:15:29 +00001574 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1575 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1576 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1577 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1578 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1579 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1580 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1581 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1582 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001583 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1584 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1585 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1586 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1587 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1588 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1589 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1590 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001591 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001592 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1593 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001594 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1595 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1596 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001597 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001598 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1599 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1600 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1601 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1602 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001603 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001604 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1605 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
Chris Caputob60668d2009-05-03 04:40:57 +00001606 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1607 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
paul718e3742002-12-13 20:15:29 +00001608}
1609
paula1ac18c2005-06-28 17:17:12 +00001610static int
paul718e3742002-12-13 20:15:29 +00001611if_join_all_router (int sock, struct interface *ifp)
1612{
1613 int ret;
1614
1615 struct ipv6_mreq mreq;
1616
1617 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1618 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1619 mreq.ipv6mr_interface = ifp->ifindex;
1620
1621 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1622 (char *) &mreq, sizeof mreq);
1623 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001624 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001625
1626 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1627
1628 return 0;
1629}
1630
paula1ac18c2005-06-28 17:17:12 +00001631static int
paul718e3742002-12-13 20:15:29 +00001632if_leave_all_router (int sock, struct interface *ifp)
1633{
1634 int ret;
1635
1636 struct ipv6_mreq mreq;
1637
1638 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1639 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1640 mreq.ipv6mr_interface = ifp->ifindex;
1641
1642 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1643 (char *) &mreq, sizeof mreq);
1644 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001645 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001646
1647 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1648
1649 return 0;
1650}
1651
1652#else
1653void
paula1ac18c2005-06-28 17:17:12 +00001654rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001655{
1656 /* Empty.*/;
1657}
1658#endif /* RTADV && HAVE_IPV6 */