]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rtadv.c
*: split & distribute memtypes and stop (re|ab)using lib/ MTYPEs
[mirror_frr.git] / zebra / rtadv.c
CommitLineData
718e3744 1/* Router advertisement
7cee1bb1 2 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
718e3744 3 * 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"
4a1ab8e4 26#include "zebra_memory.h"
718e3744 27#include "sockopt.h"
28#include "thread.h"
29#include "if.h"
4a04e5f7 30#include "stream.h"
718e3744 31#include "log.h"
32#include "prefix.h"
33#include "linklist.h"
34#include "command.h"
edd7c245 35#include "privs.h"
cd80d74f 36#include "vrf.h"
718e3744 37
38#include "zebra/interface.h"
39#include "zebra/rtadv.h"
40#include "zebra/debug.h"
537d8ea9 41#include "zebra/rib.h"
4b5e1359 42#include "zebra/zserv.h"
fe18ee2d 43#include "zebra/zebra_ns.h"
7c551956 44#include "zebra/zebra_vrf.h"
718e3744 45
edd7c245 46extern struct zebra_privs_t zserv_privs;
47
8da4e946 48#if defined (HAVE_IPV6) && defined (HAVE_RTADV)
718e3744 49
fa2b17e3 50#ifdef OPEN_BSD
51#include <netinet/icmp6.h>
52#endif
53
718e3744 54/* If RFC2133 definition is used. */
55#ifndef IPV6_JOIN_GROUP
56#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
57#endif
58#ifndef IPV6_LEAVE_GROUP
59#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
60#endif
61
62#define ALLNODE "ff02::1"
63#define ALLROUTER "ff02::2"
64
7cee1bb1 65enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
66 RTADV_TIMER_MSEC, RTADV_READ};
718e3744 67
43459b1f 68static void rtadv_event (struct zebra_ns *, enum rtadv_event, int);
718e3744 69
a1ac18c4 70static int if_join_all_router (int, struct interface *);
71static int if_leave_all_router (int, struct interface *);
6b0655a2 72
911ad1e2 73static int
b892f1dd 74rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
911ad1e2 75{
795b5abf
QY
76 int ret = -1;
77 struct interface *iface;
78 struct zebra_if *zif;
79
911ad1e2 80 iface = if_lookup_by_index_per_ns (zns, *ifindex);
81 if (iface && iface->info)
82 {
83 zif = iface->info;
84 zif->ra_rcvd++;
85 ret = 0;
86 }
795b5abf
QY
87 return ret;
88}
89
a1ac18c4 90static int
911ad1e2 91rtadv_recv_packet (struct zebra_ns *zns, int sock, u_char *buf, int buflen,
b892f1dd 92 struct sockaddr_in6 *from, ifindex_t *ifindex,
718e3744 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
b99760ab 118 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
718e3744 119 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)
b0b709ab
SH
135 {
136 int *hoptr = (int *) CMSG_DATA (cmsgptr);
137 *hoplimit = *hoptr;
138 }
718e3744 139 }
795b5abf 140
911ad1e2 141 rtadv_increment_received(zns, ifindex);
718e3744 142 return ret;
143}
144
145#define RTADV_MSG_SIZE 4096
146
147/* Send router advertisement packet. */
a1ac18c4 148static void
718e3744 149rtadv_send_packet (int sock, struct interface *ifp)
150{
151 struct msghdr msg;
152 struct iovec iov;
153 struct cmsghdr *cmsgptr;
154 struct in6_pktinfo *pkt;
155 struct sockaddr_in6 addr;
57492d56 156 static void *adata = NULL;
718e3744 157 unsigned char buf[RTADV_MSG_SIZE];
158 struct nd_router_advert *rtadv;
159 int ret;
160 int len = 0;
161 struct zebra_if *zif;
1eb8ef25 162 struct rtadv_prefix *rprefix;
718e3744 163 u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
52dc7ee6 164 struct listnode *node;
d660f698 165 u_int16_t pkt_RouterLifetime;
718e3744 166
57492d56 167 /*
168 * Allocate control message bufffer. This is dynamic because
169 * CMSG_SPACE is not guaranteed not to call a function. Note that
170 * the size will be different on different architectures due to
171 * differing alignment rules.
172 */
173 if (adata == NULL)
174 {
175 /* XXX Free on shutdown. */
176 adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
177
178 if (adata == NULL)
f360eac0 179 zlog_err("rtadv_send_packet: can't malloc control data");
57492d56 180 }
181
718e3744 182 /* Logging of packet. */
183 if (IS_ZEBRA_DEBUG_PACKET)
f360eac0 184 zlog_debug ("%s(%u): Tx RA, socket %u",
185 ifp->name, ifp->ifindex, sock);
718e3744 186
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);
aca43b65 194 IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr);
718e3744 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;
b60668d0
CC
207
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
718e3744 213 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;
7cee1bb1 217 if (zif->rtadv.AdvHomeAgentFlag)
218 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
d660f698
DO
219 /* 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);
718e3744 231 rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
232 rtadv->nd_ra_retransmit = htonl (0);
233
234 len = sizeof (struct nd_router_advert);
235
d660f698
DO
236 /* 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 )
7cee1bb1 245 {
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);
d660f698
DO
252 /* 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 );
7cee1bb1 263 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
718e3744 277 /* Fill in prefix. */
1eb8ef25 278 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
718e3744 279 {
280 struct nd_opt_prefix_info *pinfo;
718e3744 281
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;
7cee1bb1 293 if (rprefix->AdvRouterAddressFlag)
294 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
718e3744 295
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
aca43b65 300 IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix);
718e3744 301
302#ifdef DEBUG
303 {
304 u_char buf[INET6_ADDRSTRLEN];
305
b6178002 306 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
3e31cded 307 buf, INET6_ADDRSTRLEN));
718e3744 308
309 }
310#endif /* DEBUG */
311
312 len += sizeof (struct nd_opt_prefix_info);
313 }
314
315 /* Hardware address. */
718e3744 316 if (ifp->hw_addr_len != 0)
317 {
318 buf[len++] = ND_OPT_SOURCE_LINKADDR;
50adf783
DW
319
320 /* Option length should be rounded up to next octet if
321 the link address does not end on an octet boundary. */
322 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
718e3744 323
324 memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
325 len += ifp->hw_addr_len;
50adf783
DW
326
327 /* Pad option to end on an octet boundary. */
328 memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
329 len += -(ifp->hw_addr_len + 2) & 0x7;
718e3744 330 }
718e3744 331
6ae93c05
DO
332 /* 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
718e3744 343 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;
f841e02e 348 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
57492d56 349 msg.msg_flags = 0;
718e3744 350 iov.iov_base = buf;
351 iov.iov_len = len;
352
b99760ab 353 cmsgptr = ZCMSG_FIRSTHDR(&msg);
57492d56 354 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
718e3744 355 cmsgptr->cmsg_level = IPPROTO_IPV6;
356 cmsgptr->cmsg_type = IPV6_PKTINFO;
80893817 357
718e3744 358 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);
9ccabd1c 363 if (ret < 0)
364 {
f360eac0 365 zlog_err ("%s(%u): Tx RA failed, socket %u error %d (%s)",
366 ifp->name, ifp->ifindex, sock, errno, safe_strerror(errno));
9ccabd1c 367 }
795b5abf
QY
368 else
369 zif->ra_sent++;
718e3744 370}
371
a1ac18c4 372static int
718e3744 373rtadv_timer (struct thread *thread)
374{
43459b1f 375 struct zebra_ns *zns = THREAD_ARG (thread);
376 vrf_iter_t iter;
1eb8ef25 377 struct listnode *node, *nnode;
718e3744 378 struct interface *ifp;
379 struct zebra_if *zif;
7cee1bb1 380 int period;
718e3744 381
43459b1f 382 zns->rtadv.ra_timer = NULL;
383 if (zns->rtadv.adv_msec_if_count == 0)
7cee1bb1 384 {
385 period = 1000; /* 1 s */
43459b1f 386 rtadv_event (zns, RTADV_TIMER, 1 /* 1 s */);
7cee1bb1 387 }
388 else
389 {
390 period = 10; /* 10 ms */
43459b1f 391 rtadv_event (zns, RTADV_TIMER_MSEC, 10 /* 10 ms */);
7cee1bb1 392 }
718e3744 393
43459b1f 394 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
395 for (ALL_LIST_ELEMENTS (vrf_iter2iflist (iter), node, nnode, ifp))
396 {
c23af4d3 397 if (if_is_loopback (ifp) ||
398 CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK) ||
399 ! if_is_operative (ifp))
43459b1f 400 continue;
401
402 zif = ifp->info;
403
404 if (zif->rtadv.AdvSendAdvertisements)
405 {
6c9678b4 406 if (zif->rtadv.inFastRexmit)
43459b1f 407 {
6c9678b4
DD
408 /* We assume we fast rexmit every sec so no additional vars */
409 if (--zif->rtadv.NumFastReXmitsRemain <= 0)
410 zif->rtadv.inFastRexmit = 0;
411
412 if (IS_ZEBRA_DEBUG_SEND)
413 zlog_debug("Fast RA Rexmit on interface %s", ifp->name);
414
43459b1f 415 rtadv_send_packet (zns->rtadv.sock, ifp);
416 }
6c9678b4
DD
417 else
418 {
419 zif->rtadv.AdvIntervalTimer -= period;
420 if (zif->rtadv.AdvIntervalTimer <= 0)
421 {
422 /* FIXME: using MaxRtrAdvInterval each time isn't what section
423 6.2.4 of RFC4861 tells to do. */
424 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
425 rtadv_send_packet (zns->rtadv.sock, ifp);
426 }
427 }
43459b1f 428 }
429 }
718e3744 430
718e3744 431 return 0;
432}
433
a1ac18c4 434static void
718e3744 435rtadv_process_solicit (struct interface *ifp)
436{
cd80d74f 437 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
43459b1f 438 struct zebra_ns *zns = zvrf->zns;
718e3744 439
43459b1f 440 assert (zns);
441 rtadv_send_packet (zns->rtadv.sock, ifp);
718e3744 442}
443
a1ac18c4 444static void
a80beece
DS
445rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp,
446 struct sockaddr_in6 *addr)
718e3744 447{
a80beece
DS
448 struct nd_router_advert *radvert;
449 char addr_str[INET6_ADDRSTRLEN];
450 struct zebra_if *zif;
1d20ccf3 451 struct prefix p;
a80beece
DS
452
453 zif = ifp->info;
454
455 inet_ntop (AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
456
a80beece 457 if (len < sizeof(struct nd_router_advert)) {
f360eac0 458 zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
459 ifp->name, ifp->ifindex, len, addr_str);
a80beece
DS
460 return;
461 }
462 if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
f360eac0 463 zlog_warn("%s(%u): Rx RA with non-linklocal source address from %s",
464 ifp->name, ifp->ifindex, addr_str);
a80beece
DS
465 return;
466 }
467
468 radvert = (struct nd_router_advert *) msg;
469
470 if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) &&
471 (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit))
472 {
f360eac0 473 zlog_warn("%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
474 ifp->name, ifp->ifindex, addr_str);
a80beece
DS
475 }
476
477 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) &&
478 !zif->rtadv.AdvManagedFlag)
479 {
f360eac0 480 zlog_warn("%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
481 ifp->name, ifp->ifindex, addr_str);
a80beece
DS
482 }
483
484 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) &&
485 !zif->rtadv.AdvOtherConfigFlag)
486 {
f360eac0 487 zlog_warn("%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
488 ifp->name, ifp->ifindex, addr_str);
a80beece
DS
489 }
490
491 if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) &&
492 (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime))
493 {
f360eac0 494 zlog_warn("%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
495 ifp->name, ifp->ifindex, addr_str);
a80beece
DS
496 }
497
498 if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) &&
4e3afb14 499 (ntohl(radvert->nd_ra_retransmit) != (unsigned int)zif->rtadv.AdvRetransTimer))
a80beece 500 {
f360eac0 501 zlog_warn("%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
502 ifp->name, ifp->ifindex, addr_str);
a80beece
DS
503 }
504
1d20ccf3 505 /* Create entry for neighbor if not known. */
506 p.family = AF_INET6;
507 IPV6_ADDR_COPY (&p.u.prefix, &addr->sin6_addr);
508 p.prefixlen = IPV6_MAX_PREFIXLEN;
a80beece 509
1d20ccf3 510 if (!nbr_connected_check(ifp, &p))
511 nbr_connected_add_ipv6 (ifp, &addr->sin6_addr);
718e3744 512}
513
a80beece 514
a1ac18c4 515static void
b892f1dd 516rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex, int hoplimit,
43459b1f 517 struct sockaddr_in6 *from, struct zebra_ns *zns)
718e3744 518{
519 struct icmp6_hdr *icmph;
520 struct interface *ifp;
521 struct zebra_if *zif;
f360eac0 522 char addr_str[INET6_ADDRSTRLEN];
523
524 inet_ntop (AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
718e3744 525
526 /* Interface search. */
43459b1f 527 ifp = if_lookup_by_index_per_ns (zns, ifindex);
718e3744 528 if (ifp == NULL)
529 {
f360eac0 530 zlog_warn ("RA/RS received on unknown IF %u from %s",
531 ifindex, addr_str);
718e3744 532 return;
533 }
534
f360eac0 535 if (IS_ZEBRA_DEBUG_PACKET)
536 zlog_debug ("%s(%u): Rx RA/RS len %d from %s",
537 ifp->name, ifp->ifindex, len, addr_str);
538
c23af4d3 539 if (if_is_loopback (ifp) ||
540 CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
718e3744 541 return;
542
543 /* Check interface configuration. */
544 zif = ifp->info;
545 if (! zif->rtadv.AdvSendAdvertisements)
546 return;
547
548 /* ICMP message length check. */
549 if (len < sizeof (struct icmp6_hdr))
550 {
f360eac0 551 zlog_warn ("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
552 ifp->name, ifp->ifindex, len);
718e3744 553 return;
554 }
555
556 icmph = (struct icmp6_hdr *) buf;
557
558 /* ICMP message type check. */
559 if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
560 icmph->icmp6_type != ND_ROUTER_ADVERT)
561 {
f360eac0 562 zlog_warn ("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
563 ifp->name, ifp->ifindex, icmph->icmp6_type);
718e3744 564 return;
565 }
566
567 /* Hoplimit check. */
568 if (hoplimit >= 0 && hoplimit != 255)
569 {
f360eac0 570 zlog_warn ("%s(%u): Rx RA - Invalid hoplimit %d",
571 ifp->name, ifp->ifindex, hoplimit);
718e3744 572 return;
573 }
574
575 /* Check ICMP message type. */
576 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
577 rtadv_process_solicit (ifp);
578 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
a80beece 579 rtadv_process_advert (buf, len, ifp, from);
718e3744 580
581 return;
582}
583
a1ac18c4 584static int
718e3744 585rtadv_read (struct thread *thread)
586{
587 int sock;
588 int len;
589 u_char buf[RTADV_MSG_SIZE];
590 struct sockaddr_in6 from;
b892f1dd 591 ifindex_t ifindex = 0;
718e3744 592 int hoplimit = -1;
43459b1f 593 struct zebra_ns *zns = THREAD_ARG (thread);
718e3744 594
595 sock = THREAD_FD (thread);
43459b1f 596 zns->rtadv.ra_read = NULL;
718e3744 597
598 /* Register myself. */
43459b1f 599 rtadv_event (zns, RTADV_READ, sock);
718e3744 600
d9ce8324 601 len = rtadv_recv_packet (zns, sock, buf, sizeof (buf), &from, &ifindex, &hoplimit);
718e3744 602
603 if (len < 0)
604 {
f360eac0 605 zlog_warn ("RA/RS recv failed, socket %u error %s",
606 sock, safe_strerror (errno));
718e3744 607 return len;
608 }
609
43459b1f 610 rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, &from, zns);
718e3744 611
612 return 0;
613}
614
a1ac18c4 615static int
43459b1f 616rtadv_make_socket (void)
718e3744 617{
618 int sock;
43459b1f 619 int ret = 0;
718e3744 620 struct icmp6_filter filter;
621
edd7c245 622 if ( zserv_privs.change (ZPRIVS_RAISE) )
623 zlog_err ("rtadv_make_socket: could not raise privs, %s",
6099b3b5 624 safe_strerror (errno) );
edd7c245 625
43459b1f 626 sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
718e3744 627
edd7c245 628 if ( zserv_privs.change (ZPRIVS_LOWER) )
629 zlog_err ("rtadv_make_socket: could not lower privs, %s",
6099b3b5 630 safe_strerror (errno) );
edd7c245 631
718e3744 632 if (sock < 0)
a5c304ab
MS
633 {
634 close (sock);
635 return -1;
636 }
718e3744 637
638 ret = setsockopt_ipv6_pktinfo (sock, 1);
718e3744 639 if (ret < 0)
a5c304ab
MS
640 {
641 close (sock);
642 return ret;
643 }
718e3744 644 ret = setsockopt_ipv6_multicast_loop (sock, 0);
645 if (ret < 0)
a5c304ab
MS
646 {
647 close (sock);
648 return ret;
649 }
718e3744 650 ret = setsockopt_ipv6_unicast_hops (sock, 255);
651 if (ret < 0)
a5c304ab
MS
652 {
653 close (sock);
654 return ret;
655 }
718e3744 656 ret = setsockopt_ipv6_multicast_hops (sock, 255);
657 if (ret < 0)
a5c304ab
MS
658 {
659 close (sock);
660 return ret;
661 }
718e3744 662 ret = setsockopt_ipv6_hoplimit (sock, 1);
663 if (ret < 0)
a5c304ab
MS
664 {
665 close (sock);
666 return ret;
667 }
718e3744 668
669 ICMP6_FILTER_SETBLOCKALL(&filter);
670 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
671 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
672
673 ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
674 sizeof (struct icmp6_filter));
675 if (ret < 0)
676 {
6099b3b5 677 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
718e3744 678 return ret;
679 }
680
681 return sock;
682}
6b0655a2 683
a1ac18c4 684static struct rtadv_prefix *
66e5cd87 685rtadv_prefix_new (void)
718e3744 686{
393deb9b 687 return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
718e3744 688}
689
a1ac18c4 690static void
718e3744 691rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
692{
693 XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
694}
695
a1ac18c4 696static struct rtadv_prefix *
aca43b65 697rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p)
718e3744 698{
52dc7ee6 699 struct listnode *node;
718e3744 700 struct rtadv_prefix *rprefix;
701
1eb8ef25 702 for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
aca43b65 703 if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p))
1eb8ef25 704 return rprefix;
718e3744 705 return NULL;
706}
707
a1ac18c4 708static struct rtadv_prefix *
aca43b65 709rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p)
718e3744 710{
711 struct rtadv_prefix *rprefix;
712
713 rprefix = rtadv_prefix_lookup (rplist, p);
714 if (rprefix)
715 return rprefix;
716
717 rprefix = rtadv_prefix_new ();
aca43b65 718 memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6));
718e3744 719 listnode_add (rplist, rprefix);
720
721 return rprefix;
722}
723
a1ac18c4 724static void
718e3744 725rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
726{
727 struct rtadv_prefix *rprefix;
728
729 rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
730
731 /* Set parameters. */
732 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
733 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
734 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
735 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
7cee1bb1 736 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
718e3744 737}
738
a1ac18c4 739static int
718e3744 740rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
741{
742 struct rtadv_prefix *rprefix;
743
744 rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
745 if (rprefix != NULL)
746 {
747 listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
748 rtadv_prefix_free (rprefix);
749 return 1;
750 }
751 else
752 return 0;
753}
754
4a04e5f7 755static void
b6120505
DW
756ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status status)
757{
758 struct zebra_if *zif;
759 struct zebra_vrf *zvrf;
43459b1f 760 struct zebra_ns *zns;
b6120505
DW
761
762 zif = ifp->info;
763 zvrf = vrf_info_lookup (ifp->vrf_id);
43459b1f 764 zns = zvrf->zns;
b6120505
DW
765
766 if (status == RA_SUPPRESS)
767 {
768 /* RA is currently enabled */
769 if (zif->rtadv.AdvSendAdvertisements)
770 {
771 zif->rtadv.AdvSendAdvertisements = 0;
772 zif->rtadv.AdvIntervalTimer = 0;
43459b1f 773 zns->rtadv.adv_if_count--;
b6120505 774
43459b1f 775 if_leave_all_router (zns->rtadv.sock, ifp);
b6120505 776
43459b1f 777 if (zns->rtadv.adv_if_count == 0)
778 rtadv_event (zns, RTADV_STOP, 0);
b6120505
DW
779 }
780 }
781 else
782 {
783 if (! zif->rtadv.AdvSendAdvertisements)
784 {
785 zif->rtadv.AdvSendAdvertisements = 1;
786 zif->rtadv.AdvIntervalTimer = 0;
43459b1f 787 zns->rtadv.adv_if_count++;
b6120505 788
6c9678b4
DD
789 if (zif->rtadv.MaxRtrAdvInterval >= 1000)
790 {
791 /* Enable Fast RA only when RA interval is in secs */
792 zif->rtadv.inFastRexmit = 1;
793 zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
794 }
795
43459b1f 796 if_join_all_router (zns->rtadv.sock, ifp);
b6120505 797
43459b1f 798 if (zns->rtadv.adv_if_count == 1)
799 rtadv_event (zns, RTADV_START, zns->rtadv.sock);
b6120505
DW
800 }
801 }
802}
803
4a04e5f7 804/*
805 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
806 * Note that while the client could request RA on an interface on which the
807 * operator has not enabled RA, RA won't be disabled upon client request
5c81b96a 808 * if the operator has explicitly enabled RA. The enable request can also
809 * specify a RA interval (in seconds).
4a04e5f7 810 */
811void
812zebra_interface_radv_set (struct zserv *client, int sock, u_short length,
813 struct zebra_vrf *zvrf, int enable)
814{
815 struct stream *s;
816 unsigned int ifindex;
817 struct interface *ifp;
818 struct zebra_if *zif;
5c81b96a 819 int ra_interval;
4a04e5f7 820
821 s = client->ibuf;
822
5c81b96a 823 /* Get interface index and RA interval. */
4a04e5f7 824 ifindex = stream_getl (s);
5c81b96a 825 ra_interval = stream_getl (s);
4a04e5f7 826
827 if (IS_ZEBRA_DEBUG_EVENT)
5c81b96a 828 zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
4a04e5f7 829 zvrf->vrf_id, ifindex, enable ? "enable" : "disable",
5c81b96a 830 zebra_route_string(client->proto), ra_interval);
4a04e5f7 831
832 /* Locate interface and check VRF match. */
833 ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ifindex);
834 if (!ifp)
835 {
836 zlog_warn("%u: IF %u RA %s client %s - interface unknown",
837 zvrf->vrf_id, ifindex, enable ? "enable" : "disable",
838 zebra_route_string(client->proto));
839 return;
840 }
841 if (ifp->vrf_id != zvrf->vrf_id)
842 {
843 zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
844 zvrf->vrf_id, ifindex, enable ? "enable" : "disable",
845 zebra_route_string(client->proto), ifp->vrf_id);
846 return;
847 }
848
849 zif = ifp->info;
850 if (enable)
5c81b96a 851 {
852 ipv6_nd_suppress_ra_set (ifp, RA_ENABLE);
853 if (ra_interval &&
854 (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval)
855 zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
856 }
4a04e5f7 857 else
858 {
859 if (!zif->rtadv.configured)
5c81b96a 860 {
861 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
862 ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS);
863 }
4a04e5f7 864 }
865}
866
718e3744 867DEFUN (ipv6_nd_suppress_ra,
868 ipv6_nd_suppress_ra_cmd,
869 "ipv6 nd suppress-ra",
3e31cded 870 "Interface IPv6 config commands\n"
718e3744 871 "Neighbor discovery\n"
872 "Suppress Router Advertisement\n")
873{
874 struct interface *ifp;
4a04e5f7 875 struct zebra_if *zif;
718e3744 876
877 ifp = vty->index;
718e3744 878
c23af4d3 879 if (if_is_loopback (ifp) ||
880 CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
718e3744 881 {
c23af4d3 882 vty_out (vty, "Cannot configure IPv6 Router Advertisements on this interface%s", VTY_NEWLINE);
718e3744 883 return CMD_WARNING;
884 }
885
b6120505 886 ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS);
4a04e5f7 887 zif = ifp->info;
888 zif->rtadv.configured = 0;
718e3744 889 return CMD_SUCCESS;
890}
891
718e3744 892DEFUN (no_ipv6_nd_suppress_ra,
893 no_ipv6_nd_suppress_ra_cmd,
894 "no ipv6 nd suppress-ra",
895 NO_STR
3e31cded 896 "Interface IPv6 config commands\n"
718e3744 897 "Neighbor discovery\n"
898 "Suppress Router Advertisement\n")
899{
900 struct interface *ifp;
4a04e5f7 901 struct zebra_if *zif;
718e3744 902
903 ifp = vty->index;
718e3744 904
c23af4d3 905 if (if_is_loopback (ifp) ||
906 CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
718e3744 907 {
c23af4d3 908 vty_out (vty, "Cannot configure IPv6 Router Advertisements on this interface%s", VTY_NEWLINE);
718e3744 909 return CMD_WARNING;
910 }
911
b6120505 912 ipv6_nd_suppress_ra_set (ifp, RA_ENABLE);
4a04e5f7 913 zif = ifp->info;
914 zif->rtadv.configured = 1;
718e3744 915 return CMD_SUCCESS;
916}
917
7cee1bb1 918DEFUN (ipv6_nd_ra_interval_msec,
919 ipv6_nd_ra_interval_msec_cmd,
4afa50b3 920 "ipv6 nd ra-interval msec <70-1800000>",
7cee1bb1 921 "Interface IPv6 config commands\n"
922 "Neighbor discovery\n"
923 "Router Advertisement interval\n"
924 "Router Advertisement interval in milliseconds\n")
925{
4afa50b3
DO
926 unsigned interval;
927 struct interface *ifp = (struct interface *) vty->index;
928 struct zebra_if *zif = ifp->info;
cd80d74f 929 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
43459b1f 930 struct zebra_ns *zns;
7cee1bb1 931
43459b1f 932 zns = zvrf->zns;
4afa50b3
DO
933 VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
934 if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000))
935 {
936 vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
937 return CMD_WARNING;
938 }
7cee1bb1 939
940 if (zif->rtadv.MaxRtrAdvInterval % 1000)
43459b1f 941 zns->rtadv.adv_msec_if_count--;
7cee1bb1 942
943 if (interval % 1000)
43459b1f 944 zns->rtadv.adv_msec_if_count++;
7cee1bb1 945
946 zif->rtadv.MaxRtrAdvInterval = interval;
947 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
948 zif->rtadv.AdvIntervalTimer = 0;
949
950 return CMD_SUCCESS;
951}
952
718e3744 953DEFUN (ipv6_nd_ra_interval,
954 ipv6_nd_ra_interval_cmd,
4afa50b3 955 "ipv6 nd ra-interval <1-1800>",
3e31cded 956 "Interface IPv6 config commands\n"
718e3744 957 "Neighbor discovery\n"
958 "Router Advertisement interval\n"
959 "Router Advertisement interval in seconds\n")
960{
4afa50b3
DO
961 unsigned interval;
962 struct interface *ifp = (struct interface *) vty->index;
963 struct zebra_if *zif = ifp->info;
cd80d74f 964 struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
43459b1f 965 struct zebra_ns *zns;
718e3744 966
43459b1f 967 zns = zvrf->zns;
4afa50b3
DO
968 VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
969 if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime))
970 {
971 vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
972 return CMD_WARNING;
973 }
718e3744 974
7cee1bb1 975 if (zif->rtadv.MaxRtrAdvInterval % 1000)
43459b1f 976 zns->rtadv.adv_msec_if_count--;
7cee1bb1 977
978 /* convert to milliseconds */
979 interval = interval * 1000;
980
718e3744 981 zif->rtadv.MaxRtrAdvInterval = interval;
982 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
983 zif->rtadv.AdvIntervalTimer = 0;
984
985 return CMD_SUCCESS;
986}
987
988DEFUN (no_ipv6_nd_ra_interval,
989 no_ipv6_nd_ra_interval_cmd,
990 "no ipv6 nd ra-interval",
991 NO_STR
3e31cded 992 "Interface IPv6 config commands\n"
718e3744 993 "Neighbor discovery\n"
994 "Router Advertisement interval\n")
995{
996 struct interface *ifp;
997 struct zebra_if *zif;
cd80d74f 998 struct zebra_vrf *zvrf;
43459b1f 999 struct zebra_ns *zns;
718e3744 1000
1001 ifp = (struct interface *) vty->index;
1002 zif = ifp->info;
cd80d74f 1003 zvrf = vrf_info_lookup (ifp->vrf_id);
43459b1f 1004 zns = zvrf->zns;
718e3744 1005
7cee1bb1 1006 if (zif->rtadv.MaxRtrAdvInterval % 1000)
43459b1f 1007 zns->rtadv.adv_msec_if_count--;
7cee1bb1 1008
718e3744 1009 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
1010 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
1011 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
1012
1013 return CMD_SUCCESS;
1014}
1015
4afa50b3
DO
1016ALIAS (no_ipv6_nd_ra_interval,
1017 no_ipv6_nd_ra_interval_val_cmd,
1018 "no ipv6 nd ra-interval <1-1800>",
1019 NO_STR
1020 "Interface IPv6 config commands\n"
1021 "Neighbor discovery\n"
1022 "Router Advertisement interval\n")
1023
1024ALIAS (no_ipv6_nd_ra_interval,
1025 no_ipv6_nd_ra_interval_msec_val_cmd,
1026 "no ipv6 nd ra-interval msec <1-1800000>",
1027 NO_STR
1028 "Interface IPv6 config commands\n"
1029 "Neighbor discovery\n"
1030 "Router Advertisement interval\n"
1031 "Router Advertisement interval in milliseconds\n")
1032
718e3744 1033DEFUN (ipv6_nd_ra_lifetime,
1034 ipv6_nd_ra_lifetime_cmd,
4afa50b3 1035 "ipv6 nd ra-lifetime <0-9000>",
3e31cded 1036 "Interface IPv6 config commands\n"
718e3744 1037 "Neighbor discovery\n"
1038 "Router lifetime\n"
4afa50b3 1039 "Router lifetime in seconds (0 stands for a non-default gw)\n")
718e3744 1040{
1041 int lifetime;
1042 struct interface *ifp;
1043 struct zebra_if *zif;
1044
1045 ifp = (struct interface *) vty->index;
1046 zif = ifp->info;
1047
4afa50b3 1048 VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[0], 0, 9000);
718e3744 1049
d660f698
DO
1050 /* The value to be placed in the Router Lifetime field
1051 * of Router Advertisements sent from the interface,
1052 * in seconds. MUST be either zero or between
1053 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
4afa50b3 1054 if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval))
718e3744 1055 {
4afa50b3 1056 vty_out (vty, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE);
718e3744 1057 return CMD_WARNING;
1058 }
1059
1060 zif->rtadv.AdvDefaultLifetime = lifetime;
1061
1062 return CMD_SUCCESS;
1063}
1064
1065DEFUN (no_ipv6_nd_ra_lifetime,
1066 no_ipv6_nd_ra_lifetime_cmd,
1067 "no ipv6 nd ra-lifetime",
1068 NO_STR
3e31cded 1069 "Interface IPv6 config commands\n"
718e3744 1070 "Neighbor discovery\n"
1071 "Router lifetime\n")
1072{
1073 struct interface *ifp;
1074 struct zebra_if *zif;
1075
1076 ifp = (struct interface *) vty->index;
1077 zif = ifp->info;
1078
d660f698 1079 zif->rtadv.AdvDefaultLifetime = -1;
718e3744 1080
1081 return CMD_SUCCESS;
1082}
1083
4afa50b3
DO
1084ALIAS (no_ipv6_nd_ra_lifetime,
1085 no_ipv6_nd_ra_lifetime_val_cmd,
1086 "no ipv6 nd ra-lifetime <0-9000>",
1087 NO_STR
1088 "Interface IPv6 config commands\n"
1089 "Neighbor discovery\n"
1090 "Router lifetime\n"
1091 "Router lifetime in seconds (0 stands for a non-default gw)\n")
1092
718e3744 1093DEFUN (ipv6_nd_reachable_time,
1094 ipv6_nd_reachable_time_cmd,
4afa50b3 1095 "ipv6 nd reachable-time <1-3600000>",
3e31cded 1096 "Interface IPv6 config commands\n"
718e3744 1097 "Neighbor discovery\n"
1098 "Reachable time\n"
1099 "Reachable time in milliseconds\n")
1100{
4afa50b3
DO
1101 struct interface *ifp = (struct interface *) vty->index;
1102 struct zebra_if *zif = ifp->info;
1103 VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[0], 1, RTADV_MAX_REACHABLE_TIME);
718e3744 1104 return CMD_SUCCESS;
1105}
1106
1107DEFUN (no_ipv6_nd_reachable_time,
1108 no_ipv6_nd_reachable_time_cmd,
1109 "no ipv6 nd reachable-time",
1110 NO_STR
3e31cded 1111 "Interface IPv6 config commands\n"
718e3744 1112 "Neighbor discovery\n"
1113 "Reachable time\n")
1114{
1115 struct interface *ifp;
1116 struct zebra_if *zif;
1117
1118 ifp = (struct interface *) vty->index;
1119 zif = ifp->info;
1120
1121 zif->rtadv.AdvReachableTime = 0;
1122
1123 return CMD_SUCCESS;
1124}
1125
4afa50b3
DO
1126ALIAS (no_ipv6_nd_reachable_time,
1127 no_ipv6_nd_reachable_time_val_cmd,
1128 "no ipv6 nd reachable-time <1-3600000>",
1129 NO_STR
1130 "Interface IPv6 config commands\n"
1131 "Neighbor discovery\n"
1132 "Reachable time\n"
1133 "Reachable time in milliseconds\n")
1134
7cee1bb1 1135DEFUN (ipv6_nd_homeagent_preference,
1136 ipv6_nd_homeagent_preference_cmd,
4afa50b3 1137 "ipv6 nd home-agent-preference <0-65535>",
7cee1bb1 1138 "Interface IPv6 config commands\n"
1139 "Neighbor discovery\n"
1140 "Home Agent preference\n"
4afa50b3 1141 "preference value (default is 0, least preferred)\n")
7cee1bb1 1142{
4afa50b3
DO
1143 struct interface *ifp = (struct interface *) vty->index;
1144 struct zebra_if *zif = ifp->info;
1145 VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[0], 0, 65535);
7cee1bb1 1146 return CMD_SUCCESS;
1147}
1148
1149DEFUN (no_ipv6_nd_homeagent_preference,
1150 no_ipv6_nd_homeagent_preference_cmd,
1151 "no ipv6 nd home-agent-preference",
1152 NO_STR
1153 "Interface IPv6 config commands\n"
1154 "Neighbor discovery\n"
1155 "Home Agent preference\n")
1156{
1157 struct interface *ifp;
1158 struct zebra_if *zif;
1159
1160 ifp = (struct interface *) vty->index;
1161 zif = ifp->info;
1162
1163 zif->rtadv.HomeAgentPreference = 0;
1164
1165 return CMD_SUCCESS;
1166}
1167
4afa50b3
DO
1168ALIAS (no_ipv6_nd_homeagent_preference,
1169 no_ipv6_nd_homeagent_preference_val_cmd,
1170 "no ipv6 nd home-agent-preference <0-65535>",
1171 NO_STR
1172 "Interface IPv6 config commands\n"
1173 "Neighbor discovery\n"
1174 "Home Agent preference\n"
1175 "preference value (default is 0, least preferred)\n")
1176
7cee1bb1 1177DEFUN (ipv6_nd_homeagent_lifetime,
1178 ipv6_nd_homeagent_lifetime_cmd,
4afa50b3 1179 "ipv6 nd home-agent-lifetime <0-65520>",
7cee1bb1 1180 "Interface IPv6 config commands\n"
1181 "Neighbor discovery\n"
1182 "Home Agent lifetime\n"
4afa50b3 1183 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
7cee1bb1 1184{
4afa50b3
DO
1185 struct interface *ifp = (struct interface *) vty->index;
1186 struct zebra_if *zif = ifp->info;
1187 VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[0], 0, RTADV_MAX_HALIFETIME);
7cee1bb1 1188 return CMD_SUCCESS;
1189}
1190
1191DEFUN (no_ipv6_nd_homeagent_lifetime,
1192 no_ipv6_nd_homeagent_lifetime_cmd,
1193 "no ipv6 nd home-agent-lifetime",
1194 NO_STR
1195 "Interface IPv6 config commands\n"
1196 "Neighbor discovery\n"
1197 "Home Agent lifetime\n")
1198{
1199 struct interface *ifp;
1200 struct zebra_if *zif;
1201
1202 ifp = (struct interface *) vty->index;
1203 zif = ifp->info;
1204
d660f698 1205 zif->rtadv.HomeAgentLifetime = -1;
7cee1bb1 1206
1207 return CMD_SUCCESS;
1208}
1209
4afa50b3
DO
1210ALIAS (no_ipv6_nd_homeagent_lifetime,
1211 no_ipv6_nd_homeagent_lifetime_val_cmd,
1212 "no ipv6 nd home-agent-lifetime <0-65520>",
1213 NO_STR
1214 "Interface IPv6 config commands\n"
1215 "Neighbor discovery\n"
1216 "Home Agent lifetime\n"
1217 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1218
718e3744 1219DEFUN (ipv6_nd_managed_config_flag,
1220 ipv6_nd_managed_config_flag_cmd,
1221 "ipv6 nd managed-config-flag",
3e31cded 1222 "Interface IPv6 config commands\n"
718e3744 1223 "Neighbor discovery\n"
1224 "Managed address configuration flag\n")
1225{
1226 struct interface *ifp;
1227 struct zebra_if *zif;
1228
1229 ifp = (struct interface *) vty->index;
1230 zif = ifp->info;
1231
1232 zif->rtadv.AdvManagedFlag = 1;
1233
1234 return CMD_SUCCESS;
1235}
1236
1237DEFUN (no_ipv6_nd_managed_config_flag,
1238 no_ipv6_nd_managed_config_flag_cmd,
1239 "no ipv6 nd managed-config-flag",
1240 NO_STR
3e31cded 1241 "Interface IPv6 config commands\n"
718e3744 1242 "Neighbor discovery\n"
1243 "Managed address configuration flag\n")
1244{
1245 struct interface *ifp;
1246 struct zebra_if *zif;
1247
1248 ifp = (struct interface *) vty->index;
1249 zif = ifp->info;
1250
1251 zif->rtadv.AdvManagedFlag = 0;
1252
1253 return CMD_SUCCESS;
1254}
1255
7cee1bb1 1256DEFUN (ipv6_nd_homeagent_config_flag,
1257 ipv6_nd_homeagent_config_flag_cmd,
1258 "ipv6 nd home-agent-config-flag",
1259 "Interface IPv6 config commands\n"
1260 "Neighbor discovery\n"
1261 "Home Agent configuration flag\n")
1262{
1263 struct interface *ifp;
1264 struct zebra_if *zif;
1265
1266 ifp = (struct interface *) vty->index;
1267 zif = ifp->info;
1268
1269 zif->rtadv.AdvHomeAgentFlag = 1;
1270
1271 return CMD_SUCCESS;
1272}
1273
1274DEFUN (no_ipv6_nd_homeagent_config_flag,
1275 no_ipv6_nd_homeagent_config_flag_cmd,
1276 "no ipv6 nd home-agent-config-flag",
1277 NO_STR
1278 "Interface IPv6 config commands\n"
1279 "Neighbor discovery\n"
1280 "Home Agent configuration flag\n")
1281{
1282 struct interface *ifp;
1283 struct zebra_if *zif;
1284
1285 ifp = (struct interface *) vty->index;
1286 zif = ifp->info;
1287
1288 zif->rtadv.AdvHomeAgentFlag = 0;
1289
1290 return CMD_SUCCESS;
1291}
1292
1293DEFUN (ipv6_nd_adv_interval_config_option,
1294 ipv6_nd_adv_interval_config_option_cmd,
1295 "ipv6 nd adv-interval-option",
1296 "Interface IPv6 config commands\n"
1297 "Neighbor discovery\n"
1298 "Advertisement Interval Option\n")
1299{
1300 struct interface *ifp;
1301 struct zebra_if *zif;
1302
1303 ifp = (struct interface *) vty->index;
1304 zif = ifp->info;
1305
1306 zif->rtadv.AdvIntervalOption = 1;
1307
1308 return CMD_SUCCESS;
1309}
1310
1311DEFUN (no_ipv6_nd_adv_interval_config_option,
1312 no_ipv6_nd_adv_interval_config_option_cmd,
1313 "no ipv6 nd adv-interval-option",
1314 NO_STR
1315 "Interface IPv6 config commands\n"
1316 "Neighbor discovery\n"
1317 "Advertisement Interval Option\n")
1318{
1319 struct interface *ifp;
1320 struct zebra_if *zif;
1321
1322 ifp = (struct interface *) vty->index;
1323 zif = ifp->info;
1324
1325 zif->rtadv.AdvIntervalOption = 0;
1326
1327 return CMD_SUCCESS;
1328}
1329
718e3744 1330DEFUN (ipv6_nd_other_config_flag,
1331 ipv6_nd_other_config_flag_cmd,
1332 "ipv6 nd other-config-flag",
3e31cded 1333 "Interface IPv6 config commands\n"
718e3744 1334 "Neighbor discovery\n"
1335 "Other statefull configuration flag\n")
1336{
1337 struct interface *ifp;
1338 struct zebra_if *zif;
1339
1340 ifp = (struct interface *) vty->index;
1341 zif = ifp->info;
1342
1343 zif->rtadv.AdvOtherConfigFlag = 1;
1344
1345 return CMD_SUCCESS;
1346}
1347
1348DEFUN (no_ipv6_nd_other_config_flag,
1349 no_ipv6_nd_other_config_flag_cmd,
1350 "no ipv6 nd other-config-flag",
1351 NO_STR
3e31cded 1352 "Interface IPv6 config commands\n"
718e3744 1353 "Neighbor discovery\n"
1354 "Other statefull configuration flag\n")
1355{
1356 struct interface *ifp;
1357 struct zebra_if *zif;
1358
1359 ifp = (struct interface *) vty->index;
1360 zif = ifp->info;
1361
1362 zif->rtadv.AdvOtherConfigFlag = 0;
1363
1364 return CMD_SUCCESS;
1365}
1366
3e31cded 1367DEFUN (ipv6_nd_prefix,
1368 ipv6_nd_prefix_cmd,
1369 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
7cee1bb1 1370 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
3e31cded 1371 "Interface IPv6 config commands\n"
718e3744 1372 "Neighbor discovery\n"
1373 "Prefix information\n"
1374 "IPv6 prefix\n"
1375 "Valid lifetime in seconds\n"
3e31cded 1376 "Infinite valid lifetime\n"
718e3744 1377 "Preferred lifetime in seconds\n"
3e31cded 1378 "Infinite preferred lifetime\n"
1379 "Do not use prefix for onlink determination\n"
7cee1bb1 1380 "Do not use prefix for autoconfiguration\n"
1381 "Set Router Address flag\n")
718e3744 1382{
1383 int i;
1384 int ret;
3e31cded 1385 int cursor = 1;
718e3744 1386 struct interface *ifp;
1387 struct zebra_if *zebra_if;
1388 struct rtadv_prefix rp;
1389
1390 ifp = (struct interface *) vty->index;
1391 zebra_if = ifp->info;
1392
aca43b65 1393 ret = str2prefix_ipv6 (argv[0], &rp.prefix);
718e3744 1394 if (!ret)
1395 {
1396 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1397 return CMD_WARNING;
1398 }
6bb1273e 1399 apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
3e31cded 1400 rp.AdvOnLinkFlag = 1;
1401 rp.AdvAutonomousFlag = 1;
7cee1bb1 1402 rp.AdvRouterAddressFlag = 0;
3e31cded 1403 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1404 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
718e3744 1405
3e31cded 1406 if (argc > 1)
718e3744 1407 {
27b87393
DL
1408 if ((isdigit((unsigned char)argv[1][0]))
1409 || strncmp (argv[1], "i", 1) == 0)
718e3744 1410 {
3e31cded 1411 if ( strncmp (argv[1], "i", 1) == 0)
1412 rp.AdvValidLifetime = UINT32_MAX;
1413 else
1414 rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
1415 (char **)NULL, 10);
1416
1417 if ( strncmp (argv[2], "i", 1) == 0)
1418 rp.AdvPreferredLifetime = UINT32_MAX;
1419 else
1420 rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
1421 (char **)NULL, 10);
1422
1423 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
1424 {
1425 vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
1426 return CMD_WARNING;
1427 }
1428 cursor = cursor + 2;
718e3744 1429 }
3e31cded 1430 if (argc > cursor)
718e3744 1431 {
3e31cded 1432 for (i = cursor; i < argc; i++)
1433 {
1434 if (strncmp (argv[i], "of", 2) == 0)
1435 rp.AdvOnLinkFlag = 0;
1436 if (strncmp (argv[i], "no", 2) == 0)
1437 rp.AdvAutonomousFlag = 0;
7cee1bb1 1438 if (strncmp (argv[i], "ro", 2) == 0)
1439 rp.AdvRouterAddressFlag = 1;
3e31cded 1440 }
718e3744 1441 }
1442 }
1443
1444 rtadv_prefix_set (zebra_if, &rp);
1445
1446 return CMD_SUCCESS;
1447}
1448
7cee1bb1 1449ALIAS (ipv6_nd_prefix,
1450 ipv6_nd_prefix_val_nortaddr_cmd,
1451 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1452 "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
1453 "Interface IPv6 config commands\n"
1454 "Neighbor discovery\n"
1455 "Prefix information\n"
1456 "IPv6 prefix\n"
1457 "Valid lifetime in seconds\n"
1458 "Infinite valid lifetime\n"
1459 "Preferred lifetime in seconds\n"
1460 "Infinite preferred lifetime\n"
1461 "Do not use prefix for onlink determination\n"
1462 "Do not use prefix for autoconfiguration\n")
1463
3e31cded 1464ALIAS (ipv6_nd_prefix,
1465 ipv6_nd_prefix_val_rev_cmd,
1466 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1467 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1468 "Interface IPv6 config commands\n"
1469 "Neighbor discovery\n"
1470 "Prefix information\n"
1471 "IPv6 prefix\n"
1472 "Valid lifetime in seconds\n"
1473 "Infinite valid lifetime\n"
1474 "Preferred lifetime in seconds\n"
1475 "Infinite preferred lifetime\n"
1476 "Do not use prefix for autoconfiguration\n"
1477 "Do not use prefix for onlink determination\n")
1478
7cee1bb1 1479ALIAS (ipv6_nd_prefix,
1480 ipv6_nd_prefix_val_rev_rtaddr_cmd,
1481 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1482 "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1483 "Interface IPv6 config commands\n"
1484 "Neighbor discovery\n"
1485 "Prefix information\n"
1486 "IPv6 prefix\n"
1487 "Valid lifetime in seconds\n"
1488 "Infinite valid lifetime\n"
1489 "Preferred lifetime in seconds\n"
1490 "Infinite preferred lifetime\n"
1491 "Do not use prefix for autoconfiguration\n"
1492 "Do not use prefix for onlink determination\n"
1493 "Set Router Address flag\n")
1494
3e31cded 1495ALIAS (ipv6_nd_prefix,
1496 ipv6_nd_prefix_val_noauto_cmd,
1497 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1498 "(<0-4294967295>|infinite) (no-autoconfig|)",
1499 "Interface IPv6 config commands\n"
1500 "Neighbor discovery\n"
1501 "Prefix information\n"
1502 "IPv6 prefix\n"
1503 "Valid lifetime in seconds\n"
1504 "Infinite valid lifetime\n"
1505 "Preferred lifetime in seconds\n"
1506 "Infinite preferred lifetime\n"
7cee1bb1 1507 "Do not use prefix for autoconfiguration")
3e31cded 1508
1509ALIAS (ipv6_nd_prefix,
1510 ipv6_nd_prefix_val_offlink_cmd,
1511 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1512 "(<0-4294967295>|infinite) (off-link|)",
1513 "Interface IPv6 config commands\n"
1514 "Neighbor discovery\n"
1515 "Prefix information\n"
1516 "IPv6 prefix\n"
1517 "Valid lifetime in seconds\n"
1518 "Infinite valid lifetime\n"
1519 "Preferred lifetime in seconds\n"
1520 "Infinite preferred lifetime\n"
1521 "Do not use prefix for onlink determination\n")
1522
7cee1bb1 1523ALIAS (ipv6_nd_prefix,
1524 ipv6_nd_prefix_val_rtaddr_cmd,
1525 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1526 "(<0-4294967295>|infinite) (router-address|)",
1527 "Interface IPv6 config commands\n"
1528 "Neighbor discovery\n"
1529 "Prefix information\n"
1530 "IPv6 prefix\n"
1531 "Valid lifetime in seconds\n"
1532 "Infinite valid lifetime\n"
1533 "Preferred lifetime in seconds\n"
1534 "Infinite preferred lifetime\n"
1535 "Set Router Address flag\n")
1536
3e31cded 1537ALIAS (ipv6_nd_prefix,
1538 ipv6_nd_prefix_val_cmd,
1539 "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
1540 "(<0-4294967295>|infinite)",
1541 "Interface IPv6 config commands\n"
1542 "Neighbor discovery\n"
1543 "Prefix information\n"
1544 "IPv6 prefix\n"
1545 "Valid lifetime in seconds\n"
1546 "Infinite valid lifetime\n"
1547 "Preferred lifetime in seconds\n"
1548 "Infinite preferred lifetime\n")
1549
1550ALIAS (ipv6_nd_prefix,
1551 ipv6_nd_prefix_noval_cmd,
1552 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1553 "Interface IPv6 config commands\n"
1554 "Neighbor discovery\n"
1555 "Prefix information\n"
1556 "IPv6 prefix\n"
1557 "Do not use prefix for autoconfiguration\n"
1558 "Do not use prefix for onlink determination\n")
1559
1560ALIAS (ipv6_nd_prefix,
1561 ipv6_nd_prefix_noval_rev_cmd,
1562 "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1563 "Interface IPv6 config commands\n"
1564 "Neighbor discovery\n"
1565 "Prefix information\n"
1566 "IPv6 prefix\n"
1567 "Do not use prefix for onlink determination\n"
1568 "Do not use prefix for autoconfiguration\n")
1569
1570ALIAS (ipv6_nd_prefix,
1571 ipv6_nd_prefix_noval_noauto_cmd,
1572 "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1573 "Interface IPv6 config commands\n"
1574 "Neighbor discovery\n"
1575 "Prefix information\n"
1576 "IPv6 prefix\n"
1577 "Do not use prefix for autoconfiguration\n")
1578
1579ALIAS (ipv6_nd_prefix,
1580 ipv6_nd_prefix_noval_offlink_cmd,
1581 "ipv6 nd prefix X:X::X:X/M (off-link|)",
1582 "Interface IPv6 config commands\n"
1583 "Neighbor discovery\n"
1584 "Prefix information\n"
1585 "IPv6 prefix\n"
1586 "Do not use prefix for onlink determination\n")
1587
7cee1bb1 1588ALIAS (ipv6_nd_prefix,
1589 ipv6_nd_prefix_noval_rtaddr_cmd,
1590 "ipv6 nd prefix X:X::X:X/M (router-address|)",
1591 "Interface IPv6 config commands\n"
1592 "Neighbor discovery\n"
1593 "Prefix information\n"
1594 "IPv6 prefix\n"
1595 "Set Router Address flag\n")
1596
3e31cded 1597ALIAS (ipv6_nd_prefix,
1598 ipv6_nd_prefix_prefix_cmd,
1599 "ipv6 nd prefix X:X::X:X/M",
1600 "Interface IPv6 config commands\n"
718e3744 1601 "Neighbor discovery\n"
1602 "Prefix information\n"
1603 "IPv6 prefix\n")
1604
3e31cded 1605DEFUN (no_ipv6_nd_prefix,
1606 no_ipv6_nd_prefix_cmd,
1607 "no ipv6 nd prefix IPV6PREFIX",
718e3744 1608 NO_STR
3e31cded 1609 "Interface IPv6 config commands\n"
718e3744 1610 "Neighbor discovery\n"
1611 "Prefix information\n"
1612 "IPv6 prefix\n")
1613{
1614 int ret;
1615 struct interface *ifp;
1616 struct zebra_if *zebra_if;
1617 struct rtadv_prefix rp;
1618
1619 ifp = (struct interface *) vty->index;
1620 zebra_if = ifp->info;
1621
aca43b65 1622 ret = str2prefix_ipv6 (argv[0], &rp.prefix);
718e3744 1623 if (!ret)
1624 {
1625 vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
1626 return CMD_WARNING;
1627 }
6bb1273e 1628 apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
718e3744 1629
1630 ret = rtadv_prefix_reset (zebra_if, &rp);
1631 if (!ret)
1632 {
1633 vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
1634 return CMD_WARNING;
1635 }
1636
1637 return CMD_SUCCESS;
1638}
b60668d0 1639
813d4307
DW
1640ALIAS (no_ipv6_nd_prefix,
1641 no_ipv6_nd_prefix_val_nortaddr_cmd,
1642 "no ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) (<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
1643 NO_STR
1644 "Interface IPv6 config commands\n"
1645 "Neighbor discovery\n"
1646 "Prefix information\n"
1647 "IPv6 prefix\n"
1648 "Valid lifetime in seconds\n"
1649 "Infinite valid lifetime\n"
1650 "Preferred lifetime in seconds\n"
1651 "Infinite preferred lifetime\n"
1652 "Do not use prefix for onlink determination\n"
1653 "Do not use prefix for autoconfiguration\n"
1654 "Set Router Address flag\n")
1655
1656ALIAS (no_ipv6_nd_prefix,
1657 no_ipv6_nd_prefix_val_rev_cmd,
1658 "no ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) (<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
1659 NO_STR
1660 "Interface IPv6 config commands\n"
1661 "Neighbor discovery\n"
1662 "Prefix information\n"
1663 "IPv6 prefix\n"
1664 "Valid lifetime in seconds\n"
1665 "Infinite valid lifetime\n"
1666 "Preferred lifetime in seconds\n"
1667 "Infinite preferred lifetime\n"
1668 "Do not use prefix for autoconfiguration\n"
1669 "Do not use prefix for onlink determination\n")
1670
1671ALIAS (no_ipv6_nd_prefix,
1672 no_ipv6_nd_prefix_val_rev_rtaddr_cmd,
1673 "no ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) (<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
1674 NO_STR
1675 "Interface IPv6 config commands\n"
1676 "Neighbor discovery\n"
1677 "Prefix information\n"
1678 "IPv6 prefix\n"
1679 "Valid lifetime in seconds\n"
1680 "Infinite valid lifetime\n"
1681 "Preferred lifetime in seconds\n"
1682 "Infinite preferred lifetime\n"
1683 "Do not use prefix for autoconfiguration\n"
1684 "Do not use prefix for onlink determination\n"
1685 "Set Router Address flag\n")
1686
1687ALIAS (no_ipv6_nd_prefix,
1688 no_ipv6_nd_prefix_val_noauto_cmd,
1689 "no ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) (<0-4294967295>|infinite) (no-autoconfig|)",
1690 NO_STR
1691 "Interface IPv6 config commands\n"
1692 "Neighbor discovery\n"
1693 "Prefix information\n"
1694 "IPv6 prefix\n"
1695 "Valid lifetime in seconds\n"
1696 "Infinite valid lifetime\n"
1697 "Preferred lifetime in seconds\n"
1698 "Infinite preferred lifetime\n"
1699 "Do not use prefix for autoconfiguration")
1700
1701ALIAS (no_ipv6_nd_prefix,
1702 no_ipv6_nd_prefix_val_offlink_cmd,
1703 "no ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) (<0-4294967295>|infinite) (off-link|)",
1704 NO_STR
1705 "Interface IPv6 config commands\n"
1706 "Neighbor discovery\n"
1707 "Prefix information\n"
1708 "IPv6 prefix\n"
1709 "Valid lifetime in seconds\n"
1710 "Infinite valid lifetime\n"
1711 "Preferred lifetime in seconds\n"
1712 "Infinite preferred lifetime\n"
1713 "Do not use prefix for onlink determination\n")
1714
1715ALIAS (no_ipv6_nd_prefix,
1716 no_ipv6_nd_prefix_val_rtaddr_cmd,
1717 "no ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) (<0-4294967295>|infinite) (router-address|)",
1718 NO_STR
1719 "Interface IPv6 config commands\n"
1720 "Neighbor discovery\n"
1721 "Prefix information\n"
1722 "IPv6 prefix\n"
1723 "Valid lifetime in seconds\n"
1724 "Infinite valid lifetime\n"
1725 "Preferred lifetime in seconds\n"
1726 "Infinite preferred lifetime\n"
1727 "Set Router Address flag\n")
1728
1729ALIAS (no_ipv6_nd_prefix,
1730 no_ipv6_nd_prefix_val_cmd,
1731 "no ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) (<0-4294967295>|infinite)",
1732 NO_STR
1733 "Interface IPv6 config commands\n"
1734 "Neighbor discovery\n"
1735 "Prefix information\n"
1736 "IPv6 prefix\n"
1737 "Valid lifetime in seconds\n"
1738 "Infinite valid lifetime\n"
1739 "Preferred lifetime in seconds\n"
1740 "Infinite preferred lifetime\n")
1741
1742ALIAS (no_ipv6_nd_prefix,
1743 no_ipv6_nd_prefix_noval_cmd,
1744 "no ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
1745 NO_STR
1746 "Interface IPv6 config commands\n"
1747 "Neighbor discovery\n"
1748 "Prefix information\n"
1749 "IPv6 prefix\n"
1750 "Do not use prefix for autoconfiguration\n"
1751 "Do not use prefix for onlink determination\n")
1752
1753ALIAS (no_ipv6_nd_prefix,
1754 no_ipv6_nd_prefix_noval_rev_cmd,
1755 "no ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
1756 NO_STR
1757 "Interface IPv6 config commands\n"
1758 "Neighbor discovery\n"
1759 "Prefix information\n"
1760 "IPv6 prefix\n"
1761 "Do not use prefix for onlink determination\n"
1762 "Do not use prefix for autoconfiguration\n")
1763
1764ALIAS (no_ipv6_nd_prefix,
1765 no_ipv6_nd_prefix_noval_noauto_cmd,
1766 "no ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
1767 NO_STR
1768 "Interface IPv6 config commands\n"
1769 "Neighbor discovery\n"
1770 "Prefix information\n"
1771 "IPv6 prefix\n"
1772 "Do not use prefix for autoconfiguration\n")
1773
1774ALIAS (no_ipv6_nd_prefix,
1775 no_ipv6_nd_prefix_noval_offlink_cmd,
1776 "no ipv6 nd prefix X:X::X:X/M (off-link|)",
1777 NO_STR
1778 "Interface IPv6 config commands\n"
1779 "Neighbor discovery\n"
1780 "Prefix information\n"
1781 "IPv6 prefix\n"
1782 "Do not use prefix for onlink determination\n")
1783
1784ALIAS (no_ipv6_nd_prefix,
1785 no_ipv6_nd_prefix_noval_rtaddr_cmd,
1786 "no ipv6 nd prefix X:X::X:X/M (router-address|)",
1787 NO_STR
1788 "Interface IPv6 config commands\n"
1789 "Neighbor discovery\n"
1790 "Prefix information\n"
1791 "IPv6 prefix\n"
1792 "Set Router Address flag\n")
1793
b60668d0
CC
1794DEFUN (ipv6_nd_router_preference,
1795 ipv6_nd_router_preference_cmd,
1796 "ipv6 nd router-preference (high|medium|low)",
1797 "Interface IPv6 config commands\n"
1798 "Neighbor discovery\n"
1799 "Default router preference\n"
1800 "High default router preference\n"
1801 "Low default router preference\n"
1802 "Medium default router preference (default)\n")
1803{
1804 struct interface *ifp;
1805 struct zebra_if *zif;
1806 int i = 0;
1807
1808 ifp = (struct interface *) vty->index;
1809 zif = ifp->info;
1810
1811 while (0 != rtadv_pref_strs[i])
1812 {
1813 if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
1814 {
1815 zif->rtadv.DefaultPreference = i;
1816 return CMD_SUCCESS;
1817 }
1818 i++;
1819 }
1820
1821 return CMD_ERR_NO_MATCH;
1822}
1823
1824DEFUN (no_ipv6_nd_router_preference,
1825 no_ipv6_nd_router_preference_cmd,
1826 "no ipv6 nd router-preference",
1827 NO_STR
1828 "Interface IPv6 config commands\n"
1829 "Neighbor discovery\n"
1830 "Default router preference\n")
1831{
1832 struct interface *ifp;
1833 struct zebra_if *zif;
1834
1835 ifp = (struct interface *) vty->index;
1836 zif = ifp->info;
1837
1838 zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1839
1840 return CMD_SUCCESS;
1841}
1842
4afa50b3
DO
1843ALIAS (no_ipv6_nd_router_preference,
1844 no_ipv6_nd_router_preference_val_cmd,
2b00515a 1845 "no ipv6 nd router-preference (high|medium|low)",
4afa50b3
DO
1846 NO_STR
1847 "Interface IPv6 config commands\n"
1848 "Neighbor discovery\n"
1849 "Default router preference\n"
1850 "High default router preference\n"
1851 "Low default router preference\n"
1852 "Medium default router preference (default)\n")
1853
6ae93c05
DO
1854DEFUN (ipv6_nd_mtu,
1855 ipv6_nd_mtu_cmd,
1856 "ipv6 nd mtu <1-65535>",
1857 "Interface IPv6 config commands\n"
1858 "Neighbor discovery\n"
1859 "Advertised MTU\n"
1860 "MTU in bytes\n")
1861{
1862 struct interface *ifp = (struct interface *) vty->index;
1863 struct zebra_if *zif = ifp->info;
1864 VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
1865 return CMD_SUCCESS;
1866}
1867
1868DEFUN (no_ipv6_nd_mtu,
1869 no_ipv6_nd_mtu_cmd,
1870 "no ipv6 nd mtu",
1871 NO_STR
1872 "Interface IPv6 config commands\n"
1873 "Neighbor discovery\n"
1874 "Advertised MTU\n")
1875{
1876 struct interface *ifp = (struct interface *) vty->index;
1877 struct zebra_if *zif = ifp->info;
1878 zif->rtadv.AdvLinkMTU = 0;
1879 return CMD_SUCCESS;
1880}
1881
1882ALIAS (no_ipv6_nd_mtu,
1883 no_ipv6_nd_mtu_val_cmd,
1884 "no ipv6 nd mtu <1-65535>",
1885 NO_STR
1886 "Interface IPv6 config commands\n"
1887 "Neighbor discovery\n"
1888 "Advertised MTU\n"
1889 "MTU in bytes\n")
1890
718e3744 1891/* Write configuration about router advertisement. */
1892void
1893rtadv_config_write (struct vty *vty, struct interface *ifp)
1894{
1895 struct zebra_if *zif;
52dc7ee6 1896 struct listnode *node;
718e3744 1897 struct rtadv_prefix *rprefix;
35d921cc 1898 char buf[PREFIX_STRLEN];
7cee1bb1 1899 int interval;
718e3744 1900
718e3744 1901 zif = ifp->info;
1902
c23af4d3 1903 if (!(if_is_loopback (ifp) ||
1904 CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)))
718e3744 1905 {
c5b37afc 1906 if (zif->rtadv.AdvSendAdvertisements)
1907 vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
718e3744 1908 }
7cee1bb1 1909
1910 interval = zif->rtadv.MaxRtrAdvInterval;
1911 if (interval % 1000)
1912 vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
1913 VTY_NEWLINE);
1914 else
1915 if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
1916 vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
718e3744 1917 VTY_NEWLINE);
1918
6134b875
DO
1919 if (zif->rtadv.AdvIntervalOption)
1920 vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE);
1921
d660f698 1922 if (zif->rtadv.AdvDefaultLifetime != -1)
718e3744 1923 vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
1924 VTY_NEWLINE);
1925
6134b875
DO
1926 if (zif->rtadv.HomeAgentPreference)
1927 vty_out (vty, " ipv6 nd home-agent-preference %u%s",
1928 zif->rtadv.HomeAgentPreference, VTY_NEWLINE);
1929
d660f698 1930 if (zif->rtadv.HomeAgentLifetime != -1)
6134b875
DO
1931 vty_out (vty, " ipv6 nd home-agent-lifetime %u%s",
1932 zif->rtadv.HomeAgentLifetime, VTY_NEWLINE);
1933
1934 if (zif->rtadv.AdvHomeAgentFlag)
1935 vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE);
1936
718e3744 1937 if (zif->rtadv.AdvReachableTime)
1938 vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
1939 VTY_NEWLINE);
1940
1941 if (zif->rtadv.AdvManagedFlag)
1942 vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
1943
1944 if (zif->rtadv.AdvOtherConfigFlag)
1945 vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
1946
b60668d0
CC
1947 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
1948 vty_out (vty, " ipv6 nd router-preference %s%s",
1949 rtadv_pref_strs[zif->rtadv.DefaultPreference],
1950 VTY_NEWLINE);
1951
6ae93c05
DO
1952 if (zif->rtadv.AdvLinkMTU)
1953 vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
1954
1eb8ef25 1955 for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
718e3744 1956 {
35d921cc
TT
1957 vty_out (vty, " ipv6 nd prefix %s",
1958 prefix2str (&rprefix->prefix, buf, sizeof(buf)));
3e31cded 1959 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
1960 (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
1961 {
1962 if (rprefix->AdvValidLifetime == UINT32_MAX)
1963 vty_out (vty, " infinite");
1964 else
1965 vty_out (vty, " %u", rprefix->AdvValidLifetime);
1966 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
1967 vty_out (vty, " infinite");
1968 else
1969 vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
1970 }
1971 if (!rprefix->AdvOnLinkFlag)
1972 vty_out (vty, " off-link");
1973 if (!rprefix->AdvAutonomousFlag)
1974 vty_out (vty, " no-autoconfig");
7cee1bb1 1975 if (rprefix->AdvRouterAddressFlag)
1976 vty_out (vty, " router-address");
718e3744 1977 vty_out (vty, "%s", VTY_NEWLINE);
1978 }
1979}
1980
718e3744 1981
a1ac18c4 1982static void
43459b1f 1983rtadv_event (struct zebra_ns *zns, enum rtadv_event event, int val)
718e3744 1984{
43459b1f 1985 struct rtadv *rtadv = &zns->rtadv;
cd80d74f 1986
718e3744 1987 switch (event)
1988 {
1989 case RTADV_START:
1990 if (! rtadv->ra_read)
6c9678b4 1991 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zns, val);
718e3744 1992 if (! rtadv->ra_timer)
6c9678b4
DD
1993 rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
1994 zns, 0);
718e3744 1995 break;
1996 case RTADV_STOP:
1997 if (rtadv->ra_timer)
1998 {
1999 thread_cancel (rtadv->ra_timer);
2000 rtadv->ra_timer = NULL;
2001 }
2002 if (rtadv->ra_read)
2003 {
2004 thread_cancel (rtadv->ra_read);
2005 rtadv->ra_read = NULL;
2006 }
2007 break;
2008 case RTADV_TIMER:
2009 if (! rtadv->ra_timer)
43459b1f 2010 rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, zns,
3e31cded 2011 val);
718e3744 2012 break;
7cee1bb1 2013 case RTADV_TIMER_MSEC:
2014 if (! rtadv->ra_timer)
2015 rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
43459b1f 2016 zns, val);
7cee1bb1 2017 break;
718e3744 2018 case RTADV_READ:
2019 if (! rtadv->ra_read)
43459b1f 2020 rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zns, val);
718e3744 2021 break;
2022 default:
2023 break;
2024 }
2025 return;
2026}
2027
2028void
43459b1f 2029rtadv_init (struct zebra_ns *zns)
718e3744 2030{
43459b1f 2031 zns->rtadv.sock = rtadv_make_socket ();
cd80d74f 2032}
718e3744 2033
cd80d74f 2034void
43459b1f 2035rtadv_terminate (struct zebra_ns *zns)
cd80d74f 2036{
43459b1f 2037 rtadv_event (zns, RTADV_STOP, 0);
2038 if (zns->rtadv.sock >= 0)
cd80d74f 2039 {
43459b1f 2040 close (zns->rtadv.sock);
2041 zns->rtadv.sock = -1;
cd80d74f 2042 }
718e3744 2043
43459b1f 2044 zns->rtadv.adv_if_count = 0;
2045 zns->rtadv.adv_msec_if_count = 0;
cd80d74f 2046}
718e3744 2047
cd80d74f
FL
2048void
2049rtadv_cmd_init (void)
2050{
718e3744 2051 install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
2052 install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
718e3744 2053 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
7cee1bb1 2054 install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
718e3744 2055 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
4afa50b3
DO
2056 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_val_cmd);
2057 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_msec_val_cmd);
718e3744 2058 install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
2059 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
4afa50b3 2060 install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_val_cmd);
718e3744 2061 install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
2062 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
4afa50b3 2063 install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_val_cmd);
718e3744 2064 install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
2065 install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
2066 install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
2067 install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
7cee1bb1 2068 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
2069 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
2070 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
2071 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
4afa50b3 2072 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_val_cmd);
7cee1bb1 2073 install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
2074 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
4afa50b3 2075 install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_val_cmd);
7cee1bb1 2076 install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
2077 install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
3e31cded 2078 install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
7cee1bb1 2079 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
2080 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
3e31cded 2081 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
2082 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
2083 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
7cee1bb1 2084 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
3e31cded 2085 install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
2086 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
2087 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
2088 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
2089 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
7cee1bb1 2090 install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
3e31cded 2091 install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
2092 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
813d4307
DW
2093 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_val_rev_rtaddr_cmd);
2094 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_val_nortaddr_cmd);
2095 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_val_rev_cmd);
2096 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_val_noauto_cmd);
2097 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_val_offlink_cmd);
2098 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_val_rtaddr_cmd);
2099 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_val_cmd);
2100 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_noval_cmd);
2101 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_noval_rev_cmd);
2102 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_noval_noauto_cmd);
2103 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_noval_offlink_cmd);
2104 install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_noval_rtaddr_cmd);
b60668d0
CC
2105 install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
2106 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
4afa50b3 2107 install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_val_cmd);
6ae93c05
DO
2108 install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
2109 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
2110 install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
718e3744 2111}
2112
a1ac18c4 2113static int
718e3744 2114if_join_all_router (int sock, struct interface *ifp)
2115{
2116 int ret;
2117
2118 struct ipv6_mreq mreq;
2119
2120 memset (&mreq, 0, sizeof (struct ipv6_mreq));
2121 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2122 mreq.ipv6mr_interface = ifp->ifindex;
2123
2124 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
2125 (char *) &mreq, sizeof mreq);
2126 if (ret < 0)
f360eac0 2127 zlog_warn ("%s(%u): Failed to join group, socket %u error %s",
2128 ifp->name, ifp->ifindex, sock, safe_strerror (errno));
718e3744 2129
f360eac0 2130 if (IS_ZEBRA_DEBUG_EVENT)
2131 zlog_debug ("%s(%u): Join All-Routers multicast group, socket %u",
2132 ifp->name, ifp->ifindex, sock);
718e3744 2133
2134 return 0;
2135}
2136
a1ac18c4 2137static int
718e3744 2138if_leave_all_router (int sock, struct interface *ifp)
2139{
2140 int ret;
2141
2142 struct ipv6_mreq mreq;
2143
2144 memset (&mreq, 0, sizeof (struct ipv6_mreq));
2145 inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2146 mreq.ipv6mr_interface = ifp->ifindex;
2147
2148 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
2149 (char *) &mreq, sizeof mreq);
2150 if (ret < 0)
f360eac0 2151 zlog_warn ("%s(%u): Failed to leave group, socket %u error %s",
2152 ifp->name, ifp->ifindex, sock,safe_strerror (errno));
718e3744 2153
f360eac0 2154 if (IS_ZEBRA_DEBUG_EVENT)
2155 zlog_debug ("%s(%u): Leave All-Routers multicast group, socket %u",
2156 ifp->name, ifp->ifindex, sock);
718e3744 2157
2158 return 0;
2159}
2160
2161#else
2162void
43459b1f 2163rtadv_init (struct zebra_ns *zns)
cd80d74f
FL
2164{
2165 /* Empty.*/;
2166}
2167void
43459b1f 2168rtadv_terminate (struct zebra_ns *zns)
cd80d74f
FL
2169{
2170 /* Empty.*/;
2171}
2172void
2173rtadv_cmd_init (void)
718e3744 2174{
2175 /* Empty.*/;
2176}
8da4e946 2177#endif /* HAVE_RTADV && HAVE_IPV6 */