blob: c6771bbce5220362e37c6ef71945aea17549a9b9 [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 }
Denis Ovsienko6bb12732012-01-08 17:46:34 +04001205 apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
hasso3e31cde2004-05-18 11:58:59 +00001206 rp.AdvOnLinkFlag = 1;
1207 rp.AdvAutonomousFlag = 1;
vincent7cee1bb2005-03-25 13:08:53 +00001208 rp.AdvRouterAddressFlag = 0;
hasso3e31cde2004-05-18 11:58:59 +00001209 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1210 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
paul718e3742002-12-13 20:15:29 +00001211
hasso3e31cde2004-05-18 11:58:59 +00001212 if (argc > 1)
paul718e3742002-12-13 20:15:29 +00001213 {
hasso3e31cde2004-05-18 11:58:59 +00001214 if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
paul718e3742002-12-13 20:15:29 +00001215 {
hasso3e31cde2004-05-18 11:58:59 +00001216 if ( strncmp (argv[1], "i", 1) == 0)
1217 rp.AdvValidLifetime = UINT32_MAX;
1218 else
1219 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1220 (char **)NULL, 10);
1221
1222 if ( strncmp (argv[2], "i", 1) == 0)
1223 rp.AdvPreferredLifetime = UINT32_MAX;
1224 else
1225 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1226 (char **)NULL, 10);
1227
1228 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1229 {
1230 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1231 return CMD_WARNING;
1232 }
1233 cursor = cursor + 2;
paul718e3742002-12-13 20:15:29 +00001234 }
hasso3e31cde2004-05-18 11:58:59 +00001235 if (argc > cursor)
paul718e3742002-12-13 20:15:29 +00001236 {
hasso3e31cde2004-05-18 11:58:59 +00001237 for (i = cursor; i < argc; i++)
1238 {
1239 if (strncmp (argv[i], "of", 2) == 0)
1240 rp.AdvOnLinkFlag = 0;
1241 if (strncmp (argv[i], "no", 2) == 0)
1242 rp.AdvAutonomousFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +00001243 if (strncmp (argv[i], "ro", 2) == 0)
1244 rp.AdvRouterAddressFlag = 1;
hasso3e31cde2004-05-18 11:58:59 +00001245 }
paul718e3742002-12-13 20:15:29 +00001246 }
1247 }
1248
1249 rtadv_prefix_set (zebra_if, &rp);
1250
1251 return CMD_SUCCESS;
1252}
1253
hasso3e31cde2004-05-18 11:58:59 +00001254ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001255 ipv6_nd_prefix_val_nortaddr_cmd,
1256 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1257 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1258 "Interface IPv6 config commands\n"
1259 "Neighbor discovery\n"
1260 "Prefix information\n"
1261 "IPv6 prefix\n"
1262 "Valid lifetime in seconds\n"
1263 "Infinite valid lifetime\n"
1264 "Preferred lifetime in seconds\n"
1265 "Infinite preferred lifetime\n"
1266 "Do not use prefix for onlink determination\n"
1267 "Do not use prefix for autoconfiguration\n")
1268
1269ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001270 ipv6_nd_prefix_val_rev_cmd,
1271 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1272 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1273 "Interface IPv6 config commands\n"
1274 "Neighbor discovery\n"
1275 "Prefix information\n"
1276 "IPv6 prefix\n"
1277 "Valid lifetime in seconds\n"
1278 "Infinite valid lifetime\n"
1279 "Preferred lifetime in seconds\n"
1280 "Infinite preferred lifetime\n"
1281 "Do not use prefix for autoconfiguration\n"
1282 "Do not use prefix for onlink determination\n")
1283
1284ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001285 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1286 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1287 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1288 "Interface IPv6 config commands\n"
1289 "Neighbor discovery\n"
1290 "Prefix information\n"
1291 "IPv6 prefix\n"
1292 "Valid lifetime in seconds\n"
1293 "Infinite valid lifetime\n"
1294 "Preferred lifetime in seconds\n"
1295 "Infinite preferred lifetime\n"
1296 "Do not use prefix for autoconfiguration\n"
1297 "Do not use prefix for onlink determination\n"
1298 "Set Router Address flag\n")
1299
1300ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001301 ipv6_nd_prefix_val_noauto_cmd,
1302 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1303 "(<0-4294967295>|infinite) (no-autoconfig|)",
1304 "Interface IPv6 config commands\n"
1305 "Neighbor discovery\n"
1306 "Prefix information\n"
1307 "IPv6 prefix\n"
1308 "Valid lifetime in seconds\n"
1309 "Infinite valid lifetime\n"
1310 "Preferred lifetime in seconds\n"
1311 "Infinite preferred lifetime\n"
vincent7cee1bb2005-03-25 13:08:53 +00001312 "Do not use prefix for autoconfiguration")
hasso3e31cde2004-05-18 11:58:59 +00001313
1314ALIAS (ipv6_nd_prefix,
1315 ipv6_nd_prefix_val_offlink_cmd,
1316 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1317 "(<0-4294967295>|infinite) (off-link|)",
1318 "Interface IPv6 config commands\n"
1319 "Neighbor discovery\n"
1320 "Prefix information\n"
1321 "IPv6 prefix\n"
1322 "Valid lifetime in seconds\n"
1323 "Infinite valid lifetime\n"
1324 "Preferred lifetime in seconds\n"
1325 "Infinite preferred lifetime\n"
1326 "Do not use prefix for onlink determination\n")
1327
1328ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001329 ipv6_nd_prefix_val_rtaddr_cmd,
1330 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1331 "(<0-4294967295>|infinite) (router-address|)",
1332 "Interface IPv6 config commands\n"
1333 "Neighbor discovery\n"
1334 "Prefix information\n"
1335 "IPv6 prefix\n"
1336 "Valid lifetime in seconds\n"
1337 "Infinite valid lifetime\n"
1338 "Preferred lifetime in seconds\n"
1339 "Infinite preferred lifetime\n"
1340 "Set Router Address flag\n")
1341
1342ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001343 ipv6_nd_prefix_val_cmd,
1344 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1345 "(<0-4294967295>|infinite)",
1346 "Interface IPv6 config commands\n"
1347 "Neighbor discovery\n"
1348 "Prefix information\n"
1349 "IPv6 prefix\n"
1350 "Valid lifetime in seconds\n"
1351 "Infinite valid lifetime\n"
1352 "Preferred lifetime in seconds\n"
1353 "Infinite preferred lifetime\n")
1354
1355ALIAS (ipv6_nd_prefix,
1356 ipv6_nd_prefix_noval_cmd,
1357 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1358 "Interface IPv6 config commands\n"
1359 "Neighbor discovery\n"
1360 "Prefix information\n"
1361 "IPv6 prefix\n"
1362 "Do not use prefix for autoconfiguration\n"
1363 "Do not use prefix for onlink determination\n")
1364
1365ALIAS (ipv6_nd_prefix,
1366 ipv6_nd_prefix_noval_rev_cmd,
1367 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1368 "Interface IPv6 config commands\n"
1369 "Neighbor discovery\n"
1370 "Prefix information\n"
1371 "IPv6 prefix\n"
1372 "Do not use prefix for onlink determination\n"
1373 "Do not use prefix for autoconfiguration\n")
1374
1375ALIAS (ipv6_nd_prefix,
1376 ipv6_nd_prefix_noval_noauto_cmd,
1377 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1378 "Interface IPv6 config commands\n"
1379 "Neighbor discovery\n"
1380 "Prefix information\n"
1381 "IPv6 prefix\n"
1382 "Do not use prefix for autoconfiguration\n")
1383
1384ALIAS (ipv6_nd_prefix,
1385 ipv6_nd_prefix_noval_offlink_cmd,
1386 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1387 "Interface IPv6 config commands\n"
1388 "Neighbor discovery\n"
1389 "Prefix information\n"
1390 "IPv6 prefix\n"
1391 "Do not use prefix for onlink determination\n")
1392
1393ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001394 ipv6_nd_prefix_noval_rtaddr_cmd,
1395 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1396 "Interface IPv6 config commands\n"
1397 "Neighbor discovery\n"
1398 "Prefix information\n"
1399 "IPv6 prefix\n"
1400 "Set Router Address flag\n")
1401
1402ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001403 ipv6_nd_prefix_prefix_cmd,
1404 "ipv6 nd prefix X:X::X:X/M",
1405 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001406 "Neighbor discovery\n"
1407 "Prefix information\n"
1408 "IPv6 prefix\n")
1409
hasso3e31cde2004-05-18 11:58:59 +00001410DEFUN (no_ipv6_nd_prefix,
1411 no_ipv6_nd_prefix_cmd,
1412 "no ipv6 nd prefix IPV6PREFIX",
paul718e3742002-12-13 20:15:29 +00001413 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001414 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001415 "Neighbor discovery\n"
1416 "Prefix information\n"
1417 "IPv6 prefix\n")
1418{
1419 int ret;
1420 struct interface *ifp;
1421 struct zebra_if *zebra_if;
1422 struct rtadv_prefix rp;
1423
1424 ifp = (struct interface *) vty->index;
1425 zebra_if = ifp->info;
1426
1427 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
1428 if (!ret)
1429 {
1430 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1431 return CMD_WARNING;
1432 }
Denis Ovsienko6bb12732012-01-08 17:46:34 +04001433 apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
paul718e3742002-12-13 20:15:29 +00001434
1435 ret = rtadv_prefix_reset (zebra_if, &rp);
1436 if (!ret)
1437 {
1438 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1439 return CMD_WARNING;
1440 }
1441
1442 return CMD_SUCCESS;
1443}
Chris Caputob60668d2009-05-03 04:40:57 +00001444
1445DEFUN (ipv6_nd_router_preference,
1446 ipv6_nd_router_preference_cmd,
1447 "ipv6 nd router-preference (high|medium|low)",
1448 "Interface IPv6 config commands\n"
1449 "Neighbor discovery\n"
1450 "Default router preference\n"
1451 "High default router preference\n"
1452 "Low default router preference\n"
1453 "Medium default router preference (default)\n")
1454{
1455 struct interface *ifp;
1456 struct zebra_if *zif;
1457 int i = 0;
1458
1459 ifp = (struct interface *) vty->index;
1460 zif = ifp->info;
1461
1462 while (0 != rtadv_pref_strs[i])
1463 {
1464 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1465 {
1466 zif->rtadv.DefaultPreference = i;
1467 return CMD_SUCCESS;
1468 }
1469 i++;
1470 }
1471
1472 return CMD_ERR_NO_MATCH;
1473}
1474
1475DEFUN (no_ipv6_nd_router_preference,
1476 no_ipv6_nd_router_preference_cmd,
1477 "no ipv6 nd router-preference",
1478 NO_STR
1479 "Interface IPv6 config commands\n"
1480 "Neighbor discovery\n"
1481 "Default router preference\n")
1482{
1483 struct interface *ifp;
1484 struct zebra_if *zif;
1485
1486 ifp = (struct interface *) vty->index;
1487 zif = ifp->info;
1488
1489 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1490
1491 return CMD_SUCCESS;
1492}
1493
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001494DEFUN (ipv6_nd_mtu,
1495 ipv6_nd_mtu_cmd,
1496 "ipv6 nd mtu <1-65535>",
1497 "Interface IPv6 config commands\n"
1498 "Neighbor discovery\n"
1499 "Advertised MTU\n"
1500 "MTU in bytes\n")
1501{
1502 struct interface *ifp = (struct interface *) vty->index;
1503 struct zebra_if *zif = ifp->info;
1504 VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
1505 return CMD_SUCCESS;
1506}
1507
1508DEFUN (no_ipv6_nd_mtu,
1509 no_ipv6_nd_mtu_cmd,
1510 "no ipv6 nd mtu",
1511 NO_STR
1512 "Interface IPv6 config commands\n"
1513 "Neighbor discovery\n"
1514 "Advertised MTU\n")
1515{
1516 struct interface *ifp = (struct interface *) vty->index;
1517 struct zebra_if *zif = ifp->info;
1518 zif->rtadv.AdvLinkMTU = 0;
1519 return CMD_SUCCESS;
1520}
1521
1522ALIAS (no_ipv6_nd_mtu,
1523 no_ipv6_nd_mtu_val_cmd,
1524 "no ipv6 nd mtu <1-65535>",
1525 NO_STR
1526 "Interface IPv6 config commands\n"
1527 "Neighbor discovery\n"
1528 "Advertised MTU\n"
1529 "MTU in bytes\n")
1530
paul718e3742002-12-13 20:15:29 +00001531/* Write configuration about router advertisement. */
1532void
1533rtadv_config_write (struct vty *vty, struct interface *ifp)
1534{
1535 struct zebra_if *zif;
hasso52dc7ee2004-09-23 19:18:23 +00001536 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001537 struct rtadv_prefix *rprefix;
1538 u_char buf[INET6_ADDRSTRLEN];
vincent7cee1bb2005-03-25 13:08:53 +00001539 int interval;
paul718e3742002-12-13 20:15:29 +00001540
1541 if (! rtadv)
1542 return;
1543
1544 zif = ifp->info;
1545
1546 if (! if_is_loopback (ifp))
1547 {
1548 if (zif->rtadv.AdvSendAdvertisements)
1549 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1550 else
1551 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1552 }
1553
vincent7cee1bb2005-03-25 13:08:53 +00001554
1555 interval = zif->rtadv.MaxRtrAdvInterval;
1556 if (interval % 1000)
1557 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1558 VTY_NEWLINE);
1559 else
1560 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1561 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
paul718e3742002-12-13 20:15:29 +00001562 VTY_NEWLINE);
1563
Denis Ovsienko6134b872011-12-27 18:49:15 +04001564 if (zif->rtadv.AdvIntervalOption)
1565 vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE);
1566
Denis Ovsienkod660f692011-12-30 21:55:49 +04001567 if (zif->rtadv.AdvDefaultLifetime != -1)
paul718e3742002-12-13 20:15:29 +00001568 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1569 VTY_NEWLINE);
1570
Denis Ovsienko6134b872011-12-27 18:49:15 +04001571 if (zif->rtadv.HomeAgentPreference)
1572 vty_out (vty, " ipv6 nd home-agent-preference %u%s",
1573 zif->rtadv.HomeAgentPreference, VTY_NEWLINE);
1574
Denis Ovsienkod660f692011-12-30 21:55:49 +04001575 if (zif->rtadv.HomeAgentLifetime != -1)
Denis Ovsienko6134b872011-12-27 18:49:15 +04001576 vty_out (vty, " ipv6 nd home-agent-lifetime %u%s",
1577 zif->rtadv.HomeAgentLifetime, VTY_NEWLINE);
1578
1579 if (zif->rtadv.AdvHomeAgentFlag)
1580 vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE);
1581
paul718e3742002-12-13 20:15:29 +00001582 if (zif->rtadv.AdvReachableTime)
1583 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1584 VTY_NEWLINE);
1585
1586 if (zif->rtadv.AdvManagedFlag)
1587 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1588
1589 if (zif->rtadv.AdvOtherConfigFlag)
1590 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1591
Chris Caputob60668d2009-05-03 04:40:57 +00001592 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1593 vty_out (vty, " ipv6 nd router-preference %s%s",
1594 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1595 VTY_NEWLINE);
1596
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001597 if (zif->rtadv.AdvLinkMTU)
1598 vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
1599
paul1eb8ef22005-04-07 07:30:20 +00001600 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +00001601 {
hasso3e31cde2004-05-18 11:58:59 +00001602 vty_out (vty, " ipv6 nd prefix %s/%d",
paul718e3742002-12-13 20:15:29 +00001603 inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
hassoc9e52be2004-09-26 16:09:34 +00001604 (char *) buf, INET6_ADDRSTRLEN),
hasso3e31cde2004-05-18 11:58:59 +00001605 rprefix->prefix.prefixlen);
1606 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1607 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1608 {
1609 if (rprefix->AdvValidLifetime == UINT32_MAX)
1610 vty_out (vty, " infinite");
1611 else
1612 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1613 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1614 vty_out (vty, " infinite");
1615 else
1616 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1617 }
1618 if (!rprefix->AdvOnLinkFlag)
1619 vty_out (vty, " off-link");
1620 if (!rprefix->AdvAutonomousFlag)
1621 vty_out (vty, " no-autoconfig");
vincent7cee1bb2005-03-25 13:08:53 +00001622 if (rprefix->AdvRouterAddressFlag)
1623 vty_out (vty, " router-address");
paul718e3742002-12-13 20:15:29 +00001624 vty_out (vty, "%s", VTY_NEWLINE);
1625 }
1626}
1627
paul718e3742002-12-13 20:15:29 +00001628
paula1ac18c2005-06-28 17:17:12 +00001629static void
paul718e3742002-12-13 20:15:29 +00001630rtadv_event (enum rtadv_event event, int val)
1631{
1632 switch (event)
1633 {
1634 case RTADV_START:
1635 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001636 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001637 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001638 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1639 NULL, 0);
paul718e3742002-12-13 20:15:29 +00001640 break;
1641 case RTADV_STOP:
1642 if (rtadv->ra_timer)
1643 {
1644 thread_cancel (rtadv->ra_timer);
1645 rtadv->ra_timer = NULL;
1646 }
1647 if (rtadv->ra_read)
1648 {
1649 thread_cancel (rtadv->ra_read);
1650 rtadv->ra_read = NULL;
1651 }
1652 break;
1653 case RTADV_TIMER:
1654 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001655 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
1656 val);
paul718e3742002-12-13 20:15:29 +00001657 break;
vincent7cee1bb2005-03-25 13:08:53 +00001658 case RTADV_TIMER_MSEC:
1659 if (! rtadv->ra_timer)
1660 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
1661 NULL, val);
1662 break;
paul718e3742002-12-13 20:15:29 +00001663 case RTADV_READ:
1664 if (! rtadv->ra_read)
paulb21b19c2003-06-15 01:28:29 +00001665 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
paul718e3742002-12-13 20:15:29 +00001666 break;
1667 default:
1668 break;
1669 }
1670 return;
1671}
1672
1673void
paula1ac18c2005-06-28 17:17:12 +00001674rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001675{
1676 int sock;
1677
1678 sock = rtadv_make_socket ();
1679 if (sock < 0)
1680 return;
1681
1682 rtadv = rtadv_new ();
1683 rtadv->sock = sock;
1684
1685 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1686 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
paul718e3742002-12-13 20:15:29 +00001687 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001688 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
paul718e3742002-12-13 20:15:29 +00001689 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
1690 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1691 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
1692 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1693 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
1694 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1695 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1696 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1697 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001698 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1699 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1700 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1701 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
1702 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1703 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
1704 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1705 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001706 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001707 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1708 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001709 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1710 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1711 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001712 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001713 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1714 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1715 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1716 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1717 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001718 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001719 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1720 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
Chris Caputob60668d2009-05-03 04:40:57 +00001721 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1722 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001723 install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
1724 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
1725 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
paul718e3742002-12-13 20:15:29 +00001726}
1727
paula1ac18c2005-06-28 17:17:12 +00001728static int
paul718e3742002-12-13 20:15:29 +00001729if_join_all_router (int sock, struct interface *ifp)
1730{
1731 int ret;
1732
1733 struct ipv6_mreq mreq;
1734
1735 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1736 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1737 mreq.ipv6mr_interface = ifp->ifindex;
1738
1739 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1740 (char *) &mreq, sizeof mreq);
1741 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001742 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001743
1744 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1745
1746 return 0;
1747}
1748
paula1ac18c2005-06-28 17:17:12 +00001749static int
paul718e3742002-12-13 20:15:29 +00001750if_leave_all_router (int sock, struct interface *ifp)
1751{
1752 int ret;
1753
1754 struct ipv6_mreq mreq;
1755
1756 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1757 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1758 mreq.ipv6mr_interface = ifp->ifindex;
1759
1760 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1761 (char *) &mreq, sizeof mreq);
1762 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001763 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001764
1765 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1766
1767 return 0;
1768}
1769
1770#else
1771void
paula1ac18c2005-06-28 17:17:12 +00001772rtadv_init (void)
paul718e3742002-12-13 20:15:29 +00001773{
1774 /* Empty.*/;
1775}
1776#endif /* RTADV && HAVE_IPV6 */