blob: 01f88336ba268e4f608f8b0a88c58de7828763b1 [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;
Denis Ovsienkod660f692011-12-30 21:55:49 +0400166 u_int16_t pkt_RouterLifetime;
paul718e3742002-12-13 20:15:29 +0000167
gdt57492d52004-08-11 18:06:38 +0000168 /*
169 * Allocate control message bufffer. This is dynamic because
170 * CMSG_SPACE is not guaranteed not to call a function. Note that
171 * the size will be different on different architectures due to
172 * differing alignment rules.
173 */
174 if (adata == NULL)
175 {
176 /* XXX Free on shutdown. */
177 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
178
179 if (adata == NULL)
180 zlog_err("rtadv_send_packet: can't malloc control data\n");
181 }
182
paul718e3742002-12-13 20:15:29 +0000183 /* Logging of packet. */
184 if (IS_ZEBRA_DEBUG_PACKET)
ajsb6178002004-12-07 21:12:56 +0000185 zlog_debug ("Router advertisement send to %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000186
187 /* Fill in sockaddr_in6. */
188 memset (&addr, 0, sizeof (struct sockaddr_in6));
189 addr.sin6_family = AF_INET6;
190#ifdef SIN6_LEN
191 addr.sin6_len = sizeof (struct sockaddr_in6);
192#endif /* SIN6_LEN */
193 addr.sin6_port = htons (IPPROTO_ICMPV6);
194 memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
195
196 /* Fetch interface information. */
197 zif = ifp->info;
198
199 /* Make router advertisement message. */
200 rtadv = (struct nd_router_advert *) buf;
201
202 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
203 rtadv->nd_ra_code = 0;
204 rtadv->nd_ra_cksum = 0;
205
206 rtadv->nd_ra_curhoplimit = 64;
Chris Caputob60668d2009-05-03 04:40:57 +0000207
208 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
209 rtadv->nd_ra_flags_reserved =
210 zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
211 rtadv->nd_ra_flags_reserved <<= 3;
212
paul718e3742002-12-13 20:15:29 +0000213 if (zif->rtadv.AdvManagedFlag)
214 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
215 if (zif->rtadv.AdvOtherConfigFlag)
216 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
vincent7cee1bb2005-03-25 13:08:53 +0000217 if (zif->rtadv.AdvHomeAgentFlag)
218 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
Denis Ovsienkod660f692011-12-30 21:55:49 +0400219 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
220 * AdvDefaultLifetime is by default based on the value of
221 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
222 * field of Router Advertisements. Given that this field is expressed
223 * in seconds, a small MaxRtrAdvInterval value can result in a zero
224 * value for this field. To prevent this, routers SHOULD keep
225 * AdvDefaultLifetime in at least one second, even if the use of
226 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
227 pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ?
228 zif->rtadv.AdvDefaultLifetime :
229 MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
230 rtadv->nd_ra_router_lifetime = htons (pkt_RouterLifetime);
paul718e3742002-12-13 20:15:29 +0000231 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
232 rtadv->nd_ra_retransmit = htonl (0);
233
234 len = sizeof (struct nd_router_advert);
235
Denis Ovsienkod660f692011-12-30 21:55:49 +0400236 /* If both the Home Agent Preference and Home Agent Lifetime are set to
237 * their default values specified above, this option SHOULD NOT be
238 * included in the Router Advertisement messages sent by this home
239 * agent. -- RFC6275, 7.4 */
240 if
241 (
242 zif->rtadv.AdvHomeAgentFlag &&
243 (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1)
244 )
vincent7cee1bb2005-03-25 13:08:53 +0000245 {
246 struct nd_opt_homeagent_info *ndopt_hai =
247 (struct nd_opt_homeagent_info *)(buf + len);
248 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
249 ndopt_hai->nd_opt_hai_len = 1;
250 ndopt_hai->nd_opt_hai_reserved = 0;
251 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
Denis Ovsienkod660f692011-12-30 21:55:49 +0400252 /* 16-bit unsigned integer. The lifetime associated with the home
253 * agent in units of seconds. The default value is the same as the
254 * Router Lifetime, as specified in the main body of the Router
255 * Advertisement. The maximum value corresponds to 18.2 hours. A
256 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
257 ndopt_hai->nd_opt_hai_lifetime = htons
258 (
259 zif->rtadv.HomeAgentLifetime != -1 ?
260 zif->rtadv.HomeAgentLifetime :
261 MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/
262 );
vincent7cee1bb2005-03-25 13:08:53 +0000263 len += sizeof(struct nd_opt_homeagent_info);
264 }
265
266 if (zif->rtadv.AdvIntervalOption)
267 {
268 struct nd_opt_adv_interval *ndopt_adv =
269 (struct nd_opt_adv_interval *)(buf + len);
270 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
271 ndopt_adv->nd_opt_ai_len = 1;
272 ndopt_adv->nd_opt_ai_reserved = 0;
273 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
274 len += sizeof(struct nd_opt_adv_interval);
275 }
276
paul718e3742002-12-13 20:15:29 +0000277 /* Fill in prefix. */
paul1eb8ef22005-04-07 07:30:20 +0000278 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +0000279 {
280 struct nd_opt_prefix_info *pinfo;
paul718e3742002-12-13 20:15:29 +0000281
282 pinfo = (struct nd_opt_prefix_info *) (buf + len);
283
284 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
285 pinfo->nd_opt_pi_len = 4;
286 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
287
288 pinfo->nd_opt_pi_flags_reserved = 0;
289 if (rprefix->AdvOnLinkFlag)
290 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
291 if (rprefix->AdvAutonomousFlag)
292 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
vincent7cee1bb2005-03-25 13:08:53 +0000293 if (rprefix->AdvRouterAddressFlag)
294 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
paul718e3742002-12-13 20:15:29 +0000295
296 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
297 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
298 pinfo->nd_opt_pi_reserved2 = 0;
299
300 memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
301 sizeof (struct in6_addr));
302
303#ifdef DEBUG
304 {
305 u_char buf[INET6_ADDRSTRLEN];
306
ajsb6178002004-12-07 21:12:56 +0000307 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
hasso3e31cde2004-05-18 11:58:59 +0000308 buf, INET6_ADDRSTRLEN));
paul718e3742002-12-13 20:15:29 +0000309
310 }
311#endif /* DEBUG */
312
313 len += sizeof (struct nd_opt_prefix_info);
314 }
315
316 /* Hardware address. */
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000317#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000318 sdl = &ifp->sdl;
319 if (sdl != NULL && sdl->sdl_alen != 0)
320 {
321 buf[len++] = ND_OPT_SOURCE_LINKADDR;
David Ward50adf782009-08-31 10:42:06 -0400322
323 /* Option length should be rounded up to next octet if
324 the link address does not end on an octet boundary. */
325 buf[len++] = (sdl->sdl_alen + 9) >> 3;
paul718e3742002-12-13 20:15:29 +0000326
327 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
328 len += sdl->sdl_alen;
David Ward50adf782009-08-31 10:42:06 -0400329
330 /* Pad option to end on an octet boundary. */
331 memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
332 len += -(sdl->sdl_alen + 2) & 0x7;
paul718e3742002-12-13 20:15:29 +0000333 }
334#else
335 if (ifp->hw_addr_len != 0)
336 {
337 buf[len++] = ND_OPT_SOURCE_LINKADDR;
David Ward50adf782009-08-31 10:42:06 -0400338
339 /* Option length should be rounded up to next octet if
340 the link address does not end on an octet boundary. */
341 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
paul718e3742002-12-13 20:15:29 +0000342
343 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
344 len += ifp->hw_addr_len;
David Ward50adf782009-08-31 10:42:06 -0400345
346 /* Pad option to end on an octet boundary. */
347 memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
348 len += -(ifp->hw_addr_len + 2) & 0x7;
paul718e3742002-12-13 20:15:29 +0000349 }
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000350#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000351
Denis Ovsienko6ae93c02011-12-27 10:45:36 +0400352 /* MTU */
353 if (zif->rtadv.AdvLinkMTU)
354 {
355 struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len);
356 opt->nd_opt_mtu_type = ND_OPT_MTU;
357 opt->nd_opt_mtu_len = 1;
358 opt->nd_opt_mtu_reserved = 0;
359 opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU);
360 len += sizeof (struct nd_opt_mtu);
361 }
362
paul718e3742002-12-13 20:15:29 +0000363 msg.msg_name = (void *) &addr;
364 msg.msg_namelen = sizeof (struct sockaddr_in6);
365 msg.msg_iov = &iov;
366 msg.msg_iovlen = 1;
367 msg.msg_control = (void *) adata;
gdtf841e022004-08-11 19:20:01 +0000368 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
gdt57492d52004-08-11 18:06:38 +0000369 msg.msg_flags = 0;
paul718e3742002-12-13 20:15:29 +0000370 iov.iov_base = buf;
371 iov.iov_len = len;
372
ajsb99760a2005-01-04 16:24:43 +0000373 cmsgptr = ZCMSG_FIRSTHDR(&msg);
gdt57492d52004-08-11 18:06:38 +0000374 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
paul718e3742002-12-13 20:15:29 +0000375 cmsgptr->cmsg_level = IPPROTO_IPV6;
376 cmsgptr->cmsg_type = IPV6_PKTINFO;
gdt80893812004-08-11 15:58:00 +0000377
paul718e3742002-12-13 20:15:29 +0000378 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
379 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
380 pkt->ipi6_ifindex = ifp->ifindex;
381
382 ret = sendmsg (sock, &msg, 0);
gdt9ccabd12004-01-06 18:23:02 +0000383 if (ret < 0)
384 {
385 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
ajs6099b3b2004-11-20 02:06:59 +0000386 errno, safe_strerror(errno));
gdt9ccabd12004-01-06 18:23:02 +0000387 }
paul718e3742002-12-13 20:15:29 +0000388}
389
paula1ac18c2005-06-28 17:17:12 +0000390static int
paul718e3742002-12-13 20:15:29 +0000391rtadv_timer (struct thread *thread)
392{
paul1eb8ef22005-04-07 07:30:20 +0000393 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000394 struct interface *ifp;
395 struct zebra_if *zif;
vincent7cee1bb2005-03-25 13:08:53 +0000396 int period;
paul718e3742002-12-13 20:15:29 +0000397
398 rtadv->ra_timer = NULL;
vincent7cee1bb2005-03-25 13:08:53 +0000399 if (rtadv->adv_msec_if_count == 0)
400 {
401 period = 1000; /* 1 s */
402 rtadv_event (RTADV_TIMER, 1 /* 1 s */);
403 }
404 else
405 {
406 period = 10; /* 10 ms */
407 rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
408 }
paul718e3742002-12-13 20:15:29 +0000409
paul1eb8ef22005-04-07 07:30:20 +0000410 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
paul718e3742002-12-13 20:15:29 +0000411 {
Denis Ovsienkofb5174a2011-12-27 10:18:47 +0400412 if (if_is_loopback (ifp) || ! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000413 continue;
414
415 zif = ifp->info;
416
417 if (zif->rtadv.AdvSendAdvertisements)
vincent7cee1bb2005-03-25 13:08:53 +0000418 {
419 zif->rtadv.AdvIntervalTimer -= period;
420 if (zif->rtadv.AdvIntervalTimer <= 0)
421 {
Denis Ovsienkod660f692011-12-30 21:55:49 +0400422 /* FIXME: using MaxRtrAdvInterval each time isn't what section
423 6.2.4 of RFC4861 tells to do. */
vincent7cee1bb2005-03-25 13:08:53 +0000424 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
425 rtadv_send_packet (rtadv->sock, ifp);
426 }
427 }
paul718e3742002-12-13 20:15:29 +0000428 }
429 return 0;
430}
431
paula1ac18c2005-06-28 17:17:12 +0000432static void
paul718e3742002-12-13 20:15:29 +0000433rtadv_process_solicit (struct interface *ifp)
434{
435 zlog_info ("Router solicitation received on %s", ifp->name);
436
437 rtadv_send_packet (rtadv->sock, ifp);
438}
439
paula1ac18c2005-06-28 17:17:12 +0000440static void
441rtadv_process_advert (void)
paul718e3742002-12-13 20:15:29 +0000442{
443 zlog_info ("Router advertisement received");
444}
445
paula1ac18c2005-06-28 17:17:12 +0000446static void
hassofce954f2004-10-07 20:29:24 +0000447rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
paul718e3742002-12-13 20:15:29 +0000448{
449 struct icmp6_hdr *icmph;
450 struct interface *ifp;
451 struct zebra_if *zif;
452
453 /* Interface search. */
454 ifp = if_lookup_by_index (ifindex);
455 if (ifp == NULL)
456 {
457 zlog_warn ("Unknown interface index: %d", ifindex);
458 return;
459 }
460
461 if (if_is_loopback (ifp))
462 return;
463
464 /* Check interface configuration. */
465 zif = ifp->info;
466 if (! zif->rtadv.AdvSendAdvertisements)
467 return;
468
469 /* ICMP message length check. */
470 if (len < sizeof (struct icmp6_hdr))
471 {
472 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
473 return;
474 }
475
476 icmph = (struct icmp6_hdr *) buf;
477
478 /* ICMP message type check. */
479 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
480 icmph->icmp6_type != ND_ROUTER_ADVERT)
481 {
482 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
483 return;
484 }
485
486 /* Hoplimit check. */
487 if (hoplimit >= 0 && hoplimit != 255)
488 {
489 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
490 hoplimit);
491 return;
492 }
493
494 /* Check ICMP message type. */
495 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
496 rtadv_process_solicit (ifp);
497 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
498 rtadv_process_advert ();
499
500 return;
501}
502
paula1ac18c2005-06-28 17:17:12 +0000503static int
paul718e3742002-12-13 20:15:29 +0000504rtadv_read (struct thread *thread)
505{
506 int sock;
507 int len;
508 u_char buf[RTADV_MSG_SIZE];
509 struct sockaddr_in6 from;
Stephen Hemmingerb0b709a2009-12-08 13:26:14 +0300510 unsigned int ifindex = 0;
paul718e3742002-12-13 20:15:29 +0000511 int hoplimit = -1;
512
513 sock = THREAD_FD (thread);
514 rtadv->ra_read = NULL;
515
516 /* Register myself. */
517 rtadv_event (RTADV_READ, sock);
518
519 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
520
521 if (len < 0)
522 {
ajs6099b3b2004-11-20 02:06:59 +0000523 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000524 return len;
525 }
526
hassofce954f2004-10-07 20:29:24 +0000527 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
paul718e3742002-12-13 20:15:29 +0000528
529 return 0;
530}
531
paula1ac18c2005-06-28 17:17:12 +0000532static int
paul718e3742002-12-13 20:15:29 +0000533rtadv_make_socket (void)
534{
535 int sock;
536 int ret;
537 struct icmp6_filter filter;
538
pauledd7c242003-06-04 13:59:38 +0000539 if ( zserv_privs.change (ZPRIVS_RAISE) )
540 zlog_err ("rtadv_make_socket: could not raise privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000541 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000542
paul718e3742002-12-13 20:15:29 +0000543 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
544
pauledd7c242003-06-04 13:59:38 +0000545 if ( zserv_privs.change (ZPRIVS_LOWER) )
546 zlog_err ("rtadv_make_socket: could not lower privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000547 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000548
paul718e3742002-12-13 20:15:29 +0000549 /* When we can't make ICMPV6 socket simply back. Router
550 advertisement feature will not be supported. */
551 if (sock < 0)
552 return -1;
553
554 ret = setsockopt_ipv6_pktinfo (sock, 1);
555 if (ret < 0)
556 return ret;
paul718e3742002-12-13 20:15:29 +0000557 ret = setsockopt_ipv6_multicast_loop (sock, 0);
558 if (ret < 0)
559 return ret;
560 ret = setsockopt_ipv6_unicast_hops (sock, 255);
561 if (ret < 0)
562 return ret;
563 ret = setsockopt_ipv6_multicast_hops (sock, 255);
564 if (ret < 0)
565 return ret;
566 ret = setsockopt_ipv6_hoplimit (sock, 1);
567 if (ret < 0)
568 return ret;
569
570 ICMP6_FILTER_SETBLOCKALL(&filter);
571 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
572 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
573
574 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
575 sizeof (struct icmp6_filter));
576 if (ret < 0)
577 {
ajs6099b3b2004-11-20 02:06:59 +0000578 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000579 return ret;
580 }
581
582 return sock;
583}
584
paula1ac18c2005-06-28 17:17:12 +0000585static struct rtadv_prefix *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800586rtadv_prefix_new (void)
paul718e3742002-12-13 20:15:29 +0000587{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700588 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
paul718e3742002-12-13 20:15:29 +0000589}
590
paula1ac18c2005-06-28 17:17:12 +0000591static void
paul718e3742002-12-13 20:15:29 +0000592rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
593{
594 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
595}
596
paula1ac18c2005-06-28 17:17:12 +0000597static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000598rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000599{
hasso52dc7ee2004-09-23 19:18:23 +0000600 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000601 struct rtadv_prefix *rprefix;
602
paul1eb8ef22005-04-07 07:30:20 +0000603 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
604 if (prefix_same (&rprefix->prefix, p))
605 return rprefix;
paul718e3742002-12-13 20:15:29 +0000606 return NULL;
607}
608
paula1ac18c2005-06-28 17:17:12 +0000609static struct rtadv_prefix *
hasso52dc7ee2004-09-23 19:18:23 +0000610rtadv_prefix_get (struct list *rplist, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000611{
612 struct rtadv_prefix *rprefix;
613
614 rprefix = rtadv_prefix_lookup (rplist, p);
615 if (rprefix)
616 return rprefix;
617
618 rprefix = rtadv_prefix_new ();
619 memcpy (&rprefix->prefix, p, sizeof (struct prefix));
620 listnode_add (rplist, rprefix);
621
622 return rprefix;
623}
624
paula1ac18c2005-06-28 17:17:12 +0000625static void
paul718e3742002-12-13 20:15:29 +0000626rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
627{
628 struct rtadv_prefix *rprefix;
629
630 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
631
632 /* Set parameters. */
633 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
634 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
635 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
636 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
vincent7cee1bb2005-03-25 13:08:53 +0000637 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
paul718e3742002-12-13 20:15:29 +0000638}
639
paula1ac18c2005-06-28 17:17:12 +0000640static int
paul718e3742002-12-13 20:15:29 +0000641rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
642{
643 struct rtadv_prefix *rprefix;
644
645 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
646 if (rprefix != NULL)
647 {
648 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
649 rtadv_prefix_free (rprefix);
650 return 1;
651 }
652 else
653 return 0;
654}
655
656DEFUN (ipv6_nd_suppress_ra,
657 ipv6_nd_suppress_ra_cmd,
658 "ipv6 nd suppress-ra",
hasso3e31cde2004-05-18 11:58:59 +0000659 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000660 "Neighbor discovery\n"
661 "Suppress Router Advertisement\n")
662{
663 struct interface *ifp;
664 struct zebra_if *zif;
665
666 ifp = vty->index;
667 zif = ifp->info;
668
669 if (if_is_loopback (ifp))
670 {
671 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
672 return CMD_WARNING;
673 }
674
675 if (zif->rtadv.AdvSendAdvertisements)
676 {
677 zif->rtadv.AdvSendAdvertisements = 0;
678 zif->rtadv.AdvIntervalTimer = 0;
679 rtadv->adv_if_count--;
680
681 if_leave_all_router (rtadv->sock, ifp);
682
683 if (rtadv->adv_if_count == 0)
684 rtadv_event (RTADV_STOP, 0);
685 }
686
687 return CMD_SUCCESS;
688}
689
paul718e3742002-12-13 20:15:29 +0000690DEFUN (no_ipv6_nd_suppress_ra,
691 no_ipv6_nd_suppress_ra_cmd,
692 "no ipv6 nd suppress-ra",
693 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000694 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000695 "Neighbor discovery\n"
696 "Suppress Router Advertisement\n")
697{
698 struct interface *ifp;
699 struct zebra_if *zif;
700
701 ifp = vty->index;
702 zif = ifp->info;
703
704 if (if_is_loopback (ifp))
705 {
706 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
707 return CMD_WARNING;
708 }
709
710 if (! zif->rtadv.AdvSendAdvertisements)
711 {
712 zif->rtadv.AdvSendAdvertisements = 1;
713 zif->rtadv.AdvIntervalTimer = 0;
714 rtadv->adv_if_count++;
715
716 if_join_all_router (rtadv->sock, ifp);
717
718 if (rtadv->adv_if_count == 1)
719 rtadv_event (RTADV_START, rtadv->sock);
720 }
721
722 return CMD_SUCCESS;
723}
724
vincent7cee1bb2005-03-25 13:08:53 +0000725DEFUN (ipv6_nd_ra_interval_msec,
726 ipv6_nd_ra_interval_msec_cmd,
727 "ipv6 nd ra-interval msec MILLISECONDS",
728 "Interface IPv6 config commands\n"
729 "Neighbor discovery\n"
730 "Router Advertisement interval\n"
731 "Router Advertisement interval in milliseconds\n")
732{
733 int interval;
734 struct interface *ifp;
735 struct zebra_if *zif;
736
737 ifp = (struct interface *) vty->index;
738 zif = ifp->info;
739
740 interval = atoi (argv[0]);
741
Denis Ovsienkod660f692011-12-30 21:55:49 +0400742 if
743 (
744 interval < 70 || interval > 1800000 ||
745 (zif->rtadv.AdvDefaultLifetime != -1 && interval > zif->rtadv.AdvDefaultLifetime * 1000)
746 )
vincent7cee1bb2005-03-25 13:08:53 +0000747 {
748 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
749 return CMD_WARNING;
750 }
751
752 if (zif->rtadv.MaxRtrAdvInterval % 1000)
753 rtadv->adv_msec_if_count--;
754
755 if (interval % 1000)
756 rtadv->adv_msec_if_count++;
757
758 zif->rtadv.MaxRtrAdvInterval = interval;
759 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
760 zif->rtadv.AdvIntervalTimer = 0;
761
762 return CMD_SUCCESS;
763}
764
paul718e3742002-12-13 20:15:29 +0000765DEFUN (ipv6_nd_ra_interval,
766 ipv6_nd_ra_interval_cmd,
767 "ipv6 nd ra-interval SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000768 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000769 "Neighbor discovery\n"
770 "Router Advertisement interval\n"
771 "Router Advertisement interval in seconds\n")
772{
773 int interval;
774 struct interface *ifp;
775 struct zebra_if *zif;
776
777 ifp = (struct interface *) vty->index;
778 zif = ifp->info;
779
780 interval = atoi (argv[0]);
781
Denis Ovsienkod660f692011-12-30 21:55:49 +0400782 if
783 (
784 interval < 1 || interval > 1800 ||
785 (zif->rtadv.AdvDefaultLifetime != -1 && interval > zif->rtadv.AdvDefaultLifetime)
786 )
paul718e3742002-12-13 20:15:29 +0000787 {
788 vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
789 return CMD_WARNING;
790 }
791
vincent7cee1bb2005-03-25 13:08:53 +0000792 if (zif->rtadv.MaxRtrAdvInterval % 1000)
793 rtadv->adv_msec_if_count--;
794
795 /* convert to milliseconds */
796 interval = interval * 1000;
797
paul718e3742002-12-13 20:15:29 +0000798 zif->rtadv.MaxRtrAdvInterval = interval;
799 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
800 zif->rtadv.AdvIntervalTimer = 0;
801
802 return CMD_SUCCESS;
803}
804
805DEFUN (no_ipv6_nd_ra_interval,
806 no_ipv6_nd_ra_interval_cmd,
807 "no ipv6 nd ra-interval",
808 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000809 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000810 "Neighbor discovery\n"
811 "Router Advertisement interval\n")
812{
813 struct interface *ifp;
814 struct zebra_if *zif;
815
816 ifp = (struct interface *) vty->index;
817 zif = ifp->info;
818
vincent7cee1bb2005-03-25 13:08:53 +0000819 if (zif->rtadv.MaxRtrAdvInterval % 1000)
820 rtadv->adv_msec_if_count--;
821
paul718e3742002-12-13 20:15:29 +0000822 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
823 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
824 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
825
826 return CMD_SUCCESS;
827}
828
829DEFUN (ipv6_nd_ra_lifetime,
830 ipv6_nd_ra_lifetime_cmd,
831 "ipv6 nd ra-lifetime SECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000832 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000833 "Neighbor discovery\n"
834 "Router lifetime\n"
835 "Router lifetime in seconds\n")
836{
837 int lifetime;
838 struct interface *ifp;
839 struct zebra_if *zif;
840
841 ifp = (struct interface *) vty->index;
842 zif = ifp->info;
843
844 lifetime = atoi (argv[0]);
845
Denis Ovsienkod660f692011-12-30 21:55:49 +0400846 /* The value to be placed in the Router Lifetime field
847 * of Router Advertisements sent from the interface,
848 * in seconds. MUST be either zero or between
849 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
850 if
851 (
852 lifetime > RTADV_MAX_RTRLIFETIME ||
853 (lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)
854 )
paul718e3742002-12-13 20:15:29 +0000855 {
856 vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
857 return CMD_WARNING;
858 }
859
860 zif->rtadv.AdvDefaultLifetime = lifetime;
861
862 return CMD_SUCCESS;
863}
864
865DEFUN (no_ipv6_nd_ra_lifetime,
866 no_ipv6_nd_ra_lifetime_cmd,
867 "no ipv6 nd ra-lifetime",
868 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000869 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000870 "Neighbor discovery\n"
871 "Router lifetime\n")
872{
873 struct interface *ifp;
874 struct zebra_if *zif;
875
876 ifp = (struct interface *) vty->index;
877 zif = ifp->info;
878
Denis Ovsienkod660f692011-12-30 21:55:49 +0400879 zif->rtadv.AdvDefaultLifetime = -1;
paul718e3742002-12-13 20:15:29 +0000880
881 return CMD_SUCCESS;
882}
883
884DEFUN (ipv6_nd_reachable_time,
885 ipv6_nd_reachable_time_cmd,
886 "ipv6 nd reachable-time MILLISECONDS",
hasso3e31cde2004-05-18 11:58:59 +0000887 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000888 "Neighbor discovery\n"
889 "Reachable time\n"
890 "Reachable time in milliseconds\n")
891{
892 u_int32_t rtime;
893 struct interface *ifp;
894 struct zebra_if *zif;
895
896 ifp = (struct interface *) vty->index;
897 zif = ifp->info;
898
899 rtime = (u_int32_t) atol (argv[0]);
900
901 if (rtime > RTADV_MAX_REACHABLE_TIME)
902 {
903 vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
904 return CMD_WARNING;
905 }
906
907 zif->rtadv.AdvReachableTime = rtime;
908
909 return CMD_SUCCESS;
910}
911
912DEFUN (no_ipv6_nd_reachable_time,
913 no_ipv6_nd_reachable_time_cmd,
914 "no ipv6 nd reachable-time",
915 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000916 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000917 "Neighbor discovery\n"
918 "Reachable time\n")
919{
920 struct interface *ifp;
921 struct zebra_if *zif;
922
923 ifp = (struct interface *) vty->index;
924 zif = ifp->info;
925
926 zif->rtadv.AdvReachableTime = 0;
927
928 return CMD_SUCCESS;
929}
930
vincent7cee1bb2005-03-25 13:08:53 +0000931DEFUN (ipv6_nd_homeagent_preference,
932 ipv6_nd_homeagent_preference_cmd,
933 "ipv6 nd home-agent-preference PREFERENCE",
934 "Interface IPv6 config commands\n"
935 "Neighbor discovery\n"
936 "Home Agent preference\n"
937 "Home Agent preference value 0..65535\n")
938{
939 u_int32_t hapref;
940 struct interface *ifp;
941 struct zebra_if *zif;
942
943 ifp = (struct interface *) vty->index;
944 zif = ifp->info;
945
946 hapref = (u_int32_t) atol (argv[0]);
947
948 if (hapref > 65535)
949 {
950 vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
951 return CMD_WARNING;
952 }
953
954 zif->rtadv.HomeAgentPreference = hapref;
955
956 return CMD_SUCCESS;
957}
958
959DEFUN (no_ipv6_nd_homeagent_preference,
960 no_ipv6_nd_homeagent_preference_cmd,
961 "no ipv6 nd home-agent-preference",
962 NO_STR
963 "Interface IPv6 config commands\n"
964 "Neighbor discovery\n"
965 "Home Agent preference\n")
966{
967 struct interface *ifp;
968 struct zebra_if *zif;
969
970 ifp = (struct interface *) vty->index;
971 zif = ifp->info;
972
973 zif->rtadv.HomeAgentPreference = 0;
974
975 return CMD_SUCCESS;
976}
977
978DEFUN (ipv6_nd_homeagent_lifetime,
979 ipv6_nd_homeagent_lifetime_cmd,
980 "ipv6 nd home-agent-lifetime SECONDS",
981 "Interface IPv6 config commands\n"
982 "Neighbor discovery\n"
983 "Home Agent lifetime\n"
984 "Home Agent lifetime in seconds\n")
985{
986 u_int32_t ha_ltime;
987 struct interface *ifp;
988 struct zebra_if *zif;
989
990 ifp = (struct interface *) vty->index;
991 zif = ifp->info;
992
993 ha_ltime = (u_int32_t) atol (argv[0]);
994
Denis Ovsienkod660f692011-12-30 21:55:49 +0400995 if (ha_ltime < 1 || ha_ltime > RTADV_MAX_HALIFETIME)
vincent7cee1bb2005-03-25 13:08:53 +0000996 {
997 vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
998 return CMD_WARNING;
999 }
1000
1001 zif->rtadv.HomeAgentLifetime = ha_ltime;
1002
1003 return CMD_SUCCESS;
1004}
1005
1006DEFUN (no_ipv6_nd_homeagent_lifetime,
1007 no_ipv6_nd_homeagent_lifetime_cmd,
1008 "no ipv6 nd home-agent-lifetime",
1009 NO_STR
1010 "Interface IPv6 config commands\n"
1011 "Neighbor discovery\n"
1012 "Home Agent lifetime\n")
1013{
1014 struct interface *ifp;
1015 struct zebra_if *zif;
1016
1017 ifp = (struct interface *) vty->index;
1018 zif = ifp->info;
1019
Denis Ovsienkod660f692011-12-30 21:55:49 +04001020 zif->rtadv.HomeAgentLifetime = -1;
vincent7cee1bb2005-03-25 13:08:53 +00001021
1022 return CMD_SUCCESS;
1023}
1024
paul718e3742002-12-13 20:15:29 +00001025DEFUN (ipv6_nd_managed_config_flag,
1026 ipv6_nd_managed_config_flag_cmd,
1027 "ipv6 nd managed-config-flag",
hasso3e31cde2004-05-18 11:58:59 +00001028 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001029 "Neighbor discovery\n"
1030 "Managed address configuration flag\n")
1031{
1032 struct interface *ifp;
1033 struct zebra_if *zif;
1034
1035 ifp = (struct interface *) vty->index;
1036 zif = ifp->info;
1037
1038 zif->rtadv.AdvManagedFlag = 1;
1039
1040 return CMD_SUCCESS;
1041}
1042
1043DEFUN (no_ipv6_nd_managed_config_flag,
1044 no_ipv6_nd_managed_config_flag_cmd,
1045 "no ipv6 nd managed-config-flag",
1046 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001047 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001048 "Neighbor discovery\n"
1049 "Managed address configuration flag\n")
1050{
1051 struct interface *ifp;
1052 struct zebra_if *zif;
1053
1054 ifp = (struct interface *) vty->index;
1055 zif = ifp->info;
1056
1057 zif->rtadv.AdvManagedFlag = 0;
1058
1059 return CMD_SUCCESS;
1060}
1061
vincent7cee1bb2005-03-25 13:08:53 +00001062DEFUN (ipv6_nd_homeagent_config_flag,
1063 ipv6_nd_homeagent_config_flag_cmd,
1064 "ipv6 nd home-agent-config-flag",
1065 "Interface IPv6 config commands\n"
1066 "Neighbor discovery\n"
1067 "Home Agent configuration flag\n")
1068{
1069 struct interface *ifp;
1070 struct zebra_if *zif;
1071
1072 ifp = (struct interface *) vty->index;
1073 zif = ifp->info;
1074
1075 zif->rtadv.AdvHomeAgentFlag = 1;
1076
1077 return CMD_SUCCESS;
1078}
1079
1080DEFUN (no_ipv6_nd_homeagent_config_flag,
1081 no_ipv6_nd_homeagent_config_flag_cmd,
1082 "no ipv6 nd home-agent-config-flag",
1083 NO_STR
1084 "Interface IPv6 config commands\n"
1085 "Neighbor discovery\n"
1086 "Home Agent configuration flag\n")
1087{
1088 struct interface *ifp;
1089 struct zebra_if *zif;
1090
1091 ifp = (struct interface *) vty->index;
1092 zif = ifp->info;
1093
1094 zif->rtadv.AdvHomeAgentFlag = 0;
1095
1096 return CMD_SUCCESS;
1097}
1098
1099DEFUN (ipv6_nd_adv_interval_config_option,
1100 ipv6_nd_adv_interval_config_option_cmd,
1101 "ipv6 nd adv-interval-option",
1102 "Interface IPv6 config commands\n"
1103 "Neighbor discovery\n"
1104 "Advertisement Interval Option\n")
1105{
1106 struct interface *ifp;
1107 struct zebra_if *zif;
1108
1109 ifp = (struct interface *) vty->index;
1110 zif = ifp->info;
1111
1112 zif->rtadv.AdvIntervalOption = 1;
1113
1114 return CMD_SUCCESS;
1115}
1116
1117DEFUN (no_ipv6_nd_adv_interval_config_option,
1118 no_ipv6_nd_adv_interval_config_option_cmd,
1119 "no ipv6 nd adv-interval-option",
1120 NO_STR
1121 "Interface IPv6 config commands\n"
1122 "Neighbor discovery\n"
1123 "Advertisement Interval Option\n")
1124{
1125 struct interface *ifp;
1126 struct zebra_if *zif;
1127
1128 ifp = (struct interface *) vty->index;
1129 zif = ifp->info;
1130
1131 zif->rtadv.AdvIntervalOption = 0;
1132
1133 return CMD_SUCCESS;
1134}
1135
paul718e3742002-12-13 20:15:29 +00001136DEFUN (ipv6_nd_other_config_flag,
1137 ipv6_nd_other_config_flag_cmd,
1138 "ipv6 nd other-config-flag",
hasso3e31cde2004-05-18 11:58:59 +00001139 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001140 "Neighbor discovery\n"
1141 "Other statefull configuration flag\n")
1142{
1143 struct interface *ifp;
1144 struct zebra_if *zif;
1145
1146 ifp = (struct interface *) vty->index;
1147 zif = ifp->info;
1148
1149 zif->rtadv.AdvOtherConfigFlag = 1;
1150
1151 return CMD_SUCCESS;
1152}
1153
1154DEFUN (no_ipv6_nd_other_config_flag,
1155 no_ipv6_nd_other_config_flag_cmd,
1156 "no ipv6 nd other-config-flag",
1157 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001158 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001159 "Neighbor discovery\n"
1160 "Other statefull configuration flag\n")
1161{
1162 struct interface *ifp;
1163 struct zebra_if *zif;
1164
1165 ifp = (struct interface *) vty->index;
1166 zif = ifp->info;
1167
1168 zif->rtadv.AdvOtherConfigFlag = 0;
1169
1170 return CMD_SUCCESS;
1171}
1172
hasso3e31cde2004-05-18 11:58:59 +00001173DEFUN (ipv6_nd_prefix,
1174 ipv6_nd_prefix_cmd,
1175 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
vincent7cee1bb2005-03-25 13:08:53 +00001176 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
hasso3e31cde2004-05-18 11:58:59 +00001177 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001178 "Neighbor discovery\n"
1179 "Prefix information\n"
1180 "IPv6 prefix\n"
1181 "Valid lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001182 "Infinite valid lifetime\n"
paul718e3742002-12-13 20:15:29 +00001183 "Preferred lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001184 "Infinite preferred lifetime\n"
1185 "Do not use prefix for onlink determination\n"
vincent7cee1bb2005-03-25 13:08:53 +00001186 "Do not use prefix for autoconfiguration\n"
1187 "Set Router Address flag\n")
paul718e3742002-12-13 20:15:29 +00001188{
1189 int i;
1190 int ret;
hasso3e31cde2004-05-18 11:58:59 +00001191 int cursor = 1;
paul718e3742002-12-13 20:15:29 +00001192 struct interface *ifp;
1193 struct zebra_if *zebra_if;
1194 struct rtadv_prefix rp;
1195
1196 ifp = (struct interface *) vty->index;
1197 zebra_if = ifp->info;
1198
1199 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1200 if (!ret)
1201 {
1202 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1203 return CMD_WARNING;
1204 }
hasso3e31cde2004-05-18 11:58:59 +00001205 rp.AdvOnLinkFlag = 1;
1206 rp.AdvAutonomousFlag = 1;
vincent7cee1bb2005-03-25 13:08:53 +00001207 rp.AdvRouterAddressFlag = 0;
hasso3e31cde2004-05-18 11:58:59 +00001208 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1209 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
paul718e3742002-12-13 20:15:29 +00001210
hasso3e31cde2004-05-18 11:58:59 +00001211 if (argc > 1)
paul718e3742002-12-13 20:15:29 +00001212 {
hasso3e31cde2004-05-18 11:58:59 +00001213 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
paul718e3742002-12-13 20:15:29 +00001214 {
hasso3e31cde2004-05-18 11:58:59 +00001215 if ( strncmp (argv[1], "i", 1) == 0)
1216 rp.AdvValidLifetime = UINT32_MAX;
1217 else
1218 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1219 (char **)NULL, 10);
1220
1221 if ( strncmp (argv[2], "i", 1) == 0)
1222 rp.AdvPreferredLifetime = UINT32_MAX;
1223 else
1224 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1225 (char **)NULL, 10);
1226
1227 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1228 {
1229 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1230 return CMD_WARNING;
1231 }
1232 cursor = cursor + 2;
paul718e3742002-12-13 20:15:29 +00001233 }
hasso3e31cde2004-05-18 11:58:59 +00001234 if (argc > cursor)
paul718e3742002-12-13 20:15:29 +00001235 {
hasso3e31cde2004-05-18 11:58:59 +00001236 for (i = cursor; i < argc; i++)
1237 {
1238 if (strncmp (argv[i], "of", 2) == 0)
1239 rp.AdvOnLinkFlag = 0;
1240 if (strncmp (argv[i], "no", 2) == 0)
1241 rp.AdvAutonomousFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +00001242 if (strncmp (argv[i], "ro", 2) == 0)
1243 rp.AdvRouterAddressFlag = 1;
hasso3e31cde2004-05-18 11:58:59 +00001244 }
paul718e3742002-12-13 20:15:29 +00001245 }
1246 }
1247
1248 rtadv_prefix_set (zebra_if, &rp);
1249
1250 return CMD_SUCCESS;
1251}
1252
hasso3e31cde2004-05-18 11:58:59 +00001253ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001254 ipv6_nd_prefix_val_nortaddr_cmd,
1255 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1256 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1257 "Interface IPv6 config commands\n"
1258 "Neighbor discovery\n"
1259 "Prefix information\n"
1260 "IPv6 prefix\n"
1261 "Valid lifetime in seconds\n"
1262 "Infinite valid lifetime\n"
1263 "Preferred lifetime in seconds\n"
1264 "Infinite preferred lifetime\n"
1265 "Do not use prefix for onlink determination\n"
1266 "Do not use prefix for autoconfiguration\n")
1267
1268ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001269 ipv6_nd_prefix_val_rev_cmd,
1270 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1271 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
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 "Do not use prefix for autoconfiguration\n"
1281 "Do not use prefix for onlink determination\n")
1282
1283ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001284 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1285 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1286 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1287 "Interface IPv6 config commands\n"
1288 "Neighbor discovery\n"
1289 "Prefix information\n"
1290 "IPv6 prefix\n"
1291 "Valid lifetime in seconds\n"
1292 "Infinite valid lifetime\n"
1293 "Preferred lifetime in seconds\n"
1294 "Infinite preferred lifetime\n"
1295 "Do not use prefix for autoconfiguration\n"
1296 "Do not use prefix for onlink determination\n"
1297 "Set Router Address flag\n")
1298
1299ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001300 ipv6_nd_prefix_val_noauto_cmd,
1301 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1302 "(<0-4294967295>|infinite) (no-autoconfig|)",
1303 "Interface IPv6 config commands\n"
1304 "Neighbor discovery\n"
1305 "Prefix information\n"
1306 "IPv6 prefix\n"
1307 "Valid lifetime in seconds\n"
1308 "Infinite valid lifetime\n"
1309 "Preferred lifetime in seconds\n"
1310 "Infinite preferred lifetime\n"
vincent7cee1bb2005-03-25 13:08:53 +00001311 "Do not use prefix for autoconfiguration")
hasso3e31cde2004-05-18 11:58:59 +00001312
1313ALIAS (ipv6_nd_prefix,
1314 ipv6_nd_prefix_val_offlink_cmd,
1315 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1316 "(<0-4294967295>|infinite) (off-link|)",
1317 "Interface IPv6 config commands\n"
1318 "Neighbor discovery\n"
1319 "Prefix information\n"
1320 "IPv6 prefix\n"
1321 "Valid lifetime in seconds\n"
1322 "Infinite valid lifetime\n"
1323 "Preferred lifetime in seconds\n"
1324 "Infinite preferred lifetime\n"
1325 "Do not use prefix for onlink determination\n")
1326
1327ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001328 ipv6_nd_prefix_val_rtaddr_cmd,
1329 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1330 "(<0-4294967295>|infinite) (router-address|)",
1331 "Interface IPv6 config commands\n"
1332 "Neighbor discovery\n"
1333 "Prefix information\n"
1334 "IPv6 prefix\n"
1335 "Valid lifetime in seconds\n"
1336 "Infinite valid lifetime\n"
1337 "Preferred lifetime in seconds\n"
1338 "Infinite preferred lifetime\n"
1339 "Set Router Address flag\n")
1340
1341ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001342 ipv6_nd_prefix_val_cmd,
1343 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1344 "(<0-4294967295>|infinite)",
1345 "Interface IPv6 config commands\n"
1346 "Neighbor discovery\n"
1347 "Prefix information\n"
1348 "IPv6 prefix\n"
1349 "Valid lifetime in seconds\n"
1350 "Infinite valid lifetime\n"
1351 "Preferred lifetime in seconds\n"
1352 "Infinite preferred lifetime\n")
1353
1354ALIAS (ipv6_nd_prefix,
1355 ipv6_nd_prefix_noval_cmd,
1356 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1357 "Interface IPv6 config commands\n"
1358 "Neighbor discovery\n"
1359 "Prefix information\n"
1360 "IPv6 prefix\n"
1361 "Do not use prefix for autoconfiguration\n"
1362 "Do not use prefix for onlink determination\n")
1363
1364ALIAS (ipv6_nd_prefix,
1365 ipv6_nd_prefix_noval_rev_cmd,
1366 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1367 "Interface IPv6 config commands\n"
1368 "Neighbor discovery\n"
1369 "Prefix information\n"
1370 "IPv6 prefix\n"
1371 "Do not use prefix for onlink determination\n"
1372 "Do not use prefix for autoconfiguration\n")
1373
1374ALIAS (ipv6_nd_prefix,
1375 ipv6_nd_prefix_noval_noauto_cmd,
1376 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1377 "Interface IPv6 config commands\n"
1378 "Neighbor discovery\n"
1379 "Prefix information\n"
1380 "IPv6 prefix\n"
1381 "Do not use prefix for autoconfiguration\n")
1382
1383ALIAS (ipv6_nd_prefix,
1384 ipv6_nd_prefix_noval_offlink_cmd,
1385 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1386 "Interface IPv6 config commands\n"
1387 "Neighbor discovery\n"
1388 "Prefix information\n"
1389 "IPv6 prefix\n"
1390 "Do not use prefix for onlink determination\n")
1391
1392ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001393 ipv6_nd_prefix_noval_rtaddr_cmd,
1394 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1395 "Interface IPv6 config commands\n"
1396 "Neighbor discovery\n"
1397 "Prefix information\n"
1398 "IPv6 prefix\n"
1399 "Set Router Address flag\n")
1400
1401ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001402 ipv6_nd_prefix_prefix_cmd,
1403 "ipv6 nd prefix X:X::X:X/M",
1404 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001405 "Neighbor discovery\n"
1406 "Prefix information\n"
1407 "IPv6 prefix\n")
1408
hasso3e31cde2004-05-18 11:58:59 +00001409DEFUN (no_ipv6_nd_prefix,
1410 no_ipv6_nd_prefix_cmd,
1411 "no ipv6 nd prefix IPV6PREFIX",
paul718e3742002-12-13 20:15:29 +00001412 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001413 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001414 "Neighbor discovery\n"
1415 "Prefix information\n"
1416 "IPv6 prefix\n")
1417{
1418 int ret;
1419 struct interface *ifp;
1420 struct zebra_if *zebra_if;
1421 struct rtadv_prefix rp;
1422
1423 ifp = (struct interface *) vty->index;
1424 zebra_if = ifp->info;
1425
1426 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1427 if (!ret)
1428 {
1429 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1430 return CMD_WARNING;
1431 }
1432
1433 ret = rtadv_prefix_reset (zebra_if, &rp);
1434 if (!ret)
1435 {
1436 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1437 return CMD_WARNING;
1438 }
1439
1440 return CMD_SUCCESS;
1441}
Chris Caputob60668d2009-05-03 04:40:57 +00001442
1443DEFUN (ipv6_nd_router_preference,
1444 ipv6_nd_router_preference_cmd,
1445 "ipv6 nd router-preference (high|medium|low)",
1446 "Interface IPv6 config commands\n"
1447 "Neighbor discovery\n"
1448 "Default router preference\n"
1449 "High default router preference\n"
1450 "Low default router preference\n"
1451 "Medium default router preference (default)\n")
1452{
1453 struct interface *ifp;
1454 struct zebra_if *zif;
1455 int i = 0;
1456
1457 ifp = (struct interface *) vty->index;
1458 zif = ifp->info;
1459
1460 while (0 != rtadv_pref_strs[i])
1461 {
1462 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1463 {
1464 zif->rtadv.DefaultPreference = i;
1465 return CMD_SUCCESS;
1466 }
1467 i++;
1468 }
1469
1470 return CMD_ERR_NO_MATCH;
1471}
1472
1473DEFUN (no_ipv6_nd_router_preference,
1474 no_ipv6_nd_router_preference_cmd,
1475 "no ipv6 nd router-preference",
1476 NO_STR
1477 "Interface IPv6 config commands\n"
1478 "Neighbor discovery\n"
1479 "Default router preference\n")
1480{
1481 struct interface *ifp;
1482 struct zebra_if *zif;
1483
1484 ifp = (struct interface *) vty->index;
1485 zif = ifp->info;
1486
1487 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1488
1489 return CMD_SUCCESS;
1490}
1491
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001492DEFUN (ipv6_nd_mtu,
1493 ipv6_nd_mtu_cmd,
1494 "ipv6 nd mtu <1-65535>",
1495 "Interface IPv6 config commands\n"
1496 "Neighbor discovery\n"
1497 "Advertised MTU\n"
1498 "MTU in bytes\n")
1499{
1500 struct interface *ifp = (struct interface *) vty->index;
1501 struct zebra_if *zif = ifp->info;
1502 VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
1503 return CMD_SUCCESS;
1504}
1505
1506DEFUN (no_ipv6_nd_mtu,
1507 no_ipv6_nd_mtu_cmd,
1508 "no ipv6 nd mtu",
1509 NO_STR
1510 "Interface IPv6 config commands\n"
1511 "Neighbor discovery\n"
1512 "Advertised MTU\n")
1513{
1514 struct interface *ifp = (struct interface *) vty->index;
1515 struct zebra_if *zif = ifp->info;
1516 zif->rtadv.AdvLinkMTU = 0;
1517 return CMD_SUCCESS;
1518}
1519
1520ALIAS (no_ipv6_nd_mtu,
1521 no_ipv6_nd_mtu_val_cmd,
1522 "no ipv6 nd mtu <1-65535>",
1523 NO_STR
1524 "Interface IPv6 config commands\n"
1525 "Neighbor discovery\n"
1526 "Advertised MTU\n"
1527 "MTU in bytes\n")
1528
paul718e3742002-12-13 20:15:29 +00001529/* Write configuration about router advertisement. */
1530void
1531rtadv_config_write (struct vty *vty, struct interface *ifp)
1532{
1533 struct zebra_if *zif;
hasso52dc7ee2004-09-23 19:18:23 +00001534 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001535 struct rtadv_prefix *rprefix;
1536 u_char buf[INET6_ADDRSTRLEN];
vincent7cee1bb2005-03-25 13:08:53 +00001537 int interval;
paul718e3742002-12-13 20:15:29 +00001538
1539 if (! rtadv)
1540 return;
1541
1542 zif = ifp->info;
1543
1544 if (! if_is_loopback (ifp))
1545 {
1546 if (zif->rtadv.AdvSendAdvertisements)
1547 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1548 else
1549 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1550 }
1551
vincent7cee1bb2005-03-25 13:08:53 +00001552
1553 interval = zif->rtadv.MaxRtrAdvInterval;
1554 if (interval % 1000)
1555 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1556 VTY_NEWLINE);
1557 else
1558 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1559 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
paul718e3742002-12-13 20:15:29 +00001560 VTY_NEWLINE);
1561
Denis Ovsienko6134b872011-12-27 18:49:15 +04001562 if (zif->rtadv.AdvIntervalOption)
1563 vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE);
1564
Denis Ovsienkod660f692011-12-30 21:55:49 +04001565 if (zif->rtadv.AdvDefaultLifetime != -1)
paul718e3742002-12-13 20:15:29 +00001566 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1567 VTY_NEWLINE);
1568
Denis Ovsienko6134b872011-12-27 18:49:15 +04001569 if (zif->rtadv.HomeAgentPreference)
1570 vty_out (vty, " ipv6 nd home-agent-preference %u%s",
1571 zif->rtadv.HomeAgentPreference, VTY_NEWLINE);
1572
Denis Ovsienkod660f692011-12-30 21:55:49 +04001573 if (zif->rtadv.HomeAgentLifetime != -1)
Denis Ovsienko6134b872011-12-27 18:49:15 +04001574 vty_out (vty, " ipv6 nd home-agent-lifetime %u%s",
1575 zif->rtadv.HomeAgentLifetime, VTY_NEWLINE);
1576
1577 if (zif->rtadv.AdvHomeAgentFlag)
1578 vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE);
1579
paul718e3742002-12-13 20:15:29 +00001580 if (zif->rtadv.AdvReachableTime)
1581 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1582 VTY_NEWLINE);
1583
1584 if (zif->rtadv.AdvManagedFlag)
1585 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1586
1587 if (zif->rtadv.AdvOtherConfigFlag)
1588 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1589
Chris Caputob60668d2009-05-03 04:40:57 +00001590 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1591 vty_out (vty, " ipv6 nd router-preference %s%s",
1592 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1593 VTY_NEWLINE);
1594
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001595 if (zif->rtadv.AdvLinkMTU)
1596 vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
1597
paul1eb8ef22005-04-07 07:30:20 +00001598 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +00001599 {
hasso3e31cde2004-05-18 11:58:59 +00001600 vty_out (vty, " ipv6 nd prefix %s/%d",
paul718e3742002-12-13 20:15:29 +00001601 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
hassoc9e52be2004-09-26 16:09:34 +00001602 (char *) buf, INET6_ADDRSTRLEN),
hasso3e31cde2004-05-18 11:58:59 +00001603 rprefix->prefix.prefixlen);
1604 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1605 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1606 {
1607 if (rprefix->AdvValidLifetime == UINT32_MAX)
1608 vty_out (vty, " infinite");
1609 else
1610 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1611 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1612 vty_out (vty, " infinite");
1613 else
1614 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1615 }
1616 if (!rprefix->AdvOnLinkFlag)
1617 vty_out (vty, " off-link");
1618 if (!rprefix->AdvAutonomousFlag)
1619 vty_out (vty, " no-autoconfig");
vincent7cee1bb2005-03-25 13:08:53 +00001620 if (rprefix->AdvRouterAddressFlag)
1621 vty_out (vty, " router-address");
paul718e3742002-12-13 20:15:29 +00001622 vty_out (vty, "%s", VTY_NEWLINE);
1623 }
1624}
1625
paul718e3742002-12-13 20:15:29 +00001626
paula1ac18c2005-06-28 17:17:12 +00001627static void
paul718e3742002-12-13 20:15:29 +00001628rtadv_event (enum rtadv_event event, int val)
1629{
1630 switch (event)
1631 {
1632 case RTADV_START:
1633 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001634 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001635 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001636 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1637 NULL, 0);
paul718e3742002-12-13 20:15:29 +00001638 break;
1639 case RTADV_STOP:
1640 if (rtadv->ra_timer)
1641 {
1642 thread_cancel (rtadv->ra_timer);
1643 rtadv->ra_timer = NULL;
1644 }
1645 if (rtadv->ra_read)
1646 {
1647 thread_cancel (rtadv->ra_read);
1648 rtadv->ra_read = NULL;
1649 }
1650 break;
1651 case RTADV_TIMER:
1652 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001653 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1654 val);
paul718e3742002-12-13 20:15:29 +00001655 break;
vincent7cee1bb2005-03-25 13:08:53 +00001656 case RTADV_TIMER_MSEC:
1657 if (! rtadv->ra_timer)
1658 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1659 NULL, val);
1660 break;
paul718e3742002-12-13 20:15:29 +00001661 case RTADV_READ:
1662 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001663 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001664 break;
1665 default:
1666 break;
1667 }
1668 return;
1669}
1670
1671void
paula1ac18c2005-06-28 17:17:12 +00001672rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001673{
1674 int sock;
1675
1676 sock = rtadv_make_socket ();
1677 if (sock < 0)
1678 return;
1679
1680 rtadv = rtadv_new ();
1681 rtadv->sock = sock;
1682
1683 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1684 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
paul718e3742002-12-13 20:15:29 +00001685 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001686 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
paul718e3742002-12-13 20:15:29 +00001687 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1688 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1689 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1690 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1691 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1692 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1693 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1694 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1695 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001696 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1697 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1698 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1699 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1700 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1701 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1702 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1703 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001704 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001705 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1706 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001707 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1708 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1709 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001710 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001711 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1712 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1713 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1714 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1715 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001716 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001717 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1718 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
Chris Caputob60668d2009-05-03 04:40:57 +00001719 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1720 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001721 install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
1722 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
1723 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
paul718e3742002-12-13 20:15:29 +00001724}
1725
paula1ac18c2005-06-28 17:17:12 +00001726static int
paul718e3742002-12-13 20:15:29 +00001727if_join_all_router (int sock, struct interface *ifp)
1728{
1729 int ret;
1730
1731 struct ipv6_mreq mreq;
1732
1733 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1734 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1735 mreq.ipv6mr_interface = ifp->ifindex;
1736
1737 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1738 (char *) &mreq, sizeof mreq);
1739 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001740 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001741
1742 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1743
1744 return 0;
1745}
1746
paula1ac18c2005-06-28 17:17:12 +00001747static int
paul718e3742002-12-13 20:15:29 +00001748if_leave_all_router (int sock, struct interface *ifp)
1749{
1750 int ret;
1751
1752 struct ipv6_mreq mreq;
1753
1754 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1755 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1756 mreq.ipv6mr_interface = ifp->ifindex;
1757
1758 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1759 (char *) &mreq, sizeof mreq);
1760 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001761 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001762
1763 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1764
1765 return 0;
1766}
1767
1768#else
1769void
paula1ac18c2005-06-28 17:17:12 +00001770rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001771{
1772 /* Empty.*/;
1773}
1774#endif /* RTADV && HAVE_IPV6 */