blob: 6b49cf622e6808548ef65f4499af1a89606345e4 [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"
Feng Lu49f76092015-05-22 11:40:10 +020034#include "vrf.h"
paul718e3742002-12-13 20:15:29 +000035
36#include "zebra/interface.h"
37#include "zebra/rtadv.h"
38#include "zebra/debug.h"
paul537d8ea2003-08-27 06:45:32 +000039#include "zebra/rib.h"
gdt4b5e1352003-12-03 17:54:34 +000040#include "zebra/zserv.h"
paul718e3742002-12-13 20:15:29 +000041
pauledd7c242003-06-04 13:59:38 +000042extern struct zebra_privs_t zserv_privs;
43
Donald Sharp64257732015-11-20 08:33:30 -050044#if defined (HAVE_IPV6) && defined (HAVE_RTADV)
paul718e3742002-12-13 20:15:29 +000045
hassofa2b17e2004-03-04 17:45:00 +000046#ifdef OPEN_BSD
47#include <netinet/icmp6.h>
48#endif
49
paul718e3742002-12-13 20:15:29 +000050/* If RFC2133 definition is used. */
51#ifndef IPV6_JOIN_GROUP
52#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
53#endif
54#ifndef IPV6_LEAVE_GROUP
55#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
56#endif
57
58#define ALLNODE "ff02::1"
59#define ALLROUTER "ff02::2"
60
paulb21b19c2003-06-15 01:28:29 +000061extern struct zebra_t zebrad;
62
vincent7cee1bb2005-03-25 13:08:53 +000063enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
64 RTADV_TIMER_MSEC, RTADV_READ};
paul718e3742002-12-13 20:15:29 +000065
Feng Lu49f76092015-05-22 11:40:10 +020066static void rtadv_event (struct zebra_vrf *, enum rtadv_event, int);
paul718e3742002-12-13 20:15:29 +000067
paula1ac18c2005-06-28 17:17:12 +000068static int if_join_all_router (int, struct interface *);
69static int if_leave_all_router (int, struct interface *);
David Lamparter6b0655a2014-06-04 06:53:35 +020070
paula1ac18c2005-06-28 17:17:12 +000071static int
paul718e3742002-12-13 20:15:29 +000072rtadv_recv_packet (int sock, u_char *buf, int buflen,
73 struct sockaddr_in6 *from, unsigned int *ifindex,
74 int *hoplimit)
75{
76 int ret;
77 struct msghdr msg;
78 struct iovec iov;
79 struct cmsghdr *cmsgptr;
80 struct in6_addr dst;
81
82 char adata[1024];
83
84 /* Fill in message and iovec. */
85 msg.msg_name = (void *) from;
86 msg.msg_namelen = sizeof (struct sockaddr_in6);
87 msg.msg_iov = &iov;
88 msg.msg_iovlen = 1;
89 msg.msg_control = (void *) adata;
90 msg.msg_controllen = sizeof adata;
91 iov.iov_base = buf;
92 iov.iov_len = buflen;
93
94 /* If recvmsg fail return minus value. */
95 ret = recvmsg (sock, &msg, 0);
96 if (ret < 0)
97 return ret;
98
ajsb99760a2005-01-04 16:24:43 +000099 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
paul718e3742002-12-13 20:15:29 +0000100 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
101 {
102 /* I want interface index which this packet comes from. */
103 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
104 cmsgptr->cmsg_type == IPV6_PKTINFO)
105 {
106 struct in6_pktinfo *ptr;
107
108 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
109 *ifindex = ptr->ipi6_ifindex;
110 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
111 }
112
113 /* Incoming packet's hop limit. */
114 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
115 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
Stephen Hemmingerb0b709a2009-12-08 13:26:14 +0300116 {
117 int *hoptr = (int *) CMSG_DATA (cmsgptr);
118 *hoplimit = *hoptr;
119 }
paul718e3742002-12-13 20:15:29 +0000120 }
121 return ret;
122}
123
124#define RTADV_MSG_SIZE 4096
125
126/* Send router advertisement packet. */
paula1ac18c2005-06-28 17:17:12 +0000127static void
paul718e3742002-12-13 20:15:29 +0000128rtadv_send_packet (int sock, struct interface *ifp)
129{
130 struct msghdr msg;
131 struct iovec iov;
132 struct cmsghdr *cmsgptr;
133 struct in6_pktinfo *pkt;
134 struct sockaddr_in6 addr;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000135#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000136 struct sockaddr_dl *sdl;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000137#endif /* HAVE_STRUCT_SOCKADDR_DL */
gdt57492d52004-08-11 18:06:38 +0000138 static void *adata = NULL;
paul718e3742002-12-13 20:15:29 +0000139 unsigned char buf[RTADV_MSG_SIZE];
140 struct nd_router_advert *rtadv;
141 int ret;
142 int len = 0;
143 struct zebra_if *zif;
paul1eb8ef22005-04-07 07:30:20 +0000144 struct rtadv_prefix *rprefix;
paul718e3742002-12-13 20:15:29 +0000145 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 +0000146 struct listnode *node;
Denis Ovsienkod660f692011-12-30 21:55:49 +0400147 u_int16_t pkt_RouterLifetime;
paul718e3742002-12-13 20:15:29 +0000148
gdt57492d52004-08-11 18:06:38 +0000149 /*
150 * Allocate control message bufffer. This is dynamic because
151 * CMSG_SPACE is not guaranteed not to call a function. Note that
152 * the size will be different on different architectures due to
153 * differing alignment rules.
154 */
155 if (adata == NULL)
156 {
157 /* XXX Free on shutdown. */
158 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
159
160 if (adata == NULL)
161 zlog_err("rtadv_send_packet: can't malloc control data\n");
162 }
163
paul718e3742002-12-13 20:15:29 +0000164 /* Logging of packet. */
165 if (IS_ZEBRA_DEBUG_PACKET)
ajsb6178002004-12-07 21:12:56 +0000166 zlog_debug ("Router advertisement send to %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000167
168 /* Fill in sockaddr_in6. */
169 memset (&addr, 0, sizeof (struct sockaddr_in6));
170 addr.sin6_family = AF_INET6;
171#ifdef SIN6_LEN
172 addr.sin6_len = sizeof (struct sockaddr_in6);
173#endif /* SIN6_LEN */
174 addr.sin6_port = htons (IPPROTO_ICMPV6);
Denis Ovsienkoaca43b62012-01-08 18:27:12 +0400175 IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr);
paul718e3742002-12-13 20:15:29 +0000176
177 /* Fetch interface information. */
178 zif = ifp->info;
179
180 /* Make router advertisement message. */
181 rtadv = (struct nd_router_advert *) buf;
182
183 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
184 rtadv->nd_ra_code = 0;
185 rtadv->nd_ra_cksum = 0;
186
187 rtadv->nd_ra_curhoplimit = 64;
Chris Caputob60668d2009-05-03 04:40:57 +0000188
189 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
190 rtadv->nd_ra_flags_reserved =
191 zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
192 rtadv->nd_ra_flags_reserved <<= 3;
193
paul718e3742002-12-13 20:15:29 +0000194 if (zif->rtadv.AdvManagedFlag)
195 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
196 if (zif->rtadv.AdvOtherConfigFlag)
197 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
vincent7cee1bb2005-03-25 13:08:53 +0000198 if (zif->rtadv.AdvHomeAgentFlag)
199 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
Denis Ovsienkod660f692011-12-30 21:55:49 +0400200 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
201 * AdvDefaultLifetime is by default based on the value of
202 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
203 * field of Router Advertisements. Given that this field is expressed
204 * in seconds, a small MaxRtrAdvInterval value can result in a zero
205 * value for this field. To prevent this, routers SHOULD keep
206 * AdvDefaultLifetime in at least one second, even if the use of
207 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
208 pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ?
209 zif->rtadv.AdvDefaultLifetime :
210 MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
211 rtadv->nd_ra_router_lifetime = htons (pkt_RouterLifetime);
paul718e3742002-12-13 20:15:29 +0000212 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
213 rtadv->nd_ra_retransmit = htonl (0);
214
215 len = sizeof (struct nd_router_advert);
216
Denis Ovsienkod660f692011-12-30 21:55:49 +0400217 /* If both the Home Agent Preference and Home Agent Lifetime are set to
218 * their default values specified above, this option SHOULD NOT be
219 * included in the Router Advertisement messages sent by this home
220 * agent. -- RFC6275, 7.4 */
221 if
222 (
223 zif->rtadv.AdvHomeAgentFlag &&
224 (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1)
225 )
vincent7cee1bb2005-03-25 13:08:53 +0000226 {
227 struct nd_opt_homeagent_info *ndopt_hai =
228 (struct nd_opt_homeagent_info *)(buf + len);
229 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
230 ndopt_hai->nd_opt_hai_len = 1;
231 ndopt_hai->nd_opt_hai_reserved = 0;
232 ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
Denis Ovsienkod660f692011-12-30 21:55:49 +0400233 /* 16-bit unsigned integer. The lifetime associated with the home
234 * agent in units of seconds. The default value is the same as the
235 * Router Lifetime, as specified in the main body of the Router
236 * Advertisement. The maximum value corresponds to 18.2 hours. A
237 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
238 ndopt_hai->nd_opt_hai_lifetime = htons
239 (
240 zif->rtadv.HomeAgentLifetime != -1 ?
241 zif->rtadv.HomeAgentLifetime :
242 MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/
243 );
vincent7cee1bb2005-03-25 13:08:53 +0000244 len += sizeof(struct nd_opt_homeagent_info);
245 }
246
247 if (zif->rtadv.AdvIntervalOption)
248 {
249 struct nd_opt_adv_interval *ndopt_adv =
250 (struct nd_opt_adv_interval *)(buf + len);
251 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
252 ndopt_adv->nd_opt_ai_len = 1;
253 ndopt_adv->nd_opt_ai_reserved = 0;
254 ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
255 len += sizeof(struct nd_opt_adv_interval);
256 }
257
paul718e3742002-12-13 20:15:29 +0000258 /* Fill in prefix. */
paul1eb8ef22005-04-07 07:30:20 +0000259 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +0000260 {
261 struct nd_opt_prefix_info *pinfo;
paul718e3742002-12-13 20:15:29 +0000262
263 pinfo = (struct nd_opt_prefix_info *) (buf + len);
264
265 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
266 pinfo->nd_opt_pi_len = 4;
267 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
268
269 pinfo->nd_opt_pi_flags_reserved = 0;
270 if (rprefix->AdvOnLinkFlag)
271 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
272 if (rprefix->AdvAutonomousFlag)
273 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
vincent7cee1bb2005-03-25 13:08:53 +0000274 if (rprefix->AdvRouterAddressFlag)
275 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
paul718e3742002-12-13 20:15:29 +0000276
277 pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
278 pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
279 pinfo->nd_opt_pi_reserved2 = 0;
280
Denis Ovsienkoaca43b62012-01-08 18:27:12 +0400281 IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix);
paul718e3742002-12-13 20:15:29 +0000282
283#ifdef DEBUG
284 {
285 u_char buf[INET6_ADDRSTRLEN];
286
ajsb6178002004-12-07 21:12:56 +0000287 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
hasso3e31cde2004-05-18 11:58:59 +0000288 buf, INET6_ADDRSTRLEN));
paul718e3742002-12-13 20:15:29 +0000289
290 }
291#endif /* DEBUG */
292
293 len += sizeof (struct nd_opt_prefix_info);
294 }
295
296 /* Hardware address. */
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000297#ifdef HAVE_STRUCT_SOCKADDR_DL
paul718e3742002-12-13 20:15:29 +0000298 sdl = &ifp->sdl;
299 if (sdl != NULL && sdl->sdl_alen != 0)
300 {
301 buf[len++] = ND_OPT_SOURCE_LINKADDR;
David Ward50adf782009-08-31 10:42:06 -0400302
303 /* Option length should be rounded up to next octet if
304 the link address does not end on an octet boundary. */
305 buf[len++] = (sdl->sdl_alen + 9) >> 3;
paul718e3742002-12-13 20:15:29 +0000306
307 memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
308 len += sdl->sdl_alen;
David Ward50adf782009-08-31 10:42:06 -0400309
310 /* Pad option to end on an octet boundary. */
311 memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
312 len += -(sdl->sdl_alen + 2) & 0x7;
paul718e3742002-12-13 20:15:29 +0000313 }
314#else
315 if (ifp->hw_addr_len != 0)
316 {
317 buf[len++] = ND_OPT_SOURCE_LINKADDR;
David Ward50adf782009-08-31 10:42:06 -0400318
319 /* Option length should be rounded up to next octet if
320 the link address does not end on an octet boundary. */
321 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
paul718e3742002-12-13 20:15:29 +0000322
323 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
324 len += ifp->hw_addr_len;
David Ward50adf782009-08-31 10:42:06 -0400325
326 /* Pad option to end on an octet boundary. */
327 memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
328 len += -(ifp->hw_addr_len + 2) & 0x7;
paul718e3742002-12-13 20:15:29 +0000329 }
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000330#endif /* HAVE_STRUCT_SOCKADDR_DL */
paul718e3742002-12-13 20:15:29 +0000331
Denis Ovsienko6ae93c02011-12-27 10:45:36 +0400332 /* MTU */
333 if (zif->rtadv.AdvLinkMTU)
334 {
335 struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len);
336 opt->nd_opt_mtu_type = ND_OPT_MTU;
337 opt->nd_opt_mtu_len = 1;
338 opt->nd_opt_mtu_reserved = 0;
339 opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU);
340 len += sizeof (struct nd_opt_mtu);
341 }
342
paul718e3742002-12-13 20:15:29 +0000343 msg.msg_name = (void *) &addr;
344 msg.msg_namelen = sizeof (struct sockaddr_in6);
345 msg.msg_iov = &iov;
346 msg.msg_iovlen = 1;
347 msg.msg_control = (void *) adata;
gdtf841e022004-08-11 19:20:01 +0000348 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
gdt57492d52004-08-11 18:06:38 +0000349 msg.msg_flags = 0;
paul718e3742002-12-13 20:15:29 +0000350 iov.iov_base = buf;
351 iov.iov_len = len;
352
ajsb99760a2005-01-04 16:24:43 +0000353 cmsgptr = ZCMSG_FIRSTHDR(&msg);
gdt57492d52004-08-11 18:06:38 +0000354 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
paul718e3742002-12-13 20:15:29 +0000355 cmsgptr->cmsg_level = IPPROTO_IPV6;
356 cmsgptr->cmsg_type = IPV6_PKTINFO;
gdt80893812004-08-11 15:58:00 +0000357
paul718e3742002-12-13 20:15:29 +0000358 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
359 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
360 pkt->ipi6_ifindex = ifp->ifindex;
361
362 ret = sendmsg (sock, &msg, 0);
gdt9ccabd12004-01-06 18:23:02 +0000363 if (ret < 0)
364 {
365 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
ajs6099b3b2004-11-20 02:06:59 +0000366 errno, safe_strerror(errno));
gdt9ccabd12004-01-06 18:23:02 +0000367 }
paul718e3742002-12-13 20:15:29 +0000368}
369
paula1ac18c2005-06-28 17:17:12 +0000370static int
paul718e3742002-12-13 20:15:29 +0000371rtadv_timer (struct thread *thread)
372{
Feng Lu49f76092015-05-22 11:40:10 +0200373 struct zebra_vrf *zvrf = THREAD_ARG (thread);
paul1eb8ef22005-04-07 07:30:20 +0000374 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000375 struct interface *ifp;
376 struct zebra_if *zif;
vincent7cee1bb2005-03-25 13:08:53 +0000377 int period;
paul718e3742002-12-13 20:15:29 +0000378
Feng Lu49f76092015-05-22 11:40:10 +0200379 zvrf->rtadv.ra_timer = NULL;
380 if (zvrf->rtadv.adv_msec_if_count == 0)
vincent7cee1bb2005-03-25 13:08:53 +0000381 {
382 period = 1000; /* 1 s */
Feng Lu49f76092015-05-22 11:40:10 +0200383 rtadv_event (zvrf, RTADV_TIMER, 1 /* 1 s */);
vincent7cee1bb2005-03-25 13:08:53 +0000384 }
385 else
386 {
387 period = 10; /* 10 ms */
Feng Lu49f76092015-05-22 11:40:10 +0200388 rtadv_event (zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
vincent7cee1bb2005-03-25 13:08:53 +0000389 }
paul718e3742002-12-13 20:15:29 +0000390
Feng Lu49f76092015-05-22 11:40:10 +0200391 for (ALL_LIST_ELEMENTS (vrf_iflist (zvrf->vrf_id), node, nnode, ifp))
paul718e3742002-12-13 20:15:29 +0000392 {
Denis Ovsienkofb5174a2011-12-27 10:18:47 +0400393 if (if_is_loopback (ifp) || ! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000394 continue;
395
396 zif = ifp->info;
397
398 if (zif->rtadv.AdvSendAdvertisements)
vincent7cee1bb2005-03-25 13:08:53 +0000399 {
400 zif->rtadv.AdvIntervalTimer -= period;
401 if (zif->rtadv.AdvIntervalTimer <= 0)
402 {
Denis Ovsienkod660f692011-12-30 21:55:49 +0400403 /* FIXME: using MaxRtrAdvInterval each time isn't what section
404 6.2.4 of RFC4861 tells to do. */
vincent7cee1bb2005-03-25 13:08:53 +0000405 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
Feng Lu49f76092015-05-22 11:40:10 +0200406 rtadv_send_packet (zvrf->rtadv.sock, ifp);
vincent7cee1bb2005-03-25 13:08:53 +0000407 }
408 }
paul718e3742002-12-13 20:15:29 +0000409 }
410 return 0;
411}
412
paula1ac18c2005-06-28 17:17:12 +0000413static void
paul718e3742002-12-13 20:15:29 +0000414rtadv_process_solicit (struct interface *ifp)
415{
Feng Lu49f76092015-05-22 11:40:10 +0200416 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000417
Feng Lu49f76092015-05-22 11:40:10 +0200418 zlog_info ("Router solicitation received on %s vrf %u", ifp->name, zvrf->vrf_id);
419
420 rtadv_send_packet (zvrf->rtadv.sock, ifp);
paul718e3742002-12-13 20:15:29 +0000421}
422
paula1ac18c2005-06-28 17:17:12 +0000423static void
424rtadv_process_advert (void)
paul718e3742002-12-13 20:15:29 +0000425{
426 zlog_info ("Router advertisement received");
427}
428
paula1ac18c2005-06-28 17:17:12 +0000429static void
Feng Lu49f76092015-05-22 11:40:10 +0200430rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex,
431 int hoplimit, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000432{
433 struct icmp6_hdr *icmph;
434 struct interface *ifp;
435 struct zebra_if *zif;
436
437 /* Interface search. */
Feng Lu49f76092015-05-22 11:40:10 +0200438 ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
paul718e3742002-12-13 20:15:29 +0000439 if (ifp == NULL)
440 {
Feng Lu49f76092015-05-22 11:40:10 +0200441 zlog_warn ("Unknown interface index: %d, vrf %u", ifindex, vrf_id);
paul718e3742002-12-13 20:15:29 +0000442 return;
443 }
444
445 if (if_is_loopback (ifp))
446 return;
447
448 /* Check interface configuration. */
449 zif = ifp->info;
450 if (! zif->rtadv.AdvSendAdvertisements)
451 return;
452
453 /* ICMP message length check. */
454 if (len < sizeof (struct icmp6_hdr))
455 {
456 zlog_warn ("Invalid ICMPV6 packet length: %d", len);
457 return;
458 }
459
460 icmph = (struct icmp6_hdr *) buf;
461
462 /* ICMP message type check. */
463 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
464 icmph->icmp6_type != ND_ROUTER_ADVERT)
465 {
466 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
467 return;
468 }
469
470 /* Hoplimit check. */
471 if (hoplimit >= 0 && hoplimit != 255)
472 {
473 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
474 hoplimit);
475 return;
476 }
477
478 /* Check ICMP message type. */
479 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
480 rtadv_process_solicit (ifp);
481 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
482 rtadv_process_advert ();
483
484 return;
485}
486
paula1ac18c2005-06-28 17:17:12 +0000487static int
paul718e3742002-12-13 20:15:29 +0000488rtadv_read (struct thread *thread)
489{
490 int sock;
491 int len;
492 u_char buf[RTADV_MSG_SIZE];
493 struct sockaddr_in6 from;
Stephen Hemmingerb0b709a2009-12-08 13:26:14 +0300494 unsigned int ifindex = 0;
paul718e3742002-12-13 20:15:29 +0000495 int hoplimit = -1;
Feng Lu49f76092015-05-22 11:40:10 +0200496 struct zebra_vrf *zvrf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000497
498 sock = THREAD_FD (thread);
Feng Lu49f76092015-05-22 11:40:10 +0200499 zvrf->rtadv.ra_read = NULL;
paul718e3742002-12-13 20:15:29 +0000500
501 /* Register myself. */
Feng Lu49f76092015-05-22 11:40:10 +0200502 rtadv_event (zvrf, RTADV_READ, sock);
paul718e3742002-12-13 20:15:29 +0000503
504 len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
505
506 if (len < 0)
507 {
ajs6099b3b2004-11-20 02:06:59 +0000508 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000509 return len;
510 }
511
Feng Lu49f76092015-05-22 11:40:10 +0200512 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, zvrf->vrf_id);
paul718e3742002-12-13 20:15:29 +0000513
514 return 0;
515}
516
paula1ac18c2005-06-28 17:17:12 +0000517static int
Feng Lu49f76092015-05-22 11:40:10 +0200518rtadv_make_socket (vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000519{
520 int sock;
521 int ret;
522 struct icmp6_filter filter;
523
pauledd7c242003-06-04 13:59:38 +0000524 if ( zserv_privs.change (ZPRIVS_RAISE) )
525 zlog_err ("rtadv_make_socket: could not raise privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000526 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000527
Feng Lu49f76092015-05-22 11:40:10 +0200528 sock = vrf_socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, vrf_id);
paul718e3742002-12-13 20:15:29 +0000529
pauledd7c242003-06-04 13:59:38 +0000530 if ( zserv_privs.change (ZPRIVS_LOWER) )
531 zlog_err ("rtadv_make_socket: could not lower privs, %s",
ajs6099b3b2004-11-20 02:06:59 +0000532 safe_strerror (errno) );
pauledd7c242003-06-04 13:59:38 +0000533
paul718e3742002-12-13 20:15:29 +0000534 /* When we can't make ICMPV6 socket simply back. Router
535 advertisement feature will not be supported. */
536 if (sock < 0)
Morgan Stewart26b663d2015-09-16 13:17:54 -0400537 {
538 close (sock);
539 return -1;
540 }
paul718e3742002-12-13 20:15:29 +0000541
542 ret = setsockopt_ipv6_pktinfo (sock, 1);
543 if (ret < 0)
Morgan Stewart26b663d2015-09-16 13:17:54 -0400544 {
545 close (sock);
546 return ret;
547 }
paul718e3742002-12-13 20:15:29 +0000548 ret = setsockopt_ipv6_multicast_loop (sock, 0);
549 if (ret < 0)
Morgan Stewart26b663d2015-09-16 13:17:54 -0400550 {
551 close (sock);
552 return ret;
553 }
paul718e3742002-12-13 20:15:29 +0000554 ret = setsockopt_ipv6_unicast_hops (sock, 255);
555 if (ret < 0)
Morgan Stewart26b663d2015-09-16 13:17:54 -0400556 {
557 close (sock);
558 return ret;
559 }
paul718e3742002-12-13 20:15:29 +0000560 ret = setsockopt_ipv6_multicast_hops (sock, 255);
561 if (ret < 0)
Morgan Stewart26b663d2015-09-16 13:17:54 -0400562 {
563 close (sock);
564 return ret;
565 }
paul718e3742002-12-13 20:15:29 +0000566 ret = setsockopt_ipv6_hoplimit (sock, 1);
567 if (ret < 0)
Morgan Stewart26b663d2015-09-16 13:17:54 -0400568 {
569 close (sock);
570 return ret;
571 }
paul718e3742002-12-13 20:15:29 +0000572
573 ICMP6_FILTER_SETBLOCKALL(&filter);
574 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
575 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
576
577 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
578 sizeof (struct icmp6_filter));
579 if (ret < 0)
580 {
ajs6099b3b2004-11-20 02:06:59 +0000581 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000582 return ret;
583 }
584
585 return sock;
586}
David Lamparter6b0655a2014-06-04 06:53:35 +0200587
paula1ac18c2005-06-28 17:17:12 +0000588static struct rtadv_prefix *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800589rtadv_prefix_new (void)
paul718e3742002-12-13 20:15:29 +0000590{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700591 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
paul718e3742002-12-13 20:15:29 +0000592}
593
paula1ac18c2005-06-28 17:17:12 +0000594static void
paul718e3742002-12-13 20:15:29 +0000595rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
596{
597 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
598}
599
paula1ac18c2005-06-28 17:17:12 +0000600static struct rtadv_prefix *
Denis Ovsienkoaca43b62012-01-08 18:27:12 +0400601rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p)
paul718e3742002-12-13 20:15:29 +0000602{
hasso52dc7ee2004-09-23 19:18:23 +0000603 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000604 struct rtadv_prefix *rprefix;
605
paul1eb8ef22005-04-07 07:30:20 +0000606 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
Denis Ovsienkoaca43b62012-01-08 18:27:12 +0400607 if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p))
paul1eb8ef22005-04-07 07:30:20 +0000608 return rprefix;
paul718e3742002-12-13 20:15:29 +0000609 return NULL;
610}
611
paula1ac18c2005-06-28 17:17:12 +0000612static struct rtadv_prefix *
Denis Ovsienkoaca43b62012-01-08 18:27:12 +0400613rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p)
paul718e3742002-12-13 20:15:29 +0000614{
615 struct rtadv_prefix *rprefix;
616
617 rprefix = rtadv_prefix_lookup (rplist, p);
618 if (rprefix)
619 return rprefix;
620
621 rprefix = rtadv_prefix_new ();
Denis Ovsienkoaca43b62012-01-08 18:27:12 +0400622 memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6));
paul718e3742002-12-13 20:15:29 +0000623 listnode_add (rplist, rprefix);
624
625 return rprefix;
626}
627
paula1ac18c2005-06-28 17:17:12 +0000628static void
paul718e3742002-12-13 20:15:29 +0000629rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
630{
631 struct rtadv_prefix *rprefix;
632
633 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
634
635 /* Set parameters. */
636 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
637 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
638 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
639 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
vincent7cee1bb2005-03-25 13:08:53 +0000640 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
paul718e3742002-12-13 20:15:29 +0000641}
642
paula1ac18c2005-06-28 17:17:12 +0000643static int
paul718e3742002-12-13 20:15:29 +0000644rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
645{
646 struct rtadv_prefix *rprefix;
647
648 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
649 if (rprefix != NULL)
650 {
651 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
652 rtadv_prefix_free (rprefix);
653 return 1;
654 }
655 else
656 return 0;
657}
658
659DEFUN (ipv6_nd_suppress_ra,
660 ipv6_nd_suppress_ra_cmd,
661 "ipv6 nd suppress-ra",
hasso3e31cde2004-05-18 11:58:59 +0000662 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000663 "Neighbor discovery\n"
664 "Suppress Router Advertisement\n")
665{
666 struct interface *ifp;
667 struct zebra_if *zif;
Feng Lu49f76092015-05-22 11:40:10 +0200668 struct zebra_vrf *zvrf;
paul718e3742002-12-13 20:15:29 +0000669
670 ifp = vty->index;
671 zif = ifp->info;
Feng Lu49f76092015-05-22 11:40:10 +0200672 zvrf = vrf_info_lookup (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000673
674 if (if_is_loopback (ifp))
675 {
676 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
677 return CMD_WARNING;
678 }
679
680 if (zif->rtadv.AdvSendAdvertisements)
681 {
682 zif->rtadv.AdvSendAdvertisements = 0;
683 zif->rtadv.AdvIntervalTimer = 0;
Feng Lu49f76092015-05-22 11:40:10 +0200684 zvrf->rtadv.adv_if_count--;
paul718e3742002-12-13 20:15:29 +0000685
Feng Lu49f76092015-05-22 11:40:10 +0200686 if_leave_all_router (zvrf->rtadv.sock, ifp);
paul718e3742002-12-13 20:15:29 +0000687
Feng Lu49f76092015-05-22 11:40:10 +0200688 if (zvrf->rtadv.adv_if_count == 0)
689 rtadv_event (zvrf, RTADV_STOP, 0);
paul718e3742002-12-13 20:15:29 +0000690 }
691
692 return CMD_SUCCESS;
693}
694
paul718e3742002-12-13 20:15:29 +0000695DEFUN (no_ipv6_nd_suppress_ra,
696 no_ipv6_nd_suppress_ra_cmd,
697 "no ipv6 nd suppress-ra",
698 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000699 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000700 "Neighbor discovery\n"
701 "Suppress Router Advertisement\n")
702{
703 struct interface *ifp;
704 struct zebra_if *zif;
Feng Lu49f76092015-05-22 11:40:10 +0200705 struct zebra_vrf *zvrf;
paul718e3742002-12-13 20:15:29 +0000706
707 ifp = vty->index;
708 zif = ifp->info;
Feng Lu49f76092015-05-22 11:40:10 +0200709 zvrf = vrf_info_lookup (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000710
711 if (if_is_loopback (ifp))
712 {
713 vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
714 return CMD_WARNING;
715 }
716
717 if (! zif->rtadv.AdvSendAdvertisements)
718 {
719 zif->rtadv.AdvSendAdvertisements = 1;
720 zif->rtadv.AdvIntervalTimer = 0;
Feng Lu49f76092015-05-22 11:40:10 +0200721 zvrf->rtadv.adv_if_count++;
paul718e3742002-12-13 20:15:29 +0000722
Feng Lu49f76092015-05-22 11:40:10 +0200723 if_join_all_router (zvrf->rtadv.sock, ifp);
paul718e3742002-12-13 20:15:29 +0000724
Feng Lu49f76092015-05-22 11:40:10 +0200725 if (zvrf->rtadv.adv_if_count == 1)
726 rtadv_event (zvrf, RTADV_START, zvrf->rtadv.sock);
paul718e3742002-12-13 20:15:29 +0000727 }
728
729 return CMD_SUCCESS;
730}
731
vincent7cee1bb2005-03-25 13:08:53 +0000732DEFUN (ipv6_nd_ra_interval_msec,
733 ipv6_nd_ra_interval_msec_cmd,
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400734 "ipv6 nd ra-interval msec <70-1800000>",
vincent7cee1bb2005-03-25 13:08:53 +0000735 "Interface IPv6 config commands\n"
736 "Neighbor discovery\n"
737 "Router Advertisement interval\n"
738 "Router Advertisement interval in milliseconds\n")
739{
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400740 unsigned interval;
741 struct interface *ifp = (struct interface *) vty->index;
742 struct zebra_if *zif = ifp->info;
Feng Lu49f76092015-05-22 11:40:10 +0200743 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
vincent7cee1bb2005-03-25 13:08:53 +0000744
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400745 VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
746 if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000))
747 {
748 vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
749 return CMD_WARNING;
750 }
vincent7cee1bb2005-03-25 13:08:53 +0000751
752 if (zif->rtadv.MaxRtrAdvInterval % 1000)
Feng Lu49f76092015-05-22 11:40:10 +0200753 zvrf->rtadv.adv_msec_if_count--;
vincent7cee1bb2005-03-25 13:08:53 +0000754
755 if (interval % 1000)
Feng Lu49f76092015-05-22 11:40:10 +0200756 zvrf->rtadv.adv_msec_if_count++;
vincent7cee1bb2005-03-25 13:08:53 +0000757
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,
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400767 "ipv6 nd ra-interval <1-1800>",
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{
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400773 unsigned interval;
774 struct interface *ifp = (struct interface *) vty->index;
775 struct zebra_if *zif = ifp->info;
Feng Lu49f76092015-05-22 11:40:10 +0200776 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000777
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400778 VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
779 if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime))
780 {
781 vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
782 return CMD_WARNING;
783 }
paul718e3742002-12-13 20:15:29 +0000784
vincent7cee1bb2005-03-25 13:08:53 +0000785 if (zif->rtadv.MaxRtrAdvInterval % 1000)
Feng Lu49f76092015-05-22 11:40:10 +0200786 zvrf->rtadv.adv_msec_if_count--;
vincent7cee1bb2005-03-25 13:08:53 +0000787
788 /* convert to milliseconds */
789 interval = interval * 1000;
790
paul718e3742002-12-13 20:15:29 +0000791 zif->rtadv.MaxRtrAdvInterval = interval;
792 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
793 zif->rtadv.AdvIntervalTimer = 0;
794
795 return CMD_SUCCESS;
796}
797
798DEFUN (no_ipv6_nd_ra_interval,
799 no_ipv6_nd_ra_interval_cmd,
800 "no ipv6 nd ra-interval",
801 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000802 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000803 "Neighbor discovery\n"
804 "Router Advertisement interval\n")
805{
806 struct interface *ifp;
807 struct zebra_if *zif;
Feng Lu49f76092015-05-22 11:40:10 +0200808 struct zebra_vrf *zvrf;
paul718e3742002-12-13 20:15:29 +0000809
810 ifp = (struct interface *) vty->index;
811 zif = ifp->info;
Feng Lu49f76092015-05-22 11:40:10 +0200812 zvrf = vrf_info_lookup (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000813
vincent7cee1bb2005-03-25 13:08:53 +0000814 if (zif->rtadv.MaxRtrAdvInterval % 1000)
Feng Lu49f76092015-05-22 11:40:10 +0200815 zvrf->rtadv.adv_msec_if_count--;
vincent7cee1bb2005-03-25 13:08:53 +0000816
paul718e3742002-12-13 20:15:29 +0000817 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
818 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
819 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
820
821 return CMD_SUCCESS;
822}
823
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400824ALIAS (no_ipv6_nd_ra_interval,
825 no_ipv6_nd_ra_interval_val_cmd,
826 "no ipv6 nd ra-interval <1-1800>",
827 NO_STR
828 "Interface IPv6 config commands\n"
829 "Neighbor discovery\n"
830 "Router Advertisement interval\n")
831
832ALIAS (no_ipv6_nd_ra_interval,
833 no_ipv6_nd_ra_interval_msec_val_cmd,
834 "no ipv6 nd ra-interval msec <1-1800000>",
835 NO_STR
836 "Interface IPv6 config commands\n"
837 "Neighbor discovery\n"
838 "Router Advertisement interval\n"
839 "Router Advertisement interval in milliseconds\n")
840
paul718e3742002-12-13 20:15:29 +0000841DEFUN (ipv6_nd_ra_lifetime,
842 ipv6_nd_ra_lifetime_cmd,
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400843 "ipv6 nd ra-lifetime <0-9000>",
hasso3e31cde2004-05-18 11:58:59 +0000844 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000845 "Neighbor discovery\n"
846 "Router lifetime\n"
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400847 "Router lifetime in seconds (0 stands for a non-default gw)\n")
paul718e3742002-12-13 20:15:29 +0000848{
849 int lifetime;
850 struct interface *ifp;
851 struct zebra_if *zif;
852
853 ifp = (struct interface *) vty->index;
854 zif = ifp->info;
855
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400856 VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[0], 0, 9000);
paul718e3742002-12-13 20:15:29 +0000857
Denis Ovsienkod660f692011-12-30 21:55:49 +0400858 /* The value to be placed in the Router Lifetime field
859 * of Router Advertisements sent from the interface,
860 * in seconds. MUST be either zero or between
861 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400862 if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval))
paul718e3742002-12-13 20:15:29 +0000863 {
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400864 vty_out (vty, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000865 return CMD_WARNING;
866 }
867
868 zif->rtadv.AdvDefaultLifetime = lifetime;
869
870 return CMD_SUCCESS;
871}
872
873DEFUN (no_ipv6_nd_ra_lifetime,
874 no_ipv6_nd_ra_lifetime_cmd,
875 "no ipv6 nd ra-lifetime",
876 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000877 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000878 "Neighbor discovery\n"
879 "Router lifetime\n")
880{
881 struct interface *ifp;
882 struct zebra_if *zif;
883
884 ifp = (struct interface *) vty->index;
885 zif = ifp->info;
886
Denis Ovsienkod660f692011-12-30 21:55:49 +0400887 zif->rtadv.AdvDefaultLifetime = -1;
paul718e3742002-12-13 20:15:29 +0000888
889 return CMD_SUCCESS;
890}
891
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400892ALIAS (no_ipv6_nd_ra_lifetime,
893 no_ipv6_nd_ra_lifetime_val_cmd,
894 "no ipv6 nd ra-lifetime <0-9000>",
895 NO_STR
896 "Interface IPv6 config commands\n"
897 "Neighbor discovery\n"
898 "Router lifetime\n"
899 "Router lifetime in seconds (0 stands for a non-default gw)\n")
900
paul718e3742002-12-13 20:15:29 +0000901DEFUN (ipv6_nd_reachable_time,
902 ipv6_nd_reachable_time_cmd,
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400903 "ipv6 nd reachable-time <1-3600000>",
hasso3e31cde2004-05-18 11:58:59 +0000904 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000905 "Neighbor discovery\n"
906 "Reachable time\n"
907 "Reachable time in milliseconds\n")
908{
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400909 struct interface *ifp = (struct interface *) vty->index;
910 struct zebra_if *zif = ifp->info;
911 VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[0], 1, RTADV_MAX_REACHABLE_TIME);
paul718e3742002-12-13 20:15:29 +0000912 return CMD_SUCCESS;
913}
914
915DEFUN (no_ipv6_nd_reachable_time,
916 no_ipv6_nd_reachable_time_cmd,
917 "no ipv6 nd reachable-time",
918 NO_STR
hasso3e31cde2004-05-18 11:58:59 +0000919 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +0000920 "Neighbor discovery\n"
921 "Reachable time\n")
922{
923 struct interface *ifp;
924 struct zebra_if *zif;
925
926 ifp = (struct interface *) vty->index;
927 zif = ifp->info;
928
929 zif->rtadv.AdvReachableTime = 0;
930
931 return CMD_SUCCESS;
932}
933
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400934ALIAS (no_ipv6_nd_reachable_time,
935 no_ipv6_nd_reachable_time_val_cmd,
936 "no ipv6 nd reachable-time <1-3600000>",
937 NO_STR
938 "Interface IPv6 config commands\n"
939 "Neighbor discovery\n"
940 "Reachable time\n"
941 "Reachable time in milliseconds\n")
942
vincent7cee1bb2005-03-25 13:08:53 +0000943DEFUN (ipv6_nd_homeagent_preference,
944 ipv6_nd_homeagent_preference_cmd,
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400945 "ipv6 nd home-agent-preference <0-65535>",
vincent7cee1bb2005-03-25 13:08:53 +0000946 "Interface IPv6 config commands\n"
947 "Neighbor discovery\n"
948 "Home Agent preference\n"
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400949 "preference value (default is 0, least preferred)\n")
vincent7cee1bb2005-03-25 13:08:53 +0000950{
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400951 struct interface *ifp = (struct interface *) vty->index;
952 struct zebra_if *zif = ifp->info;
953 VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[0], 0, 65535);
vincent7cee1bb2005-03-25 13:08:53 +0000954 return CMD_SUCCESS;
955}
956
957DEFUN (no_ipv6_nd_homeagent_preference,
958 no_ipv6_nd_homeagent_preference_cmd,
959 "no ipv6 nd home-agent-preference",
960 NO_STR
961 "Interface IPv6 config commands\n"
962 "Neighbor discovery\n"
963 "Home Agent preference\n")
964{
965 struct interface *ifp;
966 struct zebra_if *zif;
967
968 ifp = (struct interface *) vty->index;
969 zif = ifp->info;
970
971 zif->rtadv.HomeAgentPreference = 0;
972
973 return CMD_SUCCESS;
974}
975
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400976ALIAS (no_ipv6_nd_homeagent_preference,
977 no_ipv6_nd_homeagent_preference_val_cmd,
978 "no ipv6 nd home-agent-preference <0-65535>",
979 NO_STR
980 "Interface IPv6 config commands\n"
981 "Neighbor discovery\n"
982 "Home Agent preference\n"
983 "preference value (default is 0, least preferred)\n")
984
vincent7cee1bb2005-03-25 13:08:53 +0000985DEFUN (ipv6_nd_homeagent_lifetime,
986 ipv6_nd_homeagent_lifetime_cmd,
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400987 "ipv6 nd home-agent-lifetime <0-65520>",
vincent7cee1bb2005-03-25 13:08:53 +0000988 "Interface IPv6 config commands\n"
989 "Neighbor discovery\n"
990 "Home Agent lifetime\n"
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400991 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
vincent7cee1bb2005-03-25 13:08:53 +0000992{
Denis Ovsienko4afa50b2012-01-24 12:39:58 +0400993 struct interface *ifp = (struct interface *) vty->index;
994 struct zebra_if *zif = ifp->info;
995 VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[0], 0, RTADV_MAX_HALIFETIME);
vincent7cee1bb2005-03-25 13:08:53 +0000996 return CMD_SUCCESS;
997}
998
999DEFUN (no_ipv6_nd_homeagent_lifetime,
1000 no_ipv6_nd_homeagent_lifetime_cmd,
1001 "no ipv6 nd home-agent-lifetime",
1002 NO_STR
1003 "Interface IPv6 config commands\n"
1004 "Neighbor discovery\n"
1005 "Home Agent lifetime\n")
1006{
1007 struct interface *ifp;
1008 struct zebra_if *zif;
1009
1010 ifp = (struct interface *) vty->index;
1011 zif = ifp->info;
1012
Denis Ovsienkod660f692011-12-30 21:55:49 +04001013 zif->rtadv.HomeAgentLifetime = -1;
vincent7cee1bb2005-03-25 13:08:53 +00001014
1015 return CMD_SUCCESS;
1016}
1017
Denis Ovsienko4afa50b2012-01-24 12:39:58 +04001018ALIAS (no_ipv6_nd_homeagent_lifetime,
1019 no_ipv6_nd_homeagent_lifetime_val_cmd,
1020 "no ipv6 nd home-agent-lifetime <0-65520>",
1021 NO_STR
1022 "Interface IPv6 config commands\n"
1023 "Neighbor discovery\n"
1024 "Home Agent lifetime\n"
1025 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1026
paul718e3742002-12-13 20:15:29 +00001027DEFUN (ipv6_nd_managed_config_flag,
1028 ipv6_nd_managed_config_flag_cmd,
1029 "ipv6 nd managed-config-flag",
hasso3e31cde2004-05-18 11:58:59 +00001030 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001031 "Neighbor discovery\n"
1032 "Managed address configuration flag\n")
1033{
1034 struct interface *ifp;
1035 struct zebra_if *zif;
1036
1037 ifp = (struct interface *) vty->index;
1038 zif = ifp->info;
1039
1040 zif->rtadv.AdvManagedFlag = 1;
1041
1042 return CMD_SUCCESS;
1043}
1044
1045DEFUN (no_ipv6_nd_managed_config_flag,
1046 no_ipv6_nd_managed_config_flag_cmd,
1047 "no ipv6 nd managed-config-flag",
1048 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001049 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001050 "Neighbor discovery\n"
1051 "Managed address configuration flag\n")
1052{
1053 struct interface *ifp;
1054 struct zebra_if *zif;
1055
1056 ifp = (struct interface *) vty->index;
1057 zif = ifp->info;
1058
1059 zif->rtadv.AdvManagedFlag = 0;
1060
1061 return CMD_SUCCESS;
1062}
1063
vincent7cee1bb2005-03-25 13:08:53 +00001064DEFUN (ipv6_nd_homeagent_config_flag,
1065 ipv6_nd_homeagent_config_flag_cmd,
1066 "ipv6 nd home-agent-config-flag",
1067 "Interface IPv6 config commands\n"
1068 "Neighbor discovery\n"
1069 "Home Agent configuration flag\n")
1070{
1071 struct interface *ifp;
1072 struct zebra_if *zif;
1073
1074 ifp = (struct interface *) vty->index;
1075 zif = ifp->info;
1076
1077 zif->rtadv.AdvHomeAgentFlag = 1;
1078
1079 return CMD_SUCCESS;
1080}
1081
1082DEFUN (no_ipv6_nd_homeagent_config_flag,
1083 no_ipv6_nd_homeagent_config_flag_cmd,
1084 "no ipv6 nd home-agent-config-flag",
1085 NO_STR
1086 "Interface IPv6 config commands\n"
1087 "Neighbor discovery\n"
1088 "Home Agent configuration flag\n")
1089{
1090 struct interface *ifp;
1091 struct zebra_if *zif;
1092
1093 ifp = (struct interface *) vty->index;
1094 zif = ifp->info;
1095
1096 zif->rtadv.AdvHomeAgentFlag = 0;
1097
1098 return CMD_SUCCESS;
1099}
1100
1101DEFUN (ipv6_nd_adv_interval_config_option,
1102 ipv6_nd_adv_interval_config_option_cmd,
1103 "ipv6 nd adv-interval-option",
1104 "Interface IPv6 config commands\n"
1105 "Neighbor discovery\n"
1106 "Advertisement Interval Option\n")
1107{
1108 struct interface *ifp;
1109 struct zebra_if *zif;
1110
1111 ifp = (struct interface *) vty->index;
1112 zif = ifp->info;
1113
1114 zif->rtadv.AdvIntervalOption = 1;
1115
1116 return CMD_SUCCESS;
1117}
1118
1119DEFUN (no_ipv6_nd_adv_interval_config_option,
1120 no_ipv6_nd_adv_interval_config_option_cmd,
1121 "no ipv6 nd adv-interval-option",
1122 NO_STR
1123 "Interface IPv6 config commands\n"
1124 "Neighbor discovery\n"
1125 "Advertisement Interval Option\n")
1126{
1127 struct interface *ifp;
1128 struct zebra_if *zif;
1129
1130 ifp = (struct interface *) vty->index;
1131 zif = ifp->info;
1132
1133 zif->rtadv.AdvIntervalOption = 0;
1134
1135 return CMD_SUCCESS;
1136}
1137
paul718e3742002-12-13 20:15:29 +00001138DEFUN (ipv6_nd_other_config_flag,
1139 ipv6_nd_other_config_flag_cmd,
1140 "ipv6 nd other-config-flag",
hasso3e31cde2004-05-18 11:58:59 +00001141 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001142 "Neighbor discovery\n"
1143 "Other statefull configuration flag\n")
1144{
1145 struct interface *ifp;
1146 struct zebra_if *zif;
1147
1148 ifp = (struct interface *) vty->index;
1149 zif = ifp->info;
1150
1151 zif->rtadv.AdvOtherConfigFlag = 1;
1152
1153 return CMD_SUCCESS;
1154}
1155
1156DEFUN (no_ipv6_nd_other_config_flag,
1157 no_ipv6_nd_other_config_flag_cmd,
1158 "no ipv6 nd other-config-flag",
1159 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001160 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001161 "Neighbor discovery\n"
1162 "Other statefull configuration flag\n")
1163{
1164 struct interface *ifp;
1165 struct zebra_if *zif;
1166
1167 ifp = (struct interface *) vty->index;
1168 zif = ifp->info;
1169
1170 zif->rtadv.AdvOtherConfigFlag = 0;
1171
1172 return CMD_SUCCESS;
1173}
1174
hasso3e31cde2004-05-18 11:58:59 +00001175DEFUN (ipv6_nd_prefix,
1176 ipv6_nd_prefix_cmd,
1177 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
vincent7cee1bb2005-03-25 13:08:53 +00001178 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
hasso3e31cde2004-05-18 11:58:59 +00001179 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001180 "Neighbor discovery\n"
1181 "Prefix information\n"
1182 "IPv6 prefix\n"
1183 "Valid lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001184 "Infinite valid lifetime\n"
paul718e3742002-12-13 20:15:29 +00001185 "Preferred lifetime in seconds\n"
hasso3e31cde2004-05-18 11:58:59 +00001186 "Infinite preferred lifetime\n"
1187 "Do not use prefix for onlink determination\n"
vincent7cee1bb2005-03-25 13:08:53 +00001188 "Do not use prefix for autoconfiguration\n"
1189 "Set Router Address flag\n")
paul718e3742002-12-13 20:15:29 +00001190{
1191 int i;
1192 int ret;
hasso3e31cde2004-05-18 11:58:59 +00001193 int cursor = 1;
paul718e3742002-12-13 20:15:29 +00001194 struct interface *ifp;
1195 struct zebra_if *zebra_if;
1196 struct rtadv_prefix rp;
1197
1198 ifp = (struct interface *) vty->index;
1199 zebra_if = ifp->info;
1200
Denis Ovsienkoaca43b62012-01-08 18:27:12 +04001201 ret = str2prefix_ipv6 (argv[0], &rp.prefix);
paul718e3742002-12-13 20:15:29 +00001202 if (!ret)
1203 {
1204 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1205 return CMD_WARNING;
1206 }
Denis Ovsienko6bb12732012-01-08 17:46:34 +04001207 apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
hasso3e31cde2004-05-18 11:58:59 +00001208 rp.AdvOnLinkFlag = 1;
1209 rp.AdvAutonomousFlag = 1;
vincent7cee1bb2005-03-25 13:08:53 +00001210 rp.AdvRouterAddressFlag = 0;
hasso3e31cde2004-05-18 11:58:59 +00001211 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1212 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
paul718e3742002-12-13 20:15:29 +00001213
hasso3e31cde2004-05-18 11:58:59 +00001214 if (argc > 1)
paul718e3742002-12-13 20:15:29 +00001215 {
David Lamparter52f02b42015-04-10 09:14:30 +02001216 if ((isdigit((unsigned char)argv[1][0]))
1217 || strncmp (argv[1], "i", 1) == 0)
paul718e3742002-12-13 20:15:29 +00001218 {
hasso3e31cde2004-05-18 11:58:59 +00001219 if ( strncmp (argv[1], "i", 1) == 0)
1220 rp.AdvValidLifetime = UINT32_MAX;
1221 else
1222 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1223 (char **)NULL, 10);
1224
1225 if ( strncmp (argv[2], "i", 1) == 0)
1226 rp.AdvPreferredLifetime = UINT32_MAX;
1227 else
1228 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1229 (char **)NULL, 10);
1230
1231 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1232 {
1233 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1234 return CMD_WARNING;
1235 }
1236 cursor = cursor + 2;
paul718e3742002-12-13 20:15:29 +00001237 }
hasso3e31cde2004-05-18 11:58:59 +00001238 if (argc > cursor)
paul718e3742002-12-13 20:15:29 +00001239 {
hasso3e31cde2004-05-18 11:58:59 +00001240 for (i = cursor; i < argc; i++)
1241 {
1242 if (strncmp (argv[i], "of", 2) == 0)
1243 rp.AdvOnLinkFlag = 0;
1244 if (strncmp (argv[i], "no", 2) == 0)
1245 rp.AdvAutonomousFlag = 0;
vincent7cee1bb2005-03-25 13:08:53 +00001246 if (strncmp (argv[i], "ro", 2) == 0)
1247 rp.AdvRouterAddressFlag = 1;
hasso3e31cde2004-05-18 11:58:59 +00001248 }
paul718e3742002-12-13 20:15:29 +00001249 }
1250 }
1251
1252 rtadv_prefix_set (zebra_if, &rp);
1253
1254 return CMD_SUCCESS;
1255}
1256
hasso3e31cde2004-05-18 11:58:59 +00001257ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001258 ipv6_nd_prefix_val_nortaddr_cmd,
1259 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1260 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1261 "Interface IPv6 config commands\n"
1262 "Neighbor discovery\n"
1263 "Prefix information\n"
1264 "IPv6 prefix\n"
1265 "Valid lifetime in seconds\n"
1266 "Infinite valid lifetime\n"
1267 "Preferred lifetime in seconds\n"
1268 "Infinite preferred lifetime\n"
1269 "Do not use prefix for onlink determination\n"
1270 "Do not use prefix for autoconfiguration\n")
1271
1272ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001273 ipv6_nd_prefix_val_rev_cmd,
1274 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1275 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1276 "Interface IPv6 config commands\n"
1277 "Neighbor discovery\n"
1278 "Prefix information\n"
1279 "IPv6 prefix\n"
1280 "Valid lifetime in seconds\n"
1281 "Infinite valid lifetime\n"
1282 "Preferred lifetime in seconds\n"
1283 "Infinite preferred lifetime\n"
1284 "Do not use prefix for autoconfiguration\n"
1285 "Do not use prefix for onlink determination\n")
1286
1287ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001288 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1289 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1290 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1291 "Interface IPv6 config commands\n"
1292 "Neighbor discovery\n"
1293 "Prefix information\n"
1294 "IPv6 prefix\n"
1295 "Valid lifetime in seconds\n"
1296 "Infinite valid lifetime\n"
1297 "Preferred lifetime in seconds\n"
1298 "Infinite preferred lifetime\n"
1299 "Do not use prefix for autoconfiguration\n"
1300 "Do not use prefix for onlink determination\n"
1301 "Set Router Address flag\n")
1302
1303ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001304 ipv6_nd_prefix_val_noauto_cmd,
1305 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1306 "(<0-4294967295>|infinite) (no-autoconfig|)",
1307 "Interface IPv6 config commands\n"
1308 "Neighbor discovery\n"
1309 "Prefix information\n"
1310 "IPv6 prefix\n"
1311 "Valid lifetime in seconds\n"
1312 "Infinite valid lifetime\n"
1313 "Preferred lifetime in seconds\n"
1314 "Infinite preferred lifetime\n"
vincent7cee1bb2005-03-25 13:08:53 +00001315 "Do not use prefix for autoconfiguration")
hasso3e31cde2004-05-18 11:58:59 +00001316
1317ALIAS (ipv6_nd_prefix,
1318 ipv6_nd_prefix_val_offlink_cmd,
1319 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1320 "(<0-4294967295>|infinite) (off-link|)",
1321 "Interface IPv6 config commands\n"
1322 "Neighbor discovery\n"
1323 "Prefix information\n"
1324 "IPv6 prefix\n"
1325 "Valid lifetime in seconds\n"
1326 "Infinite valid lifetime\n"
1327 "Preferred lifetime in seconds\n"
1328 "Infinite preferred lifetime\n"
1329 "Do not use prefix for onlink determination\n")
1330
1331ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001332 ipv6_nd_prefix_val_rtaddr_cmd,
1333 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1334 "(<0-4294967295>|infinite) (router-address|)",
1335 "Interface IPv6 config commands\n"
1336 "Neighbor discovery\n"
1337 "Prefix information\n"
1338 "IPv6 prefix\n"
1339 "Valid lifetime in seconds\n"
1340 "Infinite valid lifetime\n"
1341 "Preferred lifetime in seconds\n"
1342 "Infinite preferred lifetime\n"
1343 "Set Router Address flag\n")
1344
1345ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001346 ipv6_nd_prefix_val_cmd,
1347 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1348 "(<0-4294967295>|infinite)",
1349 "Interface IPv6 config commands\n"
1350 "Neighbor discovery\n"
1351 "Prefix information\n"
1352 "IPv6 prefix\n"
1353 "Valid lifetime in seconds\n"
1354 "Infinite valid lifetime\n"
1355 "Preferred lifetime in seconds\n"
1356 "Infinite preferred lifetime\n")
1357
1358ALIAS (ipv6_nd_prefix,
1359 ipv6_nd_prefix_noval_cmd,
1360 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1361 "Interface IPv6 config commands\n"
1362 "Neighbor discovery\n"
1363 "Prefix information\n"
1364 "IPv6 prefix\n"
1365 "Do not use prefix for autoconfiguration\n"
1366 "Do not use prefix for onlink determination\n")
1367
1368ALIAS (ipv6_nd_prefix,
1369 ipv6_nd_prefix_noval_rev_cmd,
1370 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1371 "Interface IPv6 config commands\n"
1372 "Neighbor discovery\n"
1373 "Prefix information\n"
1374 "IPv6 prefix\n"
1375 "Do not use prefix for onlink determination\n"
1376 "Do not use prefix for autoconfiguration\n")
1377
1378ALIAS (ipv6_nd_prefix,
1379 ipv6_nd_prefix_noval_noauto_cmd,
1380 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1381 "Interface IPv6 config commands\n"
1382 "Neighbor discovery\n"
1383 "Prefix information\n"
1384 "IPv6 prefix\n"
1385 "Do not use prefix for autoconfiguration\n")
1386
1387ALIAS (ipv6_nd_prefix,
1388 ipv6_nd_prefix_noval_offlink_cmd,
1389 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1390 "Interface IPv6 config commands\n"
1391 "Neighbor discovery\n"
1392 "Prefix information\n"
1393 "IPv6 prefix\n"
1394 "Do not use prefix for onlink determination\n")
1395
1396ALIAS (ipv6_nd_prefix,
vincent7cee1bb2005-03-25 13:08:53 +00001397 ipv6_nd_prefix_noval_rtaddr_cmd,
1398 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1399 "Interface IPv6 config commands\n"
1400 "Neighbor discovery\n"
1401 "Prefix information\n"
1402 "IPv6 prefix\n"
1403 "Set Router Address flag\n")
1404
1405ALIAS (ipv6_nd_prefix,
hasso3e31cde2004-05-18 11:58:59 +00001406 ipv6_nd_prefix_prefix_cmd,
1407 "ipv6 nd prefix X:X::X:X/M",
1408 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001409 "Neighbor discovery\n"
1410 "Prefix information\n"
1411 "IPv6 prefix\n")
1412
hasso3e31cde2004-05-18 11:58:59 +00001413DEFUN (no_ipv6_nd_prefix,
1414 no_ipv6_nd_prefix_cmd,
1415 "no ipv6 nd prefix IPV6PREFIX",
paul718e3742002-12-13 20:15:29 +00001416 NO_STR
hasso3e31cde2004-05-18 11:58:59 +00001417 "Interface IPv6 config commands\n"
paul718e3742002-12-13 20:15:29 +00001418 "Neighbor discovery\n"
1419 "Prefix information\n"
1420 "IPv6 prefix\n")
1421{
1422 int ret;
1423 struct interface *ifp;
1424 struct zebra_if *zebra_if;
1425 struct rtadv_prefix rp;
1426
1427 ifp = (struct interface *) vty->index;
1428 zebra_if = ifp->info;
1429
Denis Ovsienkoaca43b62012-01-08 18:27:12 +04001430 ret = str2prefix_ipv6 (argv[0], &rp.prefix);
paul718e3742002-12-13 20:15:29 +00001431 if (!ret)
1432 {
1433 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1434 return CMD_WARNING;
1435 }
Denis Ovsienko6bb12732012-01-08 17:46:34 +04001436 apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
paul718e3742002-12-13 20:15:29 +00001437
1438 ret = rtadv_prefix_reset (zebra_if, &rp);
1439 if (!ret)
1440 {
1441 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1442 return CMD_WARNING;
1443 }
1444
1445 return CMD_SUCCESS;
1446}
Chris Caputob60668d2009-05-03 04:40:57 +00001447
1448DEFUN (ipv6_nd_router_preference,
1449 ipv6_nd_router_preference_cmd,
1450 "ipv6 nd router-preference (high|medium|low)",
1451 "Interface IPv6 config commands\n"
1452 "Neighbor discovery\n"
1453 "Default router preference\n"
1454 "High default router preference\n"
1455 "Low default router preference\n"
1456 "Medium default router preference (default)\n")
1457{
1458 struct interface *ifp;
1459 struct zebra_if *zif;
1460 int i = 0;
1461
1462 ifp = (struct interface *) vty->index;
1463 zif = ifp->info;
1464
1465 while (0 != rtadv_pref_strs[i])
1466 {
1467 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1468 {
1469 zif->rtadv.DefaultPreference = i;
1470 return CMD_SUCCESS;
1471 }
1472 i++;
1473 }
1474
1475 return CMD_ERR_NO_MATCH;
1476}
1477
1478DEFUN (no_ipv6_nd_router_preference,
1479 no_ipv6_nd_router_preference_cmd,
1480 "no ipv6 nd router-preference",
1481 NO_STR
1482 "Interface IPv6 config commands\n"
1483 "Neighbor discovery\n"
1484 "Default router preference\n")
1485{
1486 struct interface *ifp;
1487 struct zebra_if *zif;
1488
1489 ifp = (struct interface *) vty->index;
1490 zif = ifp->info;
1491
1492 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1493
1494 return CMD_SUCCESS;
1495}
1496
Denis Ovsienko4afa50b2012-01-24 12:39:58 +04001497ALIAS (no_ipv6_nd_router_preference,
1498 no_ipv6_nd_router_preference_val_cmd,
Christian Franke2b005152013-09-30 12:27:49 +00001499 "no ipv6 nd router-preference (high|medium|low)",
Denis Ovsienko4afa50b2012-01-24 12:39:58 +04001500 NO_STR
1501 "Interface IPv6 config commands\n"
1502 "Neighbor discovery\n"
1503 "Default router preference\n"
1504 "High default router preference\n"
1505 "Low default router preference\n"
1506 "Medium default router preference (default)\n")
1507
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001508DEFUN (ipv6_nd_mtu,
1509 ipv6_nd_mtu_cmd,
1510 "ipv6 nd mtu <1-65535>",
1511 "Interface IPv6 config commands\n"
1512 "Neighbor discovery\n"
1513 "Advertised MTU\n"
1514 "MTU in bytes\n")
1515{
1516 struct interface *ifp = (struct interface *) vty->index;
1517 struct zebra_if *zif = ifp->info;
1518 VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
1519 return CMD_SUCCESS;
1520}
1521
1522DEFUN (no_ipv6_nd_mtu,
1523 no_ipv6_nd_mtu_cmd,
1524 "no ipv6 nd mtu",
1525 NO_STR
1526 "Interface IPv6 config commands\n"
1527 "Neighbor discovery\n"
1528 "Advertised MTU\n")
1529{
1530 struct interface *ifp = (struct interface *) vty->index;
1531 struct zebra_if *zif = ifp->info;
1532 zif->rtadv.AdvLinkMTU = 0;
1533 return CMD_SUCCESS;
1534}
1535
1536ALIAS (no_ipv6_nd_mtu,
1537 no_ipv6_nd_mtu_val_cmd,
1538 "no ipv6 nd mtu <1-65535>",
1539 NO_STR
1540 "Interface IPv6 config commands\n"
1541 "Neighbor discovery\n"
1542 "Advertised MTU\n"
1543 "MTU in bytes\n")
1544
paul718e3742002-12-13 20:15:29 +00001545/* Write configuration about router advertisement. */
1546void
1547rtadv_config_write (struct vty *vty, struct interface *ifp)
1548{
1549 struct zebra_if *zif;
hasso52dc7ee2004-09-23 19:18:23 +00001550 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001551 struct rtadv_prefix *rprefix;
Timo Teräsbe6335d2015-05-23 11:08:41 +03001552 char buf[PREFIX_STRLEN];
vincent7cee1bb2005-03-25 13:08:53 +00001553 int interval;
paul718e3742002-12-13 20:15:29 +00001554
paul718e3742002-12-13 20:15:29 +00001555 zif = ifp->info;
1556
1557 if (! if_is_loopback (ifp))
1558 {
1559 if (zif->rtadv.AdvSendAdvertisements)
1560 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
1561 else
1562 vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
1563 }
1564
vincent7cee1bb2005-03-25 13:08:53 +00001565
1566 interval = zif->rtadv.MaxRtrAdvInterval;
1567 if (interval % 1000)
1568 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1569 VTY_NEWLINE);
1570 else
1571 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1572 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
paul718e3742002-12-13 20:15:29 +00001573 VTY_NEWLINE);
1574
Denis Ovsienko6134b872011-12-27 18:49:15 +04001575 if (zif->rtadv.AdvIntervalOption)
1576 vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE);
1577
Denis Ovsienkod660f692011-12-30 21:55:49 +04001578 if (zif->rtadv.AdvDefaultLifetime != -1)
paul718e3742002-12-13 20:15:29 +00001579 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1580 VTY_NEWLINE);
1581
Denis Ovsienko6134b872011-12-27 18:49:15 +04001582 if (zif->rtadv.HomeAgentPreference)
1583 vty_out (vty, " ipv6 nd home-agent-preference %u%s",
1584 zif->rtadv.HomeAgentPreference, VTY_NEWLINE);
1585
Denis Ovsienkod660f692011-12-30 21:55:49 +04001586 if (zif->rtadv.HomeAgentLifetime != -1)
Denis Ovsienko6134b872011-12-27 18:49:15 +04001587 vty_out (vty, " ipv6 nd home-agent-lifetime %u%s",
1588 zif->rtadv.HomeAgentLifetime, VTY_NEWLINE);
1589
1590 if (zif->rtadv.AdvHomeAgentFlag)
1591 vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE);
1592
paul718e3742002-12-13 20:15:29 +00001593 if (zif->rtadv.AdvReachableTime)
1594 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1595 VTY_NEWLINE);
1596
1597 if (zif->rtadv.AdvManagedFlag)
1598 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1599
1600 if (zif->rtadv.AdvOtherConfigFlag)
1601 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1602
Chris Caputob60668d2009-05-03 04:40:57 +00001603 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1604 vty_out (vty, " ipv6 nd router-preference %s%s",
1605 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1606 VTY_NEWLINE);
1607
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001608 if (zif->rtadv.AdvLinkMTU)
1609 vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
1610
paul1eb8ef22005-04-07 07:30:20 +00001611 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
paul718e3742002-12-13 20:15:29 +00001612 {
Timo Teräsbe6335d2015-05-23 11:08:41 +03001613 vty_out (vty, " ipv6 nd prefix %s",
1614 prefix2str (&rprefix->prefix, buf, sizeof(buf)));
hasso3e31cde2004-05-18 11:58:59 +00001615 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1616 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1617 {
1618 if (rprefix->AdvValidLifetime == UINT32_MAX)
1619 vty_out (vty, " infinite");
1620 else
1621 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1622 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1623 vty_out (vty, " infinite");
1624 else
1625 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1626 }
1627 if (!rprefix->AdvOnLinkFlag)
1628 vty_out (vty, " off-link");
1629 if (!rprefix->AdvAutonomousFlag)
1630 vty_out (vty, " no-autoconfig");
vincent7cee1bb2005-03-25 13:08:53 +00001631 if (rprefix->AdvRouterAddressFlag)
1632 vty_out (vty, " router-address");
paul718e3742002-12-13 20:15:29 +00001633 vty_out (vty, "%s", VTY_NEWLINE);
1634 }
1635}
1636
paul718e3742002-12-13 20:15:29 +00001637
paula1ac18c2005-06-28 17:17:12 +00001638static void
Feng Lu49f76092015-05-22 11:40:10 +02001639rtadv_event (struct zebra_vrf *zvrf, enum rtadv_event event, int val)
paul718e3742002-12-13 20:15:29 +00001640{
Feng Lu49f76092015-05-22 11:40:10 +02001641 struct rtadv *rtadv = &zvrf->rtadv;
1642
paul718e3742002-12-13 20:15:29 +00001643 switch (event)
1644 {
1645 case RTADV_START:
1646 if (! rtadv->ra_read)
Feng Lu49f76092015-05-22 11:40:10 +02001647 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
paul718e3742002-12-13 20:15:29 +00001648 if (! rtadv->ra_timer)
hasso3e31cde2004-05-18 11:58:59 +00001649 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
Feng Lu49f76092015-05-22 11:40:10 +02001650 zvrf, 0);
paul718e3742002-12-13 20:15:29 +00001651 break;
1652 case RTADV_STOP:
1653 if (rtadv->ra_timer)
1654 {
1655 thread_cancel (rtadv->ra_timer);
1656 rtadv->ra_timer = NULL;
1657 }
1658 if (rtadv->ra_read)
1659 {
1660 thread_cancel (rtadv->ra_read);
1661 rtadv->ra_read = NULL;
1662 }
1663 break;
1664 case RTADV_TIMER:
1665 if (! rtadv->ra_timer)
Feng Lu49f76092015-05-22 11:40:10 +02001666 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, zvrf,
hasso3e31cde2004-05-18 11:58:59 +00001667 val);
paul718e3742002-12-13 20:15:29 +00001668 break;
vincent7cee1bb2005-03-25 13:08:53 +00001669 case RTADV_TIMER_MSEC:
1670 if (! rtadv->ra_timer)
1671 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
Feng Lu49f76092015-05-22 11:40:10 +02001672 zvrf, val);
vincent7cee1bb2005-03-25 13:08:53 +00001673 break;
paul718e3742002-12-13 20:15:29 +00001674 case RTADV_READ:
1675 if (! rtadv->ra_read)
Feng Lu49f76092015-05-22 11:40:10 +02001676 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
paul718e3742002-12-13 20:15:29 +00001677 break;
1678 default:
1679 break;
1680 }
1681 return;
1682}
1683
1684void
Feng Lu49f76092015-05-22 11:40:10 +02001685rtadv_init (struct zebra_vrf *zvrf)
paul718e3742002-12-13 20:15:29 +00001686{
Feng Lu49f76092015-05-22 11:40:10 +02001687 zvrf->rtadv.sock = rtadv_make_socket (zvrf->vrf_id);
1688}
paul718e3742002-12-13 20:15:29 +00001689
Feng Lu49f76092015-05-22 11:40:10 +02001690void
1691rtadv_terminate (struct zebra_vrf *zvrf)
1692{
1693 rtadv_event (zvrf, RTADV_STOP, 0);
paul718e3742002-12-13 20:15:29 +00001694
Feng Lu49f76092015-05-22 11:40:10 +02001695 if (zvrf->rtadv.sock >= 0)
1696 {
1697 close (zvrf->rtadv.sock);
1698 zvrf->rtadv.sock = -1;
1699 }
paul718e3742002-12-13 20:15:29 +00001700
Feng Lu49f76092015-05-22 11:40:10 +02001701 zvrf->rtadv.adv_if_count = 0;
1702 zvrf->rtadv.adv_msec_if_count = 0;
1703}
1704
1705void
1706rtadv_cmd_init (void)
1707{
paul718e3742002-12-13 20:15:29 +00001708 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
1709 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
paul718e3742002-12-13 20:15:29 +00001710 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001711 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
paul718e3742002-12-13 20:15:29 +00001712 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
Denis Ovsienko4afa50b2012-01-24 12:39:58 +04001713 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_val_cmd);
1714 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_msec_val_cmd);
paul718e3742002-12-13 20:15:29 +00001715 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
1716 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
Denis Ovsienko4afa50b2012-01-24 12:39:58 +04001717 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_val_cmd);
paul718e3742002-12-13 20:15:29 +00001718 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
1719 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
Denis Ovsienko4afa50b2012-01-24 12:39:58 +04001720 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_val_cmd);
paul718e3742002-12-13 20:15:29 +00001721 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
1722 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
1723 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
1724 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001725 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
1726 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
1727 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
1728 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
Denis Ovsienko4afa50b2012-01-24 12:39:58 +04001729 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_val_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001730 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
1731 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
Denis Ovsienko4afa50b2012-01-24 12:39:58 +04001732 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_val_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001733 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
1734 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001735 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001736 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
1737 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001738 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
1739 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
1740 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001741 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001742 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
1743 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
1744 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
1745 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
1746 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
vincent7cee1bb2005-03-25 13:08:53 +00001747 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
hasso3e31cde2004-05-18 11:58:59 +00001748 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
1749 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
Chris Caputob60668d2009-05-03 04:40:57 +00001750 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
1751 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
Denis Ovsienko4afa50b2012-01-24 12:39:58 +04001752 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_val_cmd);
Denis Ovsienko6ae93c02011-12-27 10:45:36 +04001753 install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
1754 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
1755 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
paul718e3742002-12-13 20:15:29 +00001756}
1757
paula1ac18c2005-06-28 17:17:12 +00001758static int
paul718e3742002-12-13 20:15:29 +00001759if_join_all_router (int sock, struct interface *ifp)
1760{
1761 int ret;
1762
1763 struct ipv6_mreq mreq;
1764
1765 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1766 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1767 mreq.ipv6mr_interface = ifp->ifindex;
1768
1769 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1770 (char *) &mreq, sizeof mreq);
1771 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001772 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001773
1774 zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
1775
1776 return 0;
1777}
1778
paula1ac18c2005-06-28 17:17:12 +00001779static int
paul718e3742002-12-13 20:15:29 +00001780if_leave_all_router (int sock, struct interface *ifp)
1781{
1782 int ret;
1783
1784 struct ipv6_mreq mreq;
1785
1786 memset (&mreq, 0, sizeof (struct ipv6_mreq));
1787 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
1788 mreq.ipv6mr_interface = ifp->ifindex;
1789
1790 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1791 (char *) &mreq, sizeof mreq);
1792 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +00001793 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001794
1795 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
1796
1797 return 0;
1798}
1799
1800#else
1801void
Feng Lu49f76092015-05-22 11:40:10 +02001802rtadv_init (struct zebra_vrf *zvrf)
1803{
1804 /* Empty.*/;
1805}
1806void
1807rtadv_terminate (struct zebra_vrf *zvrf)
1808{
1809 /* Empty.*/;
1810}
1811void
1812rtadv_cmd_init (void)
paul718e3742002-12-13 20:15:29 +00001813{
1814 /* Empty.*/;
1815}
Donald Sharp64257732015-11-20 08:33:30 -05001816#endif /* HAVE_RTADV && HAVE_IPV6 */