blob: e0941357d71674b0795dadacbe7853164a43c448 [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
Denis Ovsienko6ae93c02011-12-27 10:45:36 +0400322 /* MTU */
323 if (zif->rtadv.AdvLinkMTU)
324 {
325 struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len);
326 opt->nd_opt_mtu_type = ND_OPT_MTU;
327 opt->nd_opt_mtu_len = 1;
328 opt->nd_opt_mtu_reserved = 0;
329 opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU);
330 len += sizeof (struct nd_opt_mtu);
331 }
332
paul718e3742002-12-13 20:15:29 +0000333 msg.msg_name = (void *) &addr;
334 msg.msg_namelen = sizeof (struct sockaddr_in6);
335 msg.msg_iov = &iov;
336 msg.msg_iovlen = 1;
337 msg.msg_control = (void *) adata;
gdtf841e022004-08-11 19:20:01 +0000338 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
gdt57492d52004-08-11 18:06:38 +0000339 msg.msg_flags = 0;
paul718e3742002-12-13 20:15:29 +0000340 iov.iov_base = buf;
341 iov.iov_len = len;
342
ajsb99760a2005-01-04 16:24:43 +0000343 cmsgptr = ZCMSG_FIRSTHDR(&msg);
gdt57492d52004-08-11 18:06:38 +0000344 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
paul718e3742002-12-13 20:15:29 +0000345 cmsgptr->cmsg_level = IPPROTO_IPV6;
346 cmsgptr->cmsg_type = IPV6_PKTINFO;
gdt80893812004-08-11 15:58:00 +0000347
paul718e3742002-12-13 20:15:29 +0000348 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
349 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
350 pkt->ipi6_ifindex = ifp->ifindex;
351
352 ret = sendmsg (sock, &msg, 0);
gdt9ccabd12004-01-06 18:23:02 +0000353 if (ret < 0)
354 {
355 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
ajs6099b3b2004-11-20 02:06:59 +0000356 errno, safe_strerror(errno));
gdt9ccabd12004-01-06 18:23:02 +0000357 }
paul718e3742002-12-13 20:15:29 +0000358}
359
paula1ac18c2005-06-28 17:17:12 +0000360static int
paul718e3742002-12-13 20:15:29 +0000361rtadv_timer (struct thread *thread)
362{
paul1eb8ef22005-04-07 07:30:20 +0000363 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000364 struct interface *ifp;
365 struct zebra_if *zif;
vincent7cee1bb2005-03-25 13:08:53 +0000366 int period;
paul718e3742002-12-13 20:15:29 +0000367
368 rtadv->ra_timer = NULL;
vincent7cee1bb2005-03-25 13:08:53 +0000369 if (rtadv->adv_msec_if_count == 0)
370 {
371 period = 1000; /* 1 s */
372 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
373 }
374 else
375 {
376 period = 10; /* 10 ms */
377 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
378 }
paul718e3742002-12-13 20:15:29 +0000379
paul1eb8ef22005-04-07 07:30:20 +0000380 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
paul718e3742002-12-13 20:15:29 +0000381 {
Denis Ovsienkofb5174a2011-12-27 10:18:47 +0400382 if (if_is_loopback (ifp) || ! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000383 continue;
384
385 zif = ifp->info;
386
387 if (zif->rtadv.AdvSendAdvertisements)
vincent7cee1bb2005-03-25 13:08:53 +0000388 {
389 zif->rtadv.AdvIntervalTimer -= period;
390 if (zif->rtadv.AdvIntervalTimer <= 0)
391 {
392 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
393 rtadv_send_packet (rtadv->sock, ifp);
394 }
395 }
paul718e3742002-12-13 20:15:29 +0000396 }
397 return 0;
398}
399
paula1ac18c2005-06-28 17:17:12 +0000400static void
paul718e3742002-12-13 20:15:29 +0000401rtadv_process_solicit (struct interface *ifp)
402{
403 zlog_info ("Router solicitation received on %s", ifp->name);
404
405 rtadv_send_packet (rtadv->sock, ifp);
406}
407
paula1ac18c2005-06-28 17:17:12 +0000408static void
409rtadv_process_advert (void)
paul718e3742002-12-13 20:15:29 +0000410{
411 zlog_info ("Router advertisement received");
412}
413
paula1ac18c2005-06-28 17:17:12 +0000414static void
hassofce954f2004-10-07 20:29:24 +0000415rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
paul718e3742002-12-13 20:15:29 +0000416{
417 struct icmp6_hdr *icmph;
418 struct interface *ifp;
419 struct zebra_if *zif;
420
421 /* Interface search. */
422 ifp = if_lookup_by_index (ifindex);
423 if (ifp == NULL)
424 {
425 zlog_warn ("Unknown interface index: %d", ifindex);
426 return;
427 }
428
429 if (if_is_loopback (ifp))
430 return;
431
432 /* Check interface configuration. */
433 zif = ifp->info;
434 if (! zif->rtadv.AdvSendAdvertisements)
435 return;
436
437 /* ICMP message length check. */
438 if (len < sizeof (struct icmp6_hdr))
439 {
440 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
441 return;
442 }
443
444 icmph = (struct icmp6_hdr *) buf;
445
446 /* ICMP message type check. */
447 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
448 icmph->icmp6_type != ND_ROUTER_ADVERT)
449 {
450 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
451 return;
452 }
453
454 /* Hoplimit check. */
455 if (hoplimit >= 0 && hoplimit != 255)
456 {
457 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
458 hoplimit);
459 return;
460 }
461
462 /* Check ICMP message type. */
463 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
464 rtadv_process_solicit (ifp);
465 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
466 rtadv_process_advert ();
467
468 return;
469}
470
paula1ac18c2005-06-28 17:17:12 +0000471static int
paul718e3742002-12-13 20:15:29 +0000472rtadv_read (struct thread *thread)
473{
474 int sock;
475 int len;
476 u_char buf[RTADV_MSG_SIZE];
477 struct sockaddr_in6 from;
Stephen Hemmingerb0b709a2009-12-08 13:26:14 +0300478 unsigned int ifindex = 0;
paul718e3742002-12-13 20:15:29 +0000479 int hoplimit = -1;
480
481 sock = THREAD_FD (thread);
482 rtadv->ra_read = NULL;
483
484 /* Register myself. */
485 rtadv_event (RTADV_READ, sock);
486
487 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
488
489 if (len < 0)
490 {
ajs6099b3b2004-11-20 02:06:59 +0000491 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000492 return len;
493 }
494
hassofce954f2004-10-07 20:29:24 +0000495 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
paul718e3742002-12-13 20:15:29 +0000496
497 return 0;
498}
499
paula1ac18c2005-06-28 17:17:12 +0000500static int
paul718e3742002-12-13 20:15:29 +0000501rtadv_make_socket (void)
502{
503 int sock;
504 int ret;
505 struct icmp6_filter filter;
506
pauledd7c242003-06-04 13:59:38 +0000507 if ( zserv_privs.change (ZPRIVS_RAISE) )
508 zlog_err ("rtadv_make_socket: could not raise privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000509 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000510
paul718e3742002-12-13 20:15:29 +0000511 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
512
pauledd7c242003-06-04 13:59:38 +0000513 if ( zserv_privs.change (ZPRIVS_LOWER) )
514 zlog_err ("rtadv_make_socket: could not lower privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000515 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000516
paul718e3742002-12-13 20:15:29 +0000517 /* When we can't make ICMPV6 socket simply back. Router
518 advertisement feature will not be supported. */
519 if (sock < 0)
520 return -1;
521
522 ret = setsockopt_ipv6_pktinfo (sock, 1);
523 if (ret < 0)
524 return ret;
paul718e3742002-12-13 20:15:29 +0000525 ret = setsockopt_ipv6_multicast_loop (sock, 0);
526 if (ret < 0)
527 return ret;
528 ret = setsockopt_ipv6_unicast_hops (sock, 255);
529 if (ret < 0)
530 return ret;
531 ret = setsockopt_ipv6_multicast_hops (sock, 255);
532 if (ret < 0)
533 return ret;
534 ret = setsockopt_ipv6_hoplimit (sock, 1);
535 if (ret < 0)
536 return ret;
537
538 ICMP6_FILTER_SETBLOCKALL(&filter);
539 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
540 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
541
542 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
543 sizeof (struct icmp6_filter));
544 if (ret < 0)
545 {
ajs6099b3b2004-11-20 02:06:59 +0000546 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000547 return ret;
548 }
549
550 return sock;
551}
552
paula1ac18c2005-06-28 17:17:12 +0000553static struct rtadv_prefix *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800554rtadv_prefix_new (void)
paul718e3742002-12-13 20:15:29 +0000555{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700556 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
paul718e3742002-12-13 20:15:29 +0000557}
558
paula1ac18c2005-06-28 17:17:12 +0000559static void
paul718e3742002-12-13 20:15:29 +0000560rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
561{
562 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
563}
564
paula1ac18c2005-06-28 17:17:12 +0000565static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000566rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000567{
hasso52dc7ee2004-09-23 19:18:23 +0000568 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000569 struct rtadv_prefix *rprefix;
570
paul1eb8ef22005-04-07 07:30:20 +0000571 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
572 if (prefix_same (&rprefix->prefix, p))
573 return rprefix;
paul718e3742002-12-13 20:15:29 +0000574 return NULL;
575}
576
paula1ac18c2005-06-28 17:17:12 +0000577static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000578rtadv_prefix_get (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000579{
580 struct rtadv_prefix *rprefix;
581
582 rprefix = rtadv_prefix_lookup (rplist, p);
583 if (rprefix)
584 return rprefix;
585
586 rprefix = rtadv_prefix_new ();
587 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
588 listnode_add (rplist, rprefix);
589
590 return rprefix;
591}
592
paula1ac18c2005-06-28 17:17:12 +0000593static void
paul718e3742002-12-13 20:15:29 +0000594rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
595{
596 struct rtadv_prefix *rprefix;
597
598 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
599
600 /* Set parameters. */
601 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
602 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
603 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
604 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
vincent7cee1bb2005-03-25 13:08:53 +0000605 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
paul718e3742002-12-13 20:15:29 +0000606}
607
paula1ac18c2005-06-28 17:17:12 +0000608static int
paul718e3742002-12-13 20:15:29 +0000609rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
610{
611 struct rtadv_prefix *rprefix;
612
613 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
614 if (rprefix != NULL)
615 {
616 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
617 rtadv_prefix_free (rprefix);
618 return 1;
619 }
620 else
621 return 0;
622}
623
624DEFUN (ipv6_nd_suppress_ra,
625 ipv6_nd_suppress_ra_cmd,
626 "ipv6 nd suppress-ra",
hasso3e31cde2004-05-18 11:58:59 +0000627 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000628 "Neighbor discovery\n"
629 "Suppress Router Advertisement\n")
630{
631 struct interface *ifp;
632 struct zebra_if *zif;
633
634 ifp = vty->index;
635 zif = ifp->info;
636
637 if (if_is_loopback (ifp))
638 {
639 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
640 return CMD_WARNING;
641 }
642
643 if (zif->rtadv.AdvSendAdvertisements)
644 {
645 zif->rtadv.AdvSendAdvertisements = 0;
646 zif->rtadv.AdvIntervalTimer = 0;
647 rtadv->adv_if_count--;
648
649 if_leave_all_router (rtadv->sock, ifp);
650
651 if (rtadv->adv_if_count == 0)
652 rtadv_event (RTADV_STOP, 0);
653 }
654
655 return CMD_SUCCESS;
656}
657
paul718e3742002-12-13 20:15:29 +0000658DEFUN (no_ipv6_nd_suppress_ra,
659 no_ipv6_nd_suppress_ra_cmd,
660 "no ipv6 nd suppress-ra",
661 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000662 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000663 "Neighbor discovery\n"
664 "Suppress Router Advertisement\n")
665{
666 struct interface *ifp;
667 struct zebra_if *zif;
668
669 ifp = vty->index;
670 zif = ifp->info;
671
672 if (if_is_loopback (ifp))
673 {
674 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
675 return CMD_WARNING;
676 }
677
678 if (! zif->rtadv.AdvSendAdvertisements)
679 {
680 zif->rtadv.AdvSendAdvertisements = 1;
681 zif->rtadv.AdvIntervalTimer = 0;
682 rtadv->adv_if_count++;
683
684 if_join_all_router (rtadv->sock, ifp);
685
686 if (rtadv->adv_if_count == 1)
687 rtadv_event (RTADV_START, rtadv->sock);
688 }
689
690 return CMD_SUCCESS;
691}
692
vincent7cee1bb2005-03-25 13:08:53 +0000693DEFUN (ipv6_nd_ra_interval_msec,
694 ipv6_nd_ra_interval_msec_cmd,
695 "ipv6 nd ra-interval msec MILLISECONDS",
696 "Interface IPv6 config commands\n"
697 "Neighbor discovery\n"
698 "Router Advertisement interval\n"
699 "Router Advertisement interval in milliseconds\n")
700{
701 int interval;
702 struct interface *ifp;
703 struct zebra_if *zif;
704
705 ifp = (struct interface *) vty->index;
706 zif = ifp->info;
707
708 interval = atoi (argv[0]);
709
710 if (interval <= 0)
711 {
712 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
713 return CMD_WARNING;
714 }
715
716 if (zif->rtadv.MaxRtrAdvInterval % 1000)
717 rtadv->adv_msec_if_count--;
718
719 if (interval % 1000)
720 rtadv->adv_msec_if_count++;
721
722 zif->rtadv.MaxRtrAdvInterval = interval;
723 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
724 zif->rtadv.AdvIntervalTimer = 0;
725
726 return CMD_SUCCESS;
727}
728
paul718e3742002-12-13 20:15:29 +0000729DEFUN (ipv6_nd_ra_interval,
730 ipv6_nd_ra_interval_cmd,
731 "ipv6 nd ra-interval SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000732 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000733 "Neighbor discovery\n"
734 "Router Advertisement interval\n"
735 "Router Advertisement interval in seconds\n")
736{
737 int interval;
738 struct interface *ifp;
739 struct zebra_if *zif;
740
741 ifp = (struct interface *) vty->index;
742 zif = ifp->info;
743
744 interval = atoi (argv[0]);
745
vincent7cee1bb2005-03-25 13:08:53 +0000746 if (interval <= 0)
paul718e3742002-12-13 20:15:29 +0000747 {
748 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
749 return CMD_WARNING;
750 }
751
vincent7cee1bb2005-03-25 13:08:53 +0000752 if (zif->rtadv.MaxRtrAdvInterval % 1000)
753 rtadv->adv_msec_if_count--;
754
755 /* convert to milliseconds */
756 interval = interval * 1000;
757
paul718e3742002-12-13 20:15:29 +0000758 zif->rtadv.MaxRtrAdvInterval = interval;
759 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
760 zif->rtadv.AdvIntervalTimer = 0;
761
762 return CMD_SUCCESS;
763}
764
765DEFUN (no_ipv6_nd_ra_interval,
766 no_ipv6_nd_ra_interval_cmd,
767 "no ipv6 nd ra-interval",
768 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000769 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000770 "Neighbor discovery\n"
771 "Router Advertisement interval\n")
772{
773 struct interface *ifp;
774 struct zebra_if *zif;
775
776 ifp = (struct interface *) vty->index;
777 zif = ifp->info;
778
vincent7cee1bb2005-03-25 13:08:53 +0000779 if (zif->rtadv.MaxRtrAdvInterval % 1000)
780 rtadv->adv_msec_if_count--;
781
paul718e3742002-12-13 20:15:29 +0000782 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
783 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
784 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
785
786 return CMD_SUCCESS;
787}
788
789DEFUN (ipv6_nd_ra_lifetime,
790 ipv6_nd_ra_lifetime_cmd,
791 "ipv6 nd ra-lifetime SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000792 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000793 "Neighbor discovery\n"
794 "Router lifetime\n"
795 "Router lifetime in seconds\n")
796{
797 int lifetime;
798 struct interface *ifp;
799 struct zebra_if *zif;
800
801 ifp = (struct interface *) vty->index;
802 zif = ifp->info;
803
804 lifetime = atoi (argv[0]);
805
806 if (lifetime < 0 || lifetime > 0xffff)
807 {
808 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
809 return CMD_WARNING;
810 }
811
812 zif->rtadv.AdvDefaultLifetime = lifetime;
813
814 return CMD_SUCCESS;
815}
816
817DEFUN (no_ipv6_nd_ra_lifetime,
818 no_ipv6_nd_ra_lifetime_cmd,
819 "no ipv6 nd ra-lifetime",
820 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000821 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000822 "Neighbor discovery\n"
823 "Router lifetime\n")
824{
825 struct interface *ifp;
826 struct zebra_if *zif;
827
828 ifp = (struct interface *) vty->index;
829 zif = ifp->info;
830
831 zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
832
833 return CMD_SUCCESS;
834}
835
836DEFUN (ipv6_nd_reachable_time,
837 ipv6_nd_reachable_time_cmd,
838 "ipv6 nd reachable-time MILLISECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000839 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000840 "Neighbor discovery\n"
841 "Reachable time\n"
842 "Reachable time in milliseconds\n")
843{
844 u_int32_t rtime;
845 struct interface *ifp;
846 struct zebra_if *zif;
847
848 ifp = (struct interface *) vty->index;
849 zif = ifp->info;
850
851 rtime = (u_int32_t) atol (argv[0]);
852
853 if (rtime > RTADV_MAX_REACHABLE_TIME)
854 {
855 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
856 return CMD_WARNING;
857 }
858
859 zif->rtadv.AdvReachableTime = rtime;
860
861 return CMD_SUCCESS;
862}
863
864DEFUN (no_ipv6_nd_reachable_time,
865 no_ipv6_nd_reachable_time_cmd,
866 "no ipv6 nd reachable-time",
867 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000868 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000869 "Neighbor discovery\n"
870 "Reachable time\n")
871{
872 struct interface *ifp;
873 struct zebra_if *zif;
874
875 ifp = (struct interface *) vty->index;
876 zif = ifp->info;
877
878 zif->rtadv.AdvReachableTime = 0;
879
880 return CMD_SUCCESS;
881}
882
vincent7cee1bb2005-03-25 13:08:53 +0000883DEFUN (ipv6_nd_homeagent_preference,
884 ipv6_nd_homeagent_preference_cmd,
885 "ipv6 nd home-agent-preference PREFERENCE",
886 "Interface IPv6 config commands\n"
887 "Neighbor discovery\n"
888 "Home Agent preference\n"
889 "Home Agent preference value 0..65535\n")
890{
891 u_int32_t hapref;
892 struct interface *ifp;
893 struct zebra_if *zif;
894
895 ifp = (struct interface *) vty->index;
896 zif = ifp->info;
897
898 hapref = (u_int32_t) atol (argv[0]);
899
900 if (hapref > 65535)
901 {
902 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
903 return CMD_WARNING;
904 }
905
906 zif->rtadv.HomeAgentPreference = hapref;
907
908 return CMD_SUCCESS;
909}
910
911DEFUN (no_ipv6_nd_homeagent_preference,
912 no_ipv6_nd_homeagent_preference_cmd,
913 "no ipv6 nd home-agent-preference",
914 NO_STR
915 "Interface IPv6 config commands\n"
916 "Neighbor discovery\n"
917 "Home Agent preference\n")
918{
919 struct interface *ifp;
920 struct zebra_if *zif;
921
922 ifp = (struct interface *) vty->index;
923 zif = ifp->info;
924
925 zif->rtadv.HomeAgentPreference = 0;
926
927 return CMD_SUCCESS;
928}
929
930DEFUN (ipv6_nd_homeagent_lifetime,
931 ipv6_nd_homeagent_lifetime_cmd,
932 "ipv6 nd home-agent-lifetime SECONDS",
933 "Interface IPv6 config commands\n"
934 "Neighbor discovery\n"
935 "Home Agent lifetime\n"
936 "Home Agent lifetime in seconds\n")
937{
938 u_int32_t ha_ltime;
939 struct interface *ifp;
940 struct zebra_if *zif;
941
942 ifp = (struct interface *) vty->index;
943 zif = ifp->info;
944
945 ha_ltime = (u_int32_t) atol (argv[0]);
946
947 if (ha_ltime > RTADV_MAX_HALIFETIME)
948 {
949 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
950 return CMD_WARNING;
951 }
952
953 zif->rtadv.HomeAgentLifetime = ha_ltime;
954
955 return CMD_SUCCESS;
956}
957
958DEFUN (no_ipv6_nd_homeagent_lifetime,
959 no_ipv6_nd_homeagent_lifetime_cmd,
960 "no ipv6 nd home-agent-lifetime",
961 NO_STR
962 "Interface IPv6 config commands\n"
963 "Neighbor discovery\n"
964 "Home Agent lifetime\n")
965{
966 struct interface *ifp;
967 struct zebra_if *zif;
968
969 ifp = (struct interface *) vty->index;
970 zif = ifp->info;
971
972 zif->rtadv.HomeAgentLifetime = 0;
973
974 return CMD_SUCCESS;
975}
976
paul718e3742002-12-13 20:15:29 +0000977DEFUN (ipv6_nd_managed_config_flag,
978 ipv6_nd_managed_config_flag_cmd,
979 "ipv6 nd managed-config-flag",
hasso3e31cde2004-05-18 11:58:59 +0000980 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000981 "Neighbor discovery\n"
982 "Managed address configuration flag\n")
983{
984 struct interface *ifp;
985 struct zebra_if *zif;
986
987 ifp = (struct interface *) vty->index;
988 zif = ifp->info;
989
990 zif->rtadv.AdvManagedFlag = 1;
991
992 return CMD_SUCCESS;
993}
994
995DEFUN (no_ipv6_nd_managed_config_flag,
996 no_ipv6_nd_managed_config_flag_cmd,
997 "no ipv6 nd managed-config-flag",
998 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000999 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001000 "Neighbor discovery\n"
1001 "Managed address configuration flag\n")
1002{
1003 struct interface *ifp;
1004 struct zebra_if *zif;
1005
1006 ifp = (struct interface *) vty->index;
1007 zif = ifp->info;
1008
1009 zif->rtadv.AdvManagedFlag = 0;
1010
1011 return CMD_SUCCESS;
1012}
1013
vincent7cee1bb2005-03-25 13:08:53 +00001014DEFUN (ipv6_nd_homeagent_config_flag,
1015 ipv6_nd_homeagent_config_flag_cmd,
1016 "ipv6 nd home-agent-config-flag",
1017 "Interface IPv6 config commands\n"
1018 "Neighbor discovery\n"
1019 "Home Agent configuration flag\n")
1020{
1021 struct interface *ifp;
1022 struct zebra_if *zif;
1023
1024 ifp = (struct interface *) vty->index;
1025 zif = ifp->info;
1026
1027 zif->rtadv.AdvHomeAgentFlag = 1;
1028
1029 return CMD_SUCCESS;
1030}
1031
1032DEFUN (no_ipv6_nd_homeagent_config_flag,
1033 no_ipv6_nd_homeagent_config_flag_cmd,
1034 "no ipv6 nd home-agent-config-flag",
1035 NO_STR
1036 "Interface IPv6 config commands\n"
1037 "Neighbor discovery\n"
1038 "Home Agent configuration flag\n")
1039{
1040 struct interface *ifp;
1041 struct zebra_if *zif;
1042
1043 ifp = (struct interface *) vty->index;
1044 zif = ifp->info;
1045
1046 zif->rtadv.AdvHomeAgentFlag = 0;
1047
1048 return CMD_SUCCESS;
1049}
1050
1051DEFUN (ipv6_nd_adv_interval_config_option,
1052 ipv6_nd_adv_interval_config_option_cmd,
1053 "ipv6 nd adv-interval-option",
1054 "Interface IPv6 config commands\n"
1055 "Neighbor discovery\n"
1056 "Advertisement Interval Option\n")
1057{
1058 struct interface *ifp;
1059 struct zebra_if *zif;
1060
1061 ifp = (struct interface *) vty->index;
1062 zif = ifp->info;
1063
1064 zif->rtadv.AdvIntervalOption = 1;
1065
1066 return CMD_SUCCESS;
1067}
1068
1069DEFUN (no_ipv6_nd_adv_interval_config_option,
1070 no_ipv6_nd_adv_interval_config_option_cmd,
1071 "no ipv6 nd adv-interval-option",
1072 NO_STR
1073 "Interface IPv6 config commands\n"
1074 "Neighbor discovery\n"
1075 "Advertisement Interval Option\n")
1076{
1077 struct interface *ifp;
1078 struct zebra_if *zif;
1079
1080 ifp = (struct interface *) vty->index;
1081 zif = ifp->info;
1082
1083 zif->rtadv.AdvIntervalOption = 0;
1084
1085 return CMD_SUCCESS;
1086}
1087
paul718e3742002-12-13 20:15:29 +00001088DEFUN (ipv6_nd_other_config_flag,
1089 ipv6_nd_other_config_flag_cmd,
1090 "ipv6 nd other-config-flag",
hasso3e31cde2004-05-18 11:58:59 +00001091 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001092 "Neighbor discovery\n"
1093 "Other statefull configuration flag\n")
1094{
1095 struct interface *ifp;
1096 struct zebra_if *zif;
1097
1098 ifp = (struct interface *) vty->index;
1099 zif = ifp->info;
1100
1101 zif->rtadv.AdvOtherConfigFlag = 1;
1102
1103 return CMD_SUCCESS;
1104}
1105
1106DEFUN (no_ipv6_nd_other_config_flag,
1107 no_ipv6_nd_other_config_flag_cmd,
1108 "no ipv6 nd other-config-flag",
1109 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001110 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001111 "Neighbor discovery\n"
1112 "Other statefull configuration flag\n")
1113{
1114 struct interface *ifp;
1115 struct zebra_if *zif;
1116
1117 ifp = (struct interface *) vty->index;
1118 zif = ifp->info;
1119
1120 zif->rtadv.AdvOtherConfigFlag = 0;
1121
1122 return CMD_SUCCESS;
1123}
1124
hasso3e31cde2004-05-18 11:58:59 +00001125DEFUN (ipv6_nd_prefix,
1126 ipv6_nd_prefix_cmd,
1127 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
vincent7cee1bb2005-03-25 13:08:53 +00001128 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
hasso3e31cde2004-05-18 11:58:59 +00001129 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001130 "Neighbor discovery\n"
1131 "Prefix information\n"
1132 "IPv6 prefix\n"
1133 "Valid lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001134 "Infinite valid lifetime\n"
paul718e3742002-12-13 20:15:29 +00001135 "Preferred lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001136 "Infinite preferred lifetime\n"
1137 "Do not use prefix for onlink determination\n"
vincent7cee1bb2005-03-25 13:08:53 +00001138 "Do not use prefix for autoconfiguration\n"
1139 "Set Router Address flag\n")
paul718e3742002-12-13 20:15:29 +00001140{
1141 int i;
1142 int ret;
hasso3e31cde2004-05-18 11:58:59 +00001143 int cursor = 1;
paul718e3742002-12-13 20:15:29 +00001144 struct interface *ifp;
1145 struct zebra_if *zebra_if;
1146 struct rtadv_prefix rp;
1147
1148 ifp = (struct interface *) vty->index;
1149 zebra_if = ifp->info;
1150
1151 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1152 if (!ret)
1153 {
1154 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1155 return CMD_WARNING;
1156 }
hasso3e31cde2004-05-18 11:58:59 +00001157 rp.AdvOnLinkFlag = 1;
1158 rp.AdvAutonomousFlag = 1;
vincent7cee1bb2005-03-25 13:08:53 +00001159 rp.AdvRouterAddressFlag = 0;
hasso3e31cde2004-05-18 11:58:59 +00001160 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1161 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
paul718e3742002-12-13 20:15:29 +00001162
hasso3e31cde2004-05-18 11:58:59 +00001163 if (argc > 1)
paul718e3742002-12-13 20:15:29 +00001164 {
hasso3e31cde2004-05-18 11:58:59 +00001165 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
paul718e3742002-12-13 20:15:29 +00001166 {
hasso3e31cde2004-05-18 11:58:59 +00001167 if ( strncmp (argv[1], "i", 1) == 0)
1168 rp.AdvValidLifetime = UINT32_MAX;
1169 else
1170 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1171 (char **)NULL, 10);
1172
1173 if ( strncmp (argv[2], "i", 1) == 0)
1174 rp.AdvPreferredLifetime = UINT32_MAX;
1175 else
1176 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1177 (char **)NULL, 10);
1178
1179 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1180 {
1181 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1182 return CMD_WARNING;
1183 }
1184 cursor = cursor + 2;
paul718e3742002-12-13 20:15:29 +00001185 }
hasso3e31cde2004-05-18 11:58:59 +00001186 if (argc > cursor)
paul718e3742002-12-13 20:15:29 +00001187 {
hasso3e31cde2004-05-18 11:58:59 +00001188 for (i = cursor; i < argc; i++)
1189 {
1190 if (strncmp (argv[i], "of", 2) == 0)
1191 rp.AdvOnLinkFlag = 0;
1192 if (strncmp (argv[i], "no", 2) == 0)
1193 rp.AdvAutonomousFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +00001194 if (strncmp (argv[i], "ro", 2) == 0)
1195 rp.AdvRouterAddressFlag = 1;
hasso3e31cde2004-05-18 11:58:59 +00001196 }
paul718e3742002-12-13 20:15:29 +00001197 }
1198 }
1199
1200 rtadv_prefix_set (zebra_if, &rp);
1201
1202 return CMD_SUCCESS;
1203}
1204
hasso3e31cde2004-05-18 11:58:59 +00001205ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001206 ipv6_nd_prefix_val_nortaddr_cmd,
1207 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1208 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1209 "Interface IPv6 config commands\n"
1210 "Neighbor discovery\n"
1211 "Prefix information\n"
1212 "IPv6 prefix\n"
1213 "Valid lifetime in seconds\n"
1214 "Infinite valid lifetime\n"
1215 "Preferred lifetime in seconds\n"
1216 "Infinite preferred lifetime\n"
1217 "Do not use prefix for onlink determination\n"
1218 "Do not use prefix for autoconfiguration\n")
1219
1220ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001221 ipv6_nd_prefix_val_rev_cmd,
1222 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1223 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1224 "Interface IPv6 config commands\n"
1225 "Neighbor discovery\n"
1226 "Prefix information\n"
1227 "IPv6 prefix\n"
1228 "Valid lifetime in seconds\n"
1229 "Infinite valid lifetime\n"
1230 "Preferred lifetime in seconds\n"
1231 "Infinite preferred lifetime\n"
1232 "Do not use prefix for autoconfiguration\n"
1233 "Do not use prefix for onlink determination\n")
1234
1235ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001236 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1237 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1238 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1239 "Interface IPv6 config commands\n"
1240 "Neighbor discovery\n"
1241 "Prefix information\n"
1242 "IPv6 prefix\n"
1243 "Valid lifetime in seconds\n"
1244 "Infinite valid lifetime\n"
1245 "Preferred lifetime in seconds\n"
1246 "Infinite preferred lifetime\n"
1247 "Do not use prefix for autoconfiguration\n"
1248 "Do not use prefix for onlink determination\n"
1249 "Set Router Address flag\n")
1250
1251ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001252 ipv6_nd_prefix_val_noauto_cmd,
1253 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1254 "(<0-4294967295>|infinite) (no-autoconfig|)",
1255 "Interface IPv6 config commands\n"
1256 "Neighbor discovery\n"
1257 "Prefix information\n"
1258 "IPv6 prefix\n"
1259 "Valid lifetime in seconds\n"
1260 "Infinite valid lifetime\n"
1261 "Preferred lifetime in seconds\n"
1262 "Infinite preferred lifetime\n"
vincent7cee1bb2005-03-25 13:08:53 +00001263 "Do not use prefix for autoconfiguration")
hasso3e31cde2004-05-18 11:58:59 +00001264
1265ALIAS (ipv6_nd_prefix,
1266 ipv6_nd_prefix_val_offlink_cmd,
1267 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1268 "(<0-4294967295>|infinite) (off-link|)",
1269 "Interface IPv6 config commands\n"
1270 "Neighbor discovery\n"
1271 "Prefix information\n"
1272 "IPv6 prefix\n"
1273 "Valid lifetime in seconds\n"
1274 "Infinite valid lifetime\n"
1275 "Preferred lifetime in seconds\n"
1276 "Infinite preferred lifetime\n"
1277 "Do not use prefix for onlink determination\n")
1278
1279ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001280 ipv6_nd_prefix_val_rtaddr_cmd,
1281 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1282 "(<0-4294967295>|infinite) (router-address|)",
1283 "Interface IPv6 config commands\n"
1284 "Neighbor discovery\n"
1285 "Prefix information\n"
1286 "IPv6 prefix\n"
1287 "Valid lifetime in seconds\n"
1288 "Infinite valid lifetime\n"
1289 "Preferred lifetime in seconds\n"
1290 "Infinite preferred lifetime\n"
1291 "Set Router Address flag\n")
1292
1293ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001294 ipv6_nd_prefix_val_cmd,
1295 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1296 "(<0-4294967295>|infinite)",
1297 "Interface IPv6 config commands\n"
1298 "Neighbor discovery\n"
1299 "Prefix information\n"
1300 "IPv6 prefix\n"
1301 "Valid lifetime in seconds\n"
1302 "Infinite valid lifetime\n"
1303 "Preferred lifetime in seconds\n"
1304 "Infinite preferred lifetime\n")
1305
1306ALIAS (ipv6_nd_prefix,
1307 ipv6_nd_prefix_noval_cmd,
1308 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1309 "Interface IPv6 config commands\n"
1310 "Neighbor discovery\n"
1311 "Prefix information\n"
1312 "IPv6 prefix\n"
1313 "Do not use prefix for autoconfiguration\n"
1314 "Do not use prefix for onlink determination\n")
1315
1316ALIAS (ipv6_nd_prefix,
1317 ipv6_nd_prefix_noval_rev_cmd,
1318 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1319 "Interface IPv6 config commands\n"
1320 "Neighbor discovery\n"
1321 "Prefix information\n"
1322 "IPv6 prefix\n"
1323 "Do not use prefix for onlink determination\n"
1324 "Do not use prefix for autoconfiguration\n")
1325
1326ALIAS (ipv6_nd_prefix,
1327 ipv6_nd_prefix_noval_noauto_cmd,
1328 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1329 "Interface IPv6 config commands\n"
1330 "Neighbor discovery\n"
1331 "Prefix information\n"
1332 "IPv6 prefix\n"
1333 "Do not use prefix for autoconfiguration\n")
1334
1335ALIAS (ipv6_nd_prefix,
1336 ipv6_nd_prefix_noval_offlink_cmd,
1337 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1338 "Interface IPv6 config commands\n"
1339 "Neighbor discovery\n"
1340 "Prefix information\n"
1341 "IPv6 prefix\n"
1342 "Do not use prefix for onlink determination\n")
1343
1344ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001345 ipv6_nd_prefix_noval_rtaddr_cmd,
1346 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1347 "Interface IPv6 config commands\n"
1348 "Neighbor discovery\n"
1349 "Prefix information\n"
1350 "IPv6 prefix\n"
1351 "Set Router Address flag\n")
1352
1353ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001354 ipv6_nd_prefix_prefix_cmd,
1355 "ipv6 nd prefix X:X::X:X/M",
1356 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001357 "Neighbor discovery\n"
1358 "Prefix information\n"
1359 "IPv6 prefix\n")
1360
hasso3e31cde2004-05-18 11:58:59 +00001361DEFUN (no_ipv6_nd_prefix,
1362 no_ipv6_nd_prefix_cmd,
1363 "no ipv6 nd prefix IPV6PREFIX",
paul718e3742002-12-13 20:15:29 +00001364 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001365 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001366 "Neighbor discovery\n"
1367 "Prefix information\n"
1368 "IPv6 prefix\n")
1369{
1370 int ret;
1371 struct interface *ifp;
1372 struct zebra_if *zebra_if;
1373 struct rtadv_prefix rp;
1374
1375 ifp = (struct interface *) vty->index;
1376 zebra_if = ifp->info;
1377
1378 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1379 if (!ret)
1380 {
1381 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1382 return CMD_WARNING;
1383 }
1384
1385 ret = rtadv_prefix_reset (zebra_if, &rp);
1386 if (!ret)
1387 {
1388 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1389 return CMD_WARNING;
1390 }
1391
1392 return CMD_SUCCESS;
1393}
Chris Caputob60668d2009-05-03 04:40:57 +00001394
1395DEFUN (ipv6_nd_router_preference,
1396 ipv6_nd_router_preference_cmd,
1397 "ipv6 nd router-preference (high|medium|low)",
1398 "Interface IPv6 config commands\n"
1399 "Neighbor discovery\n"
1400 "Default router preference\n"
1401 "High default router preference\n"
1402 "Low default router preference\n"
1403 "Medium default router preference (default)\n")
1404{
1405 struct interface *ifp;
1406 struct zebra_if *zif;
1407 int i = 0;
1408
1409 ifp = (struct interface *) vty->index;
1410 zif = ifp->info;
1411
1412 while (0 != rtadv_pref_strs[i])
1413 {
1414 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1415 {
1416 zif->rtadv.DefaultPreference = i;
1417 return CMD_SUCCESS;
1418 }
1419 i++;
1420 }
1421
1422 return CMD_ERR_NO_MATCH;
1423}
1424
1425DEFUN (no_ipv6_nd_router_preference,
1426 no_ipv6_nd_router_preference_cmd,
1427 "no ipv6 nd router-preference",
1428 NO_STR
1429 "Interface IPv6 config commands\n"
1430 "Neighbor discovery\n"
1431 "Default router preference\n")
1432{
1433 struct interface *ifp;
1434 struct zebra_if *zif;
1435
1436 ifp = (struct interface *) vty->index;
1437 zif = ifp->info;
1438
1439 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1440
1441 return CMD_SUCCESS;
1442}
1443
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001444DEFUN (ipv6_nd_mtu,
1445 ipv6_nd_mtu_cmd,
1446 "ipv6 nd mtu <1-65535>",
1447 "Interface IPv6 config commands\n"
1448 "Neighbor discovery\n"
1449 "Advertised MTU\n"
1450 "MTU in bytes\n")
1451{
1452 struct interface *ifp = (struct interface *) vty->index;
1453 struct zebra_if *zif = ifp->info;
1454 VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
1455 return CMD_SUCCESS;
1456}
1457
1458DEFUN (no_ipv6_nd_mtu,
1459 no_ipv6_nd_mtu_cmd,
1460 "no ipv6 nd mtu",
1461 NO_STR
1462 "Interface IPv6 config commands\n"
1463 "Neighbor discovery\n"
1464 "Advertised MTU\n")
1465{
1466 struct interface *ifp = (struct interface *) vty->index;
1467 struct zebra_if *zif = ifp->info;
1468 zif->rtadv.AdvLinkMTU = 0;
1469 return CMD_SUCCESS;
1470}
1471
1472ALIAS (no_ipv6_nd_mtu,
1473 no_ipv6_nd_mtu_val_cmd,
1474 "no ipv6 nd mtu <1-65535>",
1475 NO_STR
1476 "Interface IPv6 config commands\n"
1477 "Neighbor discovery\n"
1478 "Advertised MTU\n"
1479 "MTU in bytes\n")
1480
paul718e3742002-12-13 20:15:29 +00001481/* Write configuration about router advertisement. */
1482void
1483rtadv_config_write (struct vty *vty, struct interface *ifp)
1484{
1485 struct zebra_if *zif;
hasso52dc7ee2004-09-23 19:18:23 +00001486 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001487 struct rtadv_prefix *rprefix;
1488 u_char buf[INET6_ADDRSTRLEN];
vincent7cee1bb2005-03-25 13:08:53 +00001489 int interval;
paul718e3742002-12-13 20:15:29 +00001490
1491 if (! rtadv)
1492 return;
1493
1494 zif = ifp->info;
1495
1496 if (! if_is_loopback (ifp))
1497 {
1498 if (zif->rtadv.AdvSendAdvertisements)
1499 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1500 else
1501 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1502 }
1503
vincent7cee1bb2005-03-25 13:08:53 +00001504
1505 interval = zif->rtadv.MaxRtrAdvInterval;
1506 if (interval % 1000)
1507 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1508 VTY_NEWLINE);
1509 else
1510 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1511 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
paul718e3742002-12-13 20:15:29 +00001512 VTY_NEWLINE);
1513
1514 if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
1515 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1516 VTY_NEWLINE);
1517
1518 if (zif->rtadv.AdvReachableTime)
1519 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1520 VTY_NEWLINE);
1521
1522 if (zif->rtadv.AdvManagedFlag)
1523 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1524
1525 if (zif->rtadv.AdvOtherConfigFlag)
1526 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1527
Chris Caputob60668d2009-05-03 04:40:57 +00001528 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1529 vty_out (vty, " ipv6 nd router-preference %s%s",
1530 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1531 VTY_NEWLINE);
1532
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001533 if (zif->rtadv.AdvLinkMTU)
1534 vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
1535
paul1eb8ef22005-04-07 07:30:20 +00001536 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +00001537 {
hasso3e31cde2004-05-18 11:58:59 +00001538 vty_out (vty, " ipv6 nd prefix %s/%d",
paul718e3742002-12-13 20:15:29 +00001539 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
hassoc9e52be2004-09-26 16:09:34 +00001540 (char *) buf, INET6_ADDRSTRLEN),
hasso3e31cde2004-05-18 11:58:59 +00001541 rprefix->prefix.prefixlen);
1542 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1543 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1544 {
1545 if (rprefix->AdvValidLifetime == UINT32_MAX)
1546 vty_out (vty, " infinite");
1547 else
1548 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1549 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1550 vty_out (vty, " infinite");
1551 else
1552 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1553 }
1554 if (!rprefix->AdvOnLinkFlag)
1555 vty_out (vty, " off-link");
1556 if (!rprefix->AdvAutonomousFlag)
1557 vty_out (vty, " no-autoconfig");
vincent7cee1bb2005-03-25 13:08:53 +00001558 if (rprefix->AdvRouterAddressFlag)
1559 vty_out (vty, " router-address");
paul718e3742002-12-13 20:15:29 +00001560 vty_out (vty, "%s", VTY_NEWLINE);
1561 }
1562}
1563
paul718e3742002-12-13 20:15:29 +00001564
paula1ac18c2005-06-28 17:17:12 +00001565static void
paul718e3742002-12-13 20:15:29 +00001566rtadv_event (enum rtadv_event event, int val)
1567{
1568 switch (event)
1569 {
1570 case RTADV_START:
1571 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001572 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001573 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001574 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1575 NULL, 0);
paul718e3742002-12-13 20:15:29 +00001576 break;
1577 case RTADV_STOP:
1578 if (rtadv->ra_timer)
1579 {
1580 thread_cancel (rtadv->ra_timer);
1581 rtadv->ra_timer = NULL;
1582 }
1583 if (rtadv->ra_read)
1584 {
1585 thread_cancel (rtadv->ra_read);
1586 rtadv->ra_read = NULL;
1587 }
1588 break;
1589 case RTADV_TIMER:
1590 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001591 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1592 val);
paul718e3742002-12-13 20:15:29 +00001593 break;
vincent7cee1bb2005-03-25 13:08:53 +00001594 case RTADV_TIMER_MSEC:
1595 if (! rtadv->ra_timer)
1596 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1597 NULL, val);
1598 break;
paul718e3742002-12-13 20:15:29 +00001599 case RTADV_READ:
1600 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001601 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001602 break;
1603 default:
1604 break;
1605 }
1606 return;
1607}
1608
1609void
paula1ac18c2005-06-28 17:17:12 +00001610rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001611{
1612 int sock;
1613
1614 sock = rtadv_make_socket ();
1615 if (sock < 0)
1616 return;
1617
1618 rtadv = rtadv_new ();
1619 rtadv->sock = sock;
1620
1621 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1622 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
paul718e3742002-12-13 20:15:29 +00001623 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001624 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
paul718e3742002-12-13 20:15:29 +00001625 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1626 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1627 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1628 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1629 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1630 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1631 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1632 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1633 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001634 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1635 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1636 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1637 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1638 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1639 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1640 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1641 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001642 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001643 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1644 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001645 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1646 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1647 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001648 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001649 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1650 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1651 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1652 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1653 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001654 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001655 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1656 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
Chris Caputob60668d2009-05-03 04:40:57 +00001657 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1658 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001659 install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
1660 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
1661 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
paul718e3742002-12-13 20:15:29 +00001662}
1663
paula1ac18c2005-06-28 17:17:12 +00001664static int
paul718e3742002-12-13 20:15:29 +00001665if_join_all_router (int sock, struct interface *ifp)
1666{
1667 int ret;
1668
1669 struct ipv6_mreq mreq;
1670
1671 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1672 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1673 mreq.ipv6mr_interface = ifp->ifindex;
1674
1675 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1676 (char *) &mreq, sizeof mreq);
1677 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001678 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001679
1680 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1681
1682 return 0;
1683}
1684
paula1ac18c2005-06-28 17:17:12 +00001685static int
paul718e3742002-12-13 20:15:29 +00001686if_leave_all_router (int sock, struct interface *ifp)
1687{
1688 int ret;
1689
1690 struct ipv6_mreq mreq;
1691
1692 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1693 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1694 mreq.ipv6mr_interface = ifp->ifindex;
1695
1696 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1697 (char *) &mreq, sizeof mreq);
1698 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001699 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001700
1701 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1702
1703 return 0;
1704}
1705
1706#else
1707void
paula1ac18c2005-06-28 17:17:12 +00001708rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001709{
1710 /* Empty.*/;
1711}
1712#endif /* RTADV && HAVE_IPV6 */