]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rtadv.c
Merge pull request #8593 from idryzhov/cmd-ambiguous
[mirror_frr.git] / zebra / rtadv.c
CommitLineData
718e3744 1/* Router advertisement
34ccea1e 2 * Copyright (C) 2016 Cumulus Networks
7cee1bb1 3 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
718e3744 4 * Copyright (C) 1999 Kunihiro Ishiguro
5 *
6 * This file is part of GNU Zebra.
7 *
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
896014f4
DL
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 21 */
22
23#include <zebra.h>
24
25#include "memory.h"
26#include "sockopt.h"
27#include "thread.h"
28#include "if.h"
4a04e5f7 29#include "stream.h"
718e3744 30#include "log.h"
31#include "prefix.h"
32#include "linklist.h"
33#include "command.h"
edd7c245 34#include "privs.h"
cd80d74f 35#include "vrf.h"
fe533c56 36#include "ns.h"
43e52561 37#include "lib_errors.h"
718e3744 38
39#include "zebra/interface.h"
40#include "zebra/rtadv.h"
41#include "zebra/debug.h"
537d8ea9 42#include "zebra/rib.h"
bf094f69 43#include "zebra/zapi_msg.h"
7c551956 44#include "zebra/zebra_vrf.h"
364fed6b 45#include "zebra/zebra_errors.h"
a3be9fa1 46#include "zebra/zebra_router.h"
718e3744 47
edd7c245 48extern struct zebra_privs_t zserv_privs;
49
d62a17ae 50#if defined(HAVE_RTADV)
718e3744 51
d3f604f0
DS
52#ifndef VTYSH_EXTRACT_PL
53#include "zebra/rtadv_clippy.c"
54#endif
55
bf8d3d6a 56DEFINE_MTYPE_STATIC(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix");
c1344b54 57
fa2b17e3 58#ifdef OPEN_BSD
59#include <netinet/icmp6.h>
60#endif
61
718e3744 62/* If RFC2133 definition is used. */
63#ifndef IPV6_JOIN_GROUP
c258527b 64#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
718e3744 65#endif
66#ifndef IPV6_LEAVE_GROUP
c258527b 67#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
718e3744 68#endif
69
70#define ALLNODE "ff02::1"
71#define ALLROUTER "ff02::2"
72
bf8d3d6a
DL
73DEFINE_MTYPE_STATIC(ZEBRA, RTADV_RDNSS, "Router Advertisement RDNSS");
74DEFINE_MTYPE_STATIC(ZEBRA, RTADV_DNSSL, "Router Advertisement DNSSL");
110765e3 75
2eb27eec
DL
76/* Order is intentional. Matches RFC4191. This array is also used for
77 command matching, so only modify with care. */
2b64873d
DL
78static const char *const rtadv_pref_strs[] = {
79 "medium", "high", "INVALID", "low", 0
80};
2eb27eec 81
d62a17ae 82enum rtadv_event {
83 RTADV_START,
84 RTADV_STOP,
85 RTADV_TIMER,
86 RTADV_TIMER_MSEC,
87 RTADV_READ
88};
718e3744 89
df9c8c57 90static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int);
718e3744 91
d62a17ae 92static int if_join_all_router(int, struct interface *);
93static int if_leave_all_router(int, struct interface *);
6b0655a2 94
9245fe61
PG
95static int rtadv_get_socket(struct zebra_vrf *zvrf)
96{
97 if (zvrf->rtadv.sock > 0)
98 return zvrf->rtadv.sock;
99 return zrouter.rtadv_sock;
100}
101
df9c8c57 102static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
911ad1e2 103{
d62a17ae 104 int ret = -1;
105 struct interface *iface;
106 struct zebra_if *zif;
107
df9c8c57 108 iface = if_lookup_by_index(*ifindex, zvrf->vrf->vrf_id);
d62a17ae 109 if (iface && iface->info) {
110 zif = iface->info;
111 zif->ra_rcvd++;
112 ret = 0;
113 }
114 return ret;
795b5abf
QY
115}
116
df9c8c57 117static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
d62a17ae 118 int buflen, struct sockaddr_in6 *from,
119 ifindex_t *ifindex, int *hoplimit)
718e3744 120{
d62a17ae 121 int ret;
122 struct msghdr msg;
123 struct iovec iov;
124 struct cmsghdr *cmsgptr;
125 struct in6_addr dst;
126
127 char adata[1024];
128
129 /* Fill in message and iovec. */
0af35d90 130 memset(&msg, 0, sizeof(msg));
d62a17ae 131 msg.msg_name = (void *)from;
132 msg.msg_namelen = sizeof(struct sockaddr_in6);
133 msg.msg_iov = &iov;
134 msg.msg_iovlen = 1;
135 msg.msg_control = (void *)adata;
0d6f7fd6 136 msg.msg_controllen = sizeof(adata);
d62a17ae 137 iov.iov_base = buf;
138 iov.iov_len = buflen;
139
140 /* If recvmsg fail return minus value. */
141 ret = recvmsg(sock, &msg, 0);
142 if (ret < 0)
143 return ret;
144
adf0e7c6 145 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
d62a17ae 146 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
147 /* I want interface index which this packet comes from. */
148 if (cmsgptr->cmsg_level == IPPROTO_IPV6
149 && cmsgptr->cmsg_type == IPV6_PKTINFO) {
150 struct in6_pktinfo *ptr;
151
152 ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
153 *ifindex = ptr->ipi6_ifindex;
154 memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
155 }
156
157 /* Incoming packet's hop limit. */
158 if (cmsgptr->cmsg_level == IPPROTO_IPV6
159 && cmsgptr->cmsg_type == IPV6_HOPLIMIT) {
160 int *hoptr = (int *)CMSG_DATA(cmsgptr);
161 *hoplimit = *hoptr;
162 }
b0b709ab 163 }
795b5abf 164
df9c8c57 165 rtadv_increment_received(zvrf, ifindex);
d62a17ae 166 return ret;
718e3744 167}
168
169#define RTADV_MSG_SIZE 4096
170
171/* Send router advertisement packet. */
d7fc0e67 172static void rtadv_send_packet(int sock, struct interface *ifp,
57dd8642 173 enum ipv6_nd_suppress_ra_status stop)
718e3744 174{
d62a17ae 175 struct msghdr msg;
176 struct iovec iov;
177 struct cmsghdr *cmsgptr;
178 struct in6_pktinfo *pkt;
179 struct sockaddr_in6 addr;
180 static void *adata = NULL;
181 unsigned char buf[RTADV_MSG_SIZE];
182 struct nd_router_advert *rtadv;
183 int ret;
184 int len = 0;
185 struct zebra_if *zif;
186 struct rtadv_prefix *rprefix;
d7c0a89a
QY
187 uint8_t all_nodes_addr[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0, 0, 0, 1};
d62a17ae 189 struct listnode *node;
d7c0a89a 190 uint16_t pkt_RouterLifetime;
d62a17ae 191
192 /*
193 * Allocate control message bufffer. This is dynamic because
194 * CMSG_SPACE is not guaranteed not to call a function. Note that
195 * the size will be different on different architectures due to
196 * differing alignment rules.
197 */
198 if (adata == NULL) {
199 /* XXX Free on shutdown. */
b8aa3767 200 adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
d62a17ae 201
b8aa3767 202 if (adata == NULL) {
9df414fe 203 zlog_debug(
d62a17ae 204 "rtadv_send_packet: can't malloc control data");
b8aa3767
DS
205 exit(-1);
206 }
d62a17ae 207 }
208
209 /* Logging of packet. */
60077146
DS
210 if (IS_ZEBRA_DEBUG_PACKET) {
211 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
212
213 zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp->name,
214 VRF_LOGNAME(vrf), ifp->ifindex, sock);
215 }
d62a17ae 216
217 /* Fill in sockaddr_in6. */
218 memset(&addr, 0, sizeof(struct sockaddr_in6));
219 addr.sin6_family = AF_INET6;
718e3744 220#ifdef SIN6_LEN
d62a17ae 221 addr.sin6_len = sizeof(struct sockaddr_in6);
718e3744 222#endif /* SIN6_LEN */
d62a17ae 223 addr.sin6_port = htons(IPPROTO_ICMPV6);
224 IPV6_ADDR_COPY(&addr.sin6_addr, all_nodes_addr);
225
226 /* Fetch interface information. */
227 zif = ifp->info;
228
229 /* Make router advertisement message. */
230 rtadv = (struct nd_router_advert *)buf;
231
232 rtadv->nd_ra_type = ND_ROUTER_ADVERT;
233 rtadv->nd_ra_code = 0;
234 rtadv->nd_ra_cksum = 0;
235
fae01935 236 rtadv->nd_ra_curhoplimit = zif->rtadv.AdvCurHopLimit;
d62a17ae 237
238 /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
239 rtadv->nd_ra_flags_reserved = zif->rtadv.AdvDefaultLifetime == 0
240 ? 0
241 : zif->rtadv.DefaultPreference;
242 rtadv->nd_ra_flags_reserved <<= 3;
243
244 if (zif->rtadv.AdvManagedFlag)
245 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
246 if (zif->rtadv.AdvOtherConfigFlag)
247 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
248 if (zif->rtadv.AdvHomeAgentFlag)
249 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
250 /* Note that according to Neighbor Discovery (RFC 4861 [18]),
251 * AdvDefaultLifetime is by default based on the value of
252 * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
253 * field of Router Advertisements. Given that this field is expressed
254 * in seconds, a small MaxRtrAdvInterval value can result in a zero
255 * value for this field. To prevent this, routers SHOULD keep
256 * AdvDefaultLifetime in at least one second, even if the use of
257 * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
258 pkt_RouterLifetime =
259 zif->rtadv.AdvDefaultLifetime != -1
260 ? zif->rtadv.AdvDefaultLifetime
261 : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
d7fc0e67
DS
262
263 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
264 rtadv->nd_ra_router_lifetime =
265 (stop == RA_SUPPRESS) ? htons(0) : htons(pkt_RouterLifetime);
d62a17ae 266 rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime);
b19ac878 267 rtadv->nd_ra_retransmit = htonl(zif->rtadv.AdvRetransTimer);
d62a17ae 268
269 len = sizeof(struct nd_router_advert);
270
271 /* If both the Home Agent Preference and Home Agent Lifetime are set to
272 * their default values specified above, this option SHOULD NOT be
273 * included in the Router Advertisement messages sent by this home
274 * agent. -- RFC6275, 7.4 */
275 if (zif->rtadv.AdvHomeAgentFlag
276 && (zif->rtadv.HomeAgentPreference
277 || zif->rtadv.HomeAgentLifetime != -1)) {
278 struct nd_opt_homeagent_info *ndopt_hai =
279 (struct nd_opt_homeagent_info *)(buf + len);
280 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
281 ndopt_hai->nd_opt_hai_len = 1;
282 ndopt_hai->nd_opt_hai_reserved = 0;
283 ndopt_hai->nd_opt_hai_preference =
284 htons(zif->rtadv.HomeAgentPreference);
285 /* 16-bit unsigned integer. The lifetime associated with the
286 * home
287 * agent in units of seconds. The default value is the same as
288 * the
289 * Router Lifetime, as specified in the main body of the Router
290 * Advertisement. The maximum value corresponds to 18.2 hours.
291 * A
292 * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
293 ndopt_hai->nd_opt_hai_lifetime =
294 htons(zif->rtadv.HomeAgentLifetime != -1
295 ? zif->rtadv.HomeAgentLifetime
296 : MAX(1, pkt_RouterLifetime) /* 0 is OK
297 for RL,
298 but not
299 for HAL*/
9d303b37 300 );
d62a17ae 301 len += sizeof(struct nd_opt_homeagent_info);
302 }
718e3744 303
d62a17ae 304 if (zif->rtadv.AdvIntervalOption) {
305 struct nd_opt_adv_interval *ndopt_adv =
306 (struct nd_opt_adv_interval *)(buf + len);
307 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
308 ndopt_adv->nd_opt_ai_len = 1;
309 ndopt_adv->nd_opt_ai_reserved = 0;
310 ndopt_adv->nd_opt_ai_interval =
311 htonl(zif->rtadv.MaxRtrAdvInterval);
312 len += sizeof(struct nd_opt_adv_interval);
313 }
314
315 /* Fill in prefix. */
316 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) {
317 struct nd_opt_prefix_info *pinfo;
718e3744 318
d62a17ae 319 pinfo = (struct nd_opt_prefix_info *)(buf + len);
718e3744 320
d62a17ae 321 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
322 pinfo->nd_opt_pi_len = 4;
323 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
324
325 pinfo->nd_opt_pi_flags_reserved = 0;
326 if (rprefix->AdvOnLinkFlag)
327 pinfo->nd_opt_pi_flags_reserved |=
328 ND_OPT_PI_FLAG_ONLINK;
329 if (rprefix->AdvAutonomousFlag)
330 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
331 if (rprefix->AdvRouterAddressFlag)
332 pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
333
334 pinfo->nd_opt_pi_valid_time = htonl(rprefix->AdvValidLifetime);
335 pinfo->nd_opt_pi_preferred_time =
336 htonl(rprefix->AdvPreferredLifetime);
337 pinfo->nd_opt_pi_reserved2 = 0;
338
339 IPV6_ADDR_COPY(&pinfo->nd_opt_pi_prefix,
340 &rprefix->prefix.prefix);
341
d62a17ae 342 len += sizeof(struct nd_opt_prefix_info);
343 }
344
345 /* Hardware address. */
346 if (ifp->hw_addr_len != 0) {
347 buf[len++] = ND_OPT_SOURCE_LINKADDR;
348
349 /* Option length should be rounded up to next octet if
350 the link address does not end on an octet boundary. */
351 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
352
353 memcpy(buf + len, ifp->hw_addr, ifp->hw_addr_len);
354 len += ifp->hw_addr_len;
355
356 /* Pad option to end on an octet boundary. */
357 memset(buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
358 len += -(ifp->hw_addr_len + 2) & 0x7;
359 }
360
361 /* MTU */
362 if (zif->rtadv.AdvLinkMTU) {
363 struct nd_opt_mtu *opt = (struct nd_opt_mtu *)(buf + len);
364 opt->nd_opt_mtu_type = ND_OPT_MTU;
365 opt->nd_opt_mtu_len = 1;
366 opt->nd_opt_mtu_reserved = 0;
367 opt->nd_opt_mtu_mtu = htonl(zif->rtadv.AdvLinkMTU);
368 len += sizeof(struct nd_opt_mtu);
369 }
370
7eab94f9
LS
371 /*
372 * There is no limit on the number of configurable recursive DNS
373 * servers or search list entries. We don't want the RA message
374 * to exceed the link's MTU (risking fragmentation) or even
375 * blow the stack buffer allocated for it.
376 */
377 size_t max_len = MIN(ifp->mtu6 - 40, sizeof(buf));
378
3eb4fbb0
LS
379 /* Recursive DNS servers */
380 struct rtadv_rdnss *rdnss;
381
382 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
7eab94f9
LS
383 size_t opt_len =
384 sizeof(struct nd_opt_rdnss) + sizeof(struct in6_addr);
385
386 if (len + opt_len > max_len) {
60077146
DS
387 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
388
7eab94f9 389 zlog_warn(
60077146
DS
390 "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
391 ifp->name, VRF_LOGNAME(vrf), ifp->ifindex);
7eab94f9
LS
392 goto no_more_opts;
393 }
3eb4fbb0
LS
394 struct nd_opt_rdnss *opt = (struct nd_opt_rdnss *)(buf + len);
395
396 opt->nd_opt_rdnss_type = ND_OPT_RDNSS;
7eab94f9 397 opt->nd_opt_rdnss_len = opt_len / 8;
3eb4fbb0
LS
398 opt->nd_opt_rdnss_reserved = 0;
399 opt->nd_opt_rdnss_lifetime = htonl(
400 rdnss->lifetime_set
401 ? rdnss->lifetime
402 : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
403
404 len += sizeof(struct nd_opt_rdnss);
7eab94f9 405
3eb4fbb0
LS
406 IPV6_ADDR_COPY(buf + len, &rdnss->addr);
407 len += sizeof(struct in6_addr);
408 }
409
410 /* DNS search list */
411 struct rtadv_dnssl *dnssl;
412
413 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
7eab94f9
LS
414 size_t opt_len = sizeof(struct nd_opt_dnssl)
415 + ((dnssl->encoded_len + 7) & ~7);
416
417 if (len + opt_len > max_len) {
418 zlog_warn(
419 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
420 ifp->name, ifp->ifindex);
421 goto no_more_opts;
422 }
3eb4fbb0
LS
423 struct nd_opt_dnssl *opt = (struct nd_opt_dnssl *)(buf + len);
424
425 opt->nd_opt_dnssl_type = ND_OPT_DNSSL;
7eab94f9 426 opt->nd_opt_dnssl_len = opt_len / 8;
3eb4fbb0
LS
427 opt->nd_opt_dnssl_reserved = 0;
428 opt->nd_opt_dnssl_lifetime = htonl(
429 dnssl->lifetime_set
430 ? dnssl->lifetime
431 : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
432
433 len += sizeof(struct nd_opt_dnssl);
434
3eb4fbb0
LS
435 memcpy(buf + len, dnssl->encoded_name, dnssl->encoded_len);
436 len += dnssl->encoded_len;
437
438 /* Zero-pad to 8-octet boundary */
439 while (len % 8)
440 buf[len++] = '\0';
3eb4fbb0
LS
441 }
442
7eab94f9
LS
443no_more_opts:
444
d62a17ae 445 msg.msg_name = (void *)&addr;
446 msg.msg_namelen = sizeof(struct sockaddr_in6);
447 msg.msg_iov = &iov;
448 msg.msg_iovlen = 1;
449 msg.msg_control = (void *)adata;
450 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
451 msg.msg_flags = 0;
452 iov.iov_base = buf;
453 iov.iov_len = len;
454
adf0e7c6 455 cmsgptr = CMSG_FIRSTHDR(&msg);
d62a17ae 456 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
457 cmsgptr->cmsg_level = IPPROTO_IPV6;
458 cmsgptr->cmsg_type = IPV6_PKTINFO;
459
460 pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
461 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
462 pkt->ipi6_ifindex = ifp->ifindex;
463
464 ret = sendmsg(sock, &msg, 0);
465 if (ret < 0) {
450971aa 466 flog_err_sys(EC_LIB_SOCKET,
09c866e3
QY
467 "%s(%u): Tx RA failed, socket %u error %d (%s)",
468 ifp->name, ifp->ifindex, sock, errno,
469 safe_strerror(errno));
d62a17ae 470 } else
471 zif->ra_sent++;
718e3744 472}
473
d62a17ae 474static int rtadv_timer(struct thread *thread)
718e3744 475{
df9c8c57 476 struct zebra_vrf *zvrf = THREAD_ARG(thread);
d62a17ae 477 struct vrf *vrf;
d62a17ae 478 struct interface *ifp;
479 struct zebra_if *zif;
480 int period;
481
df9c8c57
PG
482 zvrf->rtadv.ra_timer = NULL;
483 if (zvrf->rtadv.adv_msec_if_count == 0) {
d62a17ae 484 period = 1000; /* 1 s */
df9c8c57 485 rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
d62a17ae 486 } else {
487 period = 10; /* 10 ms */
df9c8c57 488 rtadv_event(zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
d62a17ae 489 }
490
a2addae8 491 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
451fda4f 492 FOR_ALL_INTERFACES (vrf, ifp) {
a2addae8
RW
493 if (if_is_loopback(ifp)
494 || CHECK_FLAG(ifp->status,
495 ZEBRA_INTERFACE_VRF_LOOPBACK)
496 || !if_is_operative(ifp))
497 continue;
498
499 zif = ifp->info;
500
501 if (zif->rtadv.AdvSendAdvertisements) {
adee8f21
DS
502 if (zif->rtadv.inFastRexmit
503 && zif->rtadv.UseFastRexmit) {
a2addae8
RW
504 /* We assume we fast rexmit every sec so
505 * no
506 * additional vars */
507 if (--zif->rtadv.NumFastReXmitsRemain
508 <= 0)
509 zif->rtadv.inFastRexmit = 0;
510
60077146
DS
511 if (IS_ZEBRA_DEBUG_SEND) {
512 struct vrf *vrf =
513 vrf_lookup_by_id(
514 ifp->vrf_id);
515
a2addae8 516 zlog_debug(
60077146
DS
517 "Fast RA Rexmit on interface %s(%s:%u)",
518 ifp->name,
519 VRF_LOGNAME(vrf),
520 ifp->ifindex);
521 }
a2addae8 522
9245fe61 523 rtadv_send_packet(rtadv_get_socket(zvrf),
d7fc0e67 524 ifp, RA_ENABLE);
a2addae8
RW
525 } else {
526 zif->rtadv.AdvIntervalTimer -= period;
527 if (zif->rtadv.AdvIntervalTimer <= 0) {
528 /* FIXME: using
529 MaxRtrAdvInterval each
530 time isn't what section
531 6.2.4 of RFC4861 tells to do.
532 */
533 zif->rtadv.AdvIntervalTimer =
534 zif->rtadv
535 .MaxRtrAdvInterval;
536 rtadv_send_packet(
9245fe61 537 rtadv_get_socket(zvrf),
d7fc0e67 538 ifp, RA_ENABLE);
a2addae8 539 }
d62a17ae 540 }
541 }
542 }
d62a17ae 543
544 return 0;
718e3744 545}
546
d62a17ae 547static void rtadv_process_solicit(struct interface *ifp)
718e3744 548{
a36898e7 549 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
adee8f21 550 struct zebra_if *zif;
718e3744 551
df9c8c57 552 assert(zvrf);
adee8f21
DS
553 zif = ifp->info;
554
555 /*
556 * If FastRetransmit is enabled, send the RA immediately.
557 * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
558 * (3 seconds) since the last RA was sent, send it now and reset
559 * the timer to start at the max (configured) again.
560 * If not enabled and it is less than 3 seconds since the last
561 * RA packet was sent, set the timer for 3 seconds so the next
562 * one will be sent with a minimum of 3 seconds between RAs.
563 * RFC4861 sec 6.2.6
564 */
565 if ((zif->rtadv.UseFastRexmit)
566 || (zif->rtadv.AdvIntervalTimer <=
567 (zif->rtadv.MaxRtrAdvInterval - MIN_DELAY_BETWEEN_RAS))) {
d7fc0e67 568 rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_ENABLE);
adee8f21
DS
569 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
570 } else
571 zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS;
718e3744 572}
573
71974bf5
DS
574/*
575 * This function processes optional attributes off of
576 * end of a RA packet received. At this point in
577 * time we only care about this in one situation
578 * which is when a interface does not have a LL
579 * v6 address. We still need to be able to install
580 * the mac address for v4 to v6 resolution
581 */
582static void rtadv_process_optional(uint8_t *optional, unsigned int len,
583 struct interface *ifp,
584 struct sockaddr_in6 *addr)
585{
586 char *mac;
587
588 while (len > 0) {
589 struct nd_opt_hdr *opt_hdr = (struct nd_opt_hdr *)optional;
590
591 switch(opt_hdr->nd_opt_type) {
592 case ND_OPT_SOURCE_LINKADDR:
593 mac = (char *)(optional+2);
594 if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac,
595 &addr->sin6_addr, 1);
596 break;
597 default:
598 break;
599 }
600
601 len -= 8 * opt_hdr->nd_opt_len;
602 optional += 8 * opt_hdr->nd_opt_len;
603 }
604}
605
d7c0a89a 606static void rtadv_process_advert(uint8_t *msg, unsigned int len,
d62a17ae 607 struct interface *ifp,
608 struct sockaddr_in6 *addr)
718e3744 609{
d62a17ae 610 struct nd_router_advert *radvert;
611 char addr_str[INET6_ADDRSTRLEN];
612 struct zebra_if *zif;
613 struct prefix p;
718e3744 614
d62a17ae 615 zif = ifp->info;
a80beece 616
d62a17ae 617 inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
618
619 if (len < sizeof(struct nd_router_advert)) {
60077146
DS
620 if (IS_ZEBRA_DEBUG_PACKET) {
621 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
622
623 zlog_debug(
624 "%s(%s:%u): Rx RA with invalid length %d from %s",
625 ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, len,
626 addr_str);
627 }
d62a17ae 628 return;
629 }
71974bf5 630
d62a17ae 631 if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
71974bf5
DS
632 rtadv_process_optional(msg + sizeof(struct nd_router_advert),
633 len - sizeof(struct nd_router_advert),
634 ifp, addr);
60077146
DS
635 if (IS_ZEBRA_DEBUG_PACKET) {
636 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
637
638 zlog_debug(
639 "%s(%s:%u): Rx RA with non-linklocal source address from %s",
640 ifp->name, VRF_LOGNAME(vrf), ifp->ifindex,
641 addr_str);
642 }
d62a17ae 643 return;
644 }
645
646 radvert = (struct nd_router_advert *)msg;
647
648 if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit)
649 && (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) {
9df414fe 650 flog_warn(
e914ccbe 651 EC_ZEBRA_RA_PARAM_MISMATCH,
d62a17ae 652 "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
653 ifp->name, ifp->ifindex, addr_str);
654 }
655
656 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
657 && !zif->rtadv.AdvManagedFlag) {
9df414fe 658 flog_warn(
e914ccbe 659 EC_ZEBRA_RA_PARAM_MISMATCH,
d62a17ae 660 "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
661 ifp->name, ifp->ifindex, addr_str);
662 }
663
664 if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
665 && !zif->rtadv.AdvOtherConfigFlag) {
9df414fe 666 flog_warn(
e914ccbe 667 EC_ZEBRA_RA_PARAM_MISMATCH,
d62a17ae 668 "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
669 ifp->name, ifp->ifindex, addr_str);
670 }
671
672 if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime)
673 && (ntohl(radvert->nd_ra_reachable)
674 != zif->rtadv.AdvReachableTime)) {
9df414fe 675 flog_warn(
e914ccbe 676 EC_ZEBRA_RA_PARAM_MISMATCH,
d62a17ae 677 "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
678 ifp->name, ifp->ifindex, addr_str);
679 }
680
b19ac878
DS
681 if ((ntohl(radvert->nd_ra_retransmit)
682 != (unsigned int)zif->rtadv.AdvRetransTimer)) {
9df414fe 683 flog_warn(
e914ccbe 684 EC_ZEBRA_RA_PARAM_MISMATCH,
d62a17ae 685 "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
686 ifp->name, ifp->ifindex, addr_str);
687 }
688
689 /* Create entry for neighbor if not known. */
690 p.family = AF_INET6;
a85297a7 691 IPV6_ADDR_COPY(&p.u.prefix6, &addr->sin6_addr);
d62a17ae 692 p.prefixlen = IPV6_MAX_PREFIXLEN;
693
694 if (!nbr_connected_check(ifp, &p))
695 nbr_connected_add_ipv6(ifp, &addr->sin6_addr);
718e3744 696}
697
d62a17ae 698
d7c0a89a 699static void rtadv_process_packet(uint8_t *buf, unsigned int len,
d62a17ae 700 ifindex_t ifindex, int hoplimit,
701 struct sockaddr_in6 *from,
df9c8c57 702 struct zebra_vrf *zvrf)
718e3744 703{
d62a17ae 704 struct icmp6_hdr *icmph;
705 struct interface *ifp;
706 struct zebra_if *zif;
707 char addr_str[INET6_ADDRSTRLEN];
708
709 inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
710
711 /* Interface search. */
df9c8c57 712 ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
d62a17ae 713 if (ifp == NULL) {
e914ccbe 714 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
9df414fe 715 "RA/RS received on unknown IF %u from %s", ifindex,
d62a17ae 716 addr_str);
717 return;
718 }
719
60077146
DS
720 if (IS_ZEBRA_DEBUG_PACKET) {
721 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
722
723 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp->name,
724 VRF_LOGNAME(vrf), ifp->ifindex, len, addr_str);
725 }
d62a17ae 726
727 if (if_is_loopback(ifp)
728 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
729 return;
718e3744 730
d62a17ae 731 /* Check interface configuration. */
732 zif = ifp->info;
733 if (!zif->rtadv.AdvSendAdvertisements)
734 return;
718e3744 735
d62a17ae 736 /* ICMP message length check. */
737 if (len < sizeof(struct icmp6_hdr)) {
60077146
DS
738 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
739
740 zlog_debug(
741 "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
742 ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, len);
d62a17ae 743 return;
744 }
745
746 icmph = (struct icmp6_hdr *)buf;
718e3744 747
d62a17ae 748 /* ICMP message type check. */
749 if (icmph->icmp6_type != ND_ROUTER_SOLICIT
750 && icmph->icmp6_type != ND_ROUTER_ADVERT) {
60077146
DS
751 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
752
753 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
754 ifp->name, VRF_LOGNAME(vrf), ifp->ifindex,
755 icmph->icmp6_type);
d62a17ae 756 return;
757 }
718e3744 758
d62a17ae 759 /* Hoplimit check. */
760 if (hoplimit >= 0 && hoplimit != 255) {
60077146
DS
761 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
762
763 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp->name,
764 VRF_LOGNAME(vrf), ifp->ifindex, hoplimit);
d62a17ae 765 return;
766 }
718e3744 767
d62a17ae 768 /* Check ICMP message type. */
769 if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
770 rtadv_process_solicit(ifp);
771 else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
772 rtadv_process_advert(buf, len, ifp, from);
718e3744 773
d62a17ae 774 return;
718e3744 775}
776
d62a17ae 777static int rtadv_read(struct thread *thread)
718e3744 778{
d62a17ae 779 int sock;
780 int len;
d7c0a89a 781 uint8_t buf[RTADV_MSG_SIZE];
d62a17ae 782 struct sockaddr_in6 from;
783 ifindex_t ifindex = 0;
784 int hoplimit = -1;
df9c8c57 785 struct zebra_vrf *zvrf = THREAD_ARG(thread);
d62a17ae 786
787 sock = THREAD_FD(thread);
df9c8c57 788 zvrf->rtadv.ra_read = NULL;
d62a17ae 789
790 /* Register myself. */
df9c8c57 791 rtadv_event(zvrf, RTADV_READ, sock);
d62a17ae 792
df9c8c57 793 len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
d62a17ae 794 &hoplimit);
795
796 if (len < 0) {
450971aa 797 flog_err_sys(EC_LIB_SOCKET,
9df414fe
QY
798 "RA/RS recv failed, socket %u error %s", sock,
799 safe_strerror(errno));
d62a17ae 800 return len;
801 }
802
df9c8c57 803 rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf);
d62a17ae 804
805 return 0;
718e3744 806}
6b0655a2 807
fe533c56 808static int rtadv_make_socket(ns_id_t ns_id)
718e3744 809{
8d2dcc85 810 int sock = -1;
d62a17ae 811 int ret = 0;
812 struct icmp6_filter filter;
813
0cf6db21 814 frr_with_privs(&zserv_privs) {
d62a17ae 815
01b9e3fd 816 sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
d62a17ae 817
01b9e3fd 818 }
d62a17ae 819
820 if (sock < 0) {
d62a17ae 821 return -1;
822 }
823
824 ret = setsockopt_ipv6_pktinfo(sock, 1);
825 if (ret < 0) {
826 close(sock);
827 return ret;
828 }
829 ret = setsockopt_ipv6_multicast_loop(sock, 0);
830 if (ret < 0) {
831 close(sock);
832 return ret;
833 }
834 ret = setsockopt_ipv6_unicast_hops(sock, 255);
835 if (ret < 0) {
836 close(sock);
837 return ret;
838 }
839 ret = setsockopt_ipv6_multicast_hops(sock, 255);
840 if (ret < 0) {
841 close(sock);
842 return ret;
843 }
844 ret = setsockopt_ipv6_hoplimit(sock, 1);
845 if (ret < 0) {
846 close(sock);
847 return ret;
848 }
849
850 ICMP6_FILTER_SETBLOCKALL(&filter);
851 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
852 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
853
854 ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
855 sizeof(struct icmp6_filter));
856 if (ret < 0) {
857 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno));
44f12f20 858 close(sock);
d62a17ae 859 return ret;
860 }
861
862 return sock;
718e3744 863}
864
d62a17ae 865static struct rtadv_prefix *rtadv_prefix_new(void)
718e3744 866{
d62a17ae 867 return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix));
718e3744 868}
869
d62a17ae 870static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix)
718e3744 871{
d62a17ae 872 XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix);
873}
718e3744 874
d62a17ae 875static struct rtadv_prefix *rtadv_prefix_lookup(struct list *rplist,
876 struct prefix_ipv6 *p)
877{
878 struct listnode *node;
879 struct rtadv_prefix *rprefix;
880
881 for (ALL_LIST_ELEMENTS_RO(rplist, node, rprefix))
882 if (prefix_same((struct prefix *)&rprefix->prefix,
883 (struct prefix *)p))
884 return rprefix;
885 return NULL;
718e3744 886}
887
d62a17ae 888static struct rtadv_prefix *rtadv_prefix_get(struct list *rplist,
889 struct prefix_ipv6 *p)
718e3744 890{
d62a17ae 891 struct rtadv_prefix *rprefix;
892
893 rprefix = rtadv_prefix_lookup(rplist, p);
894 if (rprefix)
895 return rprefix;
718e3744 896
d62a17ae 897 rprefix = rtadv_prefix_new();
898 memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6));
899 listnode_add(rplist, rprefix);
718e3744 900
d62a17ae 901 return rprefix;
718e3744 902}
903
2a855763
DS
904static void rtadv_prefix_set_defaults(struct rtadv_prefix *rp)
905{
906 rp->AdvAutonomousFlag = 1;
907 rp->AdvOnLinkFlag = 1;
908 rp->AdvRouterAddressFlag = 0;
909 rp->AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
910 rp->AdvValidLifetime = RTADV_VALID_LIFETIME;
911}
912
d62a17ae 913static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
718e3744 914{
d62a17ae 915 struct rtadv_prefix *rprefix;
916
917 rprefix = rtadv_prefix_get(zif->rtadv.AdvPrefixList, &rp->prefix);
918
2a855763
DS
919 /*
920 * Set parameters based on where the prefix is created.
921 * If auto-created based on kernel address addition, set the
922 * default values. If created from a manual "ipv6 nd prefix"
923 * command, take the parameters from the manual command. Note
924 * that if the manual command exists, the default values will
925 * not overwrite the manual values.
926 */
927 if (rp->AdvPrefixCreate == PREFIX_SRC_MANUAL) {
928 if (rprefix->AdvPrefixCreate == PREFIX_SRC_AUTO)
929 rprefix->AdvPrefixCreate = PREFIX_SRC_BOTH;
930 else
931 rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
932
933 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
934 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
935 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
936 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
937 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
938 } else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
939 if (rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
940 rprefix->AdvPrefixCreate = PREFIX_SRC_BOTH;
941 else {
942 rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
943 rtadv_prefix_set_defaults(rprefix);
944 }
945 }
718e3744 946}
947
d62a17ae 948static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
718e3744 949{
d62a17ae 950 struct rtadv_prefix *rprefix;
951
952 rprefix = rtadv_prefix_lookup(zif->rtadv.AdvPrefixList, &rp->prefix);
953 if (rprefix != NULL) {
2a855763
DS
954
955 /*
956 * When deleting an address from the list, need to take care
957 * it wasn't defined both automatically via kernel
958 * address addition as well as manually by vtysh cli. If both,
959 * we don't actually delete but may change the parameters
960 * back to default if a manually defined entry is deleted.
961 */
962 if (rp->AdvPrefixCreate == PREFIX_SRC_MANUAL) {
963 if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
964 rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
965 rtadv_prefix_set_defaults(rprefix);
966 return 1;
967 }
968 } else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
969 if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
970 rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
971 return 1;
972 }
973 }
974
d62a17ae 975 listnode_delete(zif->rtadv.AdvPrefixList, (void *)rprefix);
976 rtadv_prefix_free(rprefix);
977 return 1;
978 } else
979 return 0;
718e3744 980}
981
2a855763
DS
982/* Add IPv6 prefixes learned from the kernel to the RA prefix list */
983void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p)
984{
985 struct rtadv_prefix rp;
986
987 rp.prefix = *p;
988 apply_mask_ipv6(&rp.prefix);
989 rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
990 rtadv_prefix_set(zif, &rp);
991}
992
993/* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
994void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
995{
996 struct rtadv_prefix rp;
997
998 rp.prefix = *((struct prefix_ipv6 *)p);
999 apply_mask_ipv6(&rp.prefix);
1000 rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
1001 rtadv_prefix_reset(zif, &rp);
1002}
1003
d62a17ae 1004static void ipv6_nd_suppress_ra_set(struct interface *ifp,
57dd8642 1005 enum ipv6_nd_suppress_ra_status status)
b6120505 1006{
d62a17ae 1007 struct zebra_if *zif;
1008 struct zebra_vrf *zvrf;
d62a17ae 1009
1010 zif = ifp->info;
a36898e7 1011 zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 1012
1013 if (status == RA_SUPPRESS) {
1014 /* RA is currently enabled */
1015 if (zif->rtadv.AdvSendAdvertisements) {
d7fc0e67
DS
1016 rtadv_send_packet(rtadv_get_socket(zvrf), ifp,
1017 RA_SUPPRESS);
d62a17ae 1018 zif->rtadv.AdvSendAdvertisements = 0;
1019 zif->rtadv.AdvIntervalTimer = 0;
df9c8c57 1020 zvrf->rtadv.adv_if_count--;
d62a17ae 1021
9245fe61 1022 if_leave_all_router(rtadv_get_socket(zvrf), ifp);
d62a17ae 1023
df9c8c57
PG
1024 if (zvrf->rtadv.adv_if_count == 0)
1025 rtadv_event(zvrf, RTADV_STOP, 0);
d62a17ae 1026 }
1027 } else {
1028 if (!zif->rtadv.AdvSendAdvertisements) {
1029 zif->rtadv.AdvSendAdvertisements = 1;
1030 zif->rtadv.AdvIntervalTimer = 0;
df9c8c57 1031 zvrf->rtadv.adv_if_count++;
d62a17ae 1032
adee8f21
DS
1033 if ((zif->rtadv.MaxRtrAdvInterval >= 1000)
1034 && zif->rtadv.UseFastRexmit) {
1035 /*
1036 * Enable Fast RA only when RA interval is in
1037 * secs and Fast RA retransmit is enabled
1038 */
d62a17ae 1039 zif->rtadv.inFastRexmit = 1;
1040 zif->rtadv.NumFastReXmitsRemain =
1041 RTADV_NUM_FAST_REXMITS;
1042 }
1043
9245fe61 1044 if_join_all_router(rtadv_get_socket(zvrf), ifp);
d62a17ae 1045
df9c8c57
PG
1046 if (zvrf->rtadv.adv_if_count == 1)
1047 rtadv_event(zvrf, RTADV_START,
9245fe61 1048 rtadv_get_socket(zvrf));
d62a17ae 1049 }
1050 }
b6120505
DW
1051}
1052
4a04e5f7 1053/*
1054 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1055 * Note that while the client could request RA on an interface on which the
1056 * operator has not enabled RA, RA won't be disabled upon client request
5c81b96a 1057 * if the operator has explicitly enabled RA. The enable request can also
1058 * specify a RA interval (in seconds).
4a04e5f7 1059 */
1002497a 1060static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
4a04e5f7 1061{
d62a17ae 1062 struct stream *s;
ec93aa12 1063 ifindex_t ifindex;
d62a17ae 1064 struct interface *ifp;
1065 struct zebra_if *zif;
bbad0276 1066 uint32_t ra_interval;
d62a17ae 1067
1002497a 1068 s = msg;
d62a17ae 1069
1070 /* Get interface index and RA interval. */
ec93aa12 1071 STREAM_GETL(s, ifindex);
bbad0276 1072 STREAM_GETL(s, ra_interval);
d62a17ae 1073
60077146
DS
1074 if (IS_ZEBRA_DEBUG_EVENT) {
1075 struct vrf *vrf = zvrf->vrf;
1076
1077 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1078 VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
1002497a 1079 enable ? "enable" : "disable",
d62a17ae 1080 zebra_route_string(client->proto), ra_interval);
60077146 1081 }
d62a17ae 1082
1083 /* Locate interface and check VRF match. */
df9c8c57 1084 ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
d62a17ae 1085 if (!ifp) {
60077146
DS
1086 struct vrf *vrf = zvrf->vrf;
1087
e914ccbe 1088 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
60077146
DS
1089 "%s:%u: IF %u RA %s client %s - interface unknown",
1090 VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
1091 enable ? "enable" : "disable",
d62a17ae 1092 zebra_route_string(client->proto));
1093 return;
1094 }
a36898e7 1095 if (ifp->vrf_id != zvrf_id(zvrf)) {
60077146
DS
1096 struct vrf *vrf = zvrf->vrf;
1097
9df414fe 1098 zlog_debug(
60077146
DS
1099 "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1100 VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
1101 enable ? "enable" : "disable",
a36898e7 1102 zebra_route_string(client->proto), ifp->vrf_id);
d62a17ae 1103 return;
1104 }
1105
1106 zif = ifp->info;
1002497a 1107 if (enable) {
3ea48364 1108 SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
d62a17ae 1109 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
1110 if (ra_interval
40441c3d 1111 && (ra_interval * 1000) < (unsigned int) zif->rtadv.MaxRtrAdvInterval
996c9314
LB
1112 && !CHECK_FLAG(zif->rtadv.ra_configured,
1113 VTY_RA_INTERVAL_CONFIGURED))
d62a17ae 1114 zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
1115 } else {
3ea48364
DS
1116 UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
1117 if (!CHECK_FLAG(zif->rtadv.ra_configured,
1118 VTY_RA_INTERVAL_CONFIGURED))
d62a17ae 1119 zif->rtadv.MaxRtrAdvInterval =
1120 RTADV_MAX_RTR_ADV_INTERVAL;
3ea48364 1121 if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
d62a17ae 1122 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
d62a17ae 1123 }
ec93aa12
DS
1124stream_failure:
1125 return;
4a04e5f7 1126}
1127
d7fc0e67
DS
1128/*
1129 * send router lifetime value of zero in RAs on this interface since we're
1130 * ceasing to advertise and want to let our neighbors know.
1131 * RFC 4861 secion 6.2.5
1132 */
1133void rtadv_stop_ra(struct interface *ifp)
1134{
1135 struct zebra_if *zif;
1136 struct zebra_vrf *zvrf;
1137
1138 zif = ifp->info;
1139 zvrf = vrf_info_lookup(ifp->vrf_id);
1140
1141 if (zif->rtadv.AdvSendAdvertisements)
1142 rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_SUPPRESS);
1143}
1144
1145/*
5a7aea85 1146 * Send router lifetime value of zero in RAs on all interfaces since we're
d7fc0e67
DS
1147 * ceasing to advertise globally and want to let all of our neighbors know
1148 * RFC 4861 secion 6.2.5
5a7aea85
DS
1149 *
1150 * Delete all ipv6 global prefixes added to the router advertisement prefix
1151 * lists prior to ceasing.
d7fc0e67
DS
1152 */
1153void rtadv_stop_ra_all(void)
1154{
1155 struct vrf *vrf;
1156 struct interface *ifp;
5a7aea85
DS
1157 struct listnode *node, *nnode;
1158 struct zebra_if *zif;
1159 struct rtadv_prefix *rprefix;
d7fc0e67
DS
1160
1161 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
5a7aea85
DS
1162 FOR_ALL_INTERFACES (vrf, ifp) {
1163 zif = ifp->info;
1164
1165 for (ALL_LIST_ELEMENTS(zif->rtadv.AdvPrefixList,
1166 node, nnode, rprefix))
1167 rtadv_prefix_reset(zif, rprefix);
1168
d7fc0e67 1169 rtadv_stop_ra(ifp);
5a7aea85 1170 }
d7fc0e67
DS
1171}
1172
89f4e507
QY
1173void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
1174{
1002497a 1175 zebra_interface_radv_set(client, hdr, msg, zvrf, 0);
89f4e507 1176}
89f4e507
QY
1177void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
1178{
1002497a 1179 zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
89f4e507
QY
1180}
1181
adee8f21
DS
1182DEFUN (ipv6_nd_ra_fast_retrans,
1183 ipv6_nd_ra_fast_retrans_cmd,
1184 "ipv6 nd ra-fast-retrans",
1185 "Interface IPv6 config commands\n"
1186 "Neighbor discovery\n"
1187 "Fast retransmit of RA packets\n")
1188{
1189 VTY_DECLVAR_CONTEXT(interface, ifp);
1190 struct zebra_if *zif = ifp->info;
1191
1192 if (if_is_loopback(ifp)
1193 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1194 vty_out(vty,
1195 "Cannot configure IPv6 Router Advertisements on this interface\n");
1196 return CMD_WARNING_CONFIG_FAILED;
1197 }
1198
1199 zif->rtadv.UseFastRexmit = true;
1200
1201 return CMD_SUCCESS;
1202}
1203
1204DEFUN (no_ipv6_nd_ra_fast_retrans,
1205 no_ipv6_nd_ra_fast_retrans_cmd,
1206 "no ipv6 nd ra-fast-retrans",
1207 NO_STR
1208 "Interface IPv6 config commands\n"
1209 "Neighbor discovery\n"
1210 "Fast retransmit of RA packets\n")
1211{
1212 VTY_DECLVAR_CONTEXT(interface, ifp);
1213 struct zebra_if *zif = ifp->info;
1214
1215 if (if_is_loopback(ifp)
1216 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1217 vty_out(vty,
1218 "Cannot configure IPv6 Router Advertisements on this interface\n");
1219 return CMD_WARNING_CONFIG_FAILED;
1220 }
1221
1222 zif->rtadv.UseFastRexmit = false;
1223
1224 return CMD_SUCCESS;
1225}
1226
fae01935
DS
1227DEFPY (ipv6_nd_ra_hop_limit,
1228 ipv6_nd_ra_hop_limit_cmd,
1229 "ipv6 nd ra-hop-limit (0-255)$hopcount",
1230 "Interface IPv6 config commands\n"
1231 "Neighbor discovery\n"
1232 "Advertisement Hop Limit\n"
1233 "Advertisement Hop Limit in hops (default:64)\n")
1234{
1235 VTY_DECLVAR_CONTEXT(interface, ifp);
1236 struct zebra_if *zif = ifp->info;
1237
1238 if (if_is_loopback(ifp)
1239 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1240 vty_out(vty,
1241 "Cannot configure IPv6 Router Advertisements on this interface\n");
1242 return CMD_WARNING_CONFIG_FAILED;
1243 }
1244
1245 zif->rtadv.AdvCurHopLimit = hopcount;
1246
1247 return CMD_SUCCESS;
1248}
1249
1250DEFPY (no_ipv6_nd_ra_hop_limit,
1251 no_ipv6_nd_ra_hop_limit_cmd,
1252 "no ipv6 nd ra-hop-limit [(0-255)]",
1253 NO_STR
1254 "Interface IPv6 config commands\n"
1255 "Neighbor discovery\n"
1256 "Advertisement Hop Limit\n"
1257 "Advertisement Hop Limit in hops\n")
1258{
1259 VTY_DECLVAR_CONTEXT(interface, ifp);
1260 struct zebra_if *zif = ifp->info;
1261
1262 if (if_is_loopback(ifp)
1263 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1264 vty_out(vty,
1265 "Cannot configure IPv6 Router Advertisements on this interface\n");
1266 return CMD_WARNING_CONFIG_FAILED;
1267 }
1268
1269 zif->rtadv.AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
1270
1271 return CMD_SUCCESS;
1272}
1273
b19ac878
DS
1274DEFPY (ipv6_nd_ra_retrans_interval,
1275 ipv6_nd_ra_retrans_interval_cmd,
1276 "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1277 "Interface IPv6 config commands\n"
1278 "Neighbor discovery\n"
1279 "Advertisement Retransmit Interval\n"
1280 "Advertisement Retransmit Interval in msec\n")
1281{
1282 VTY_DECLVAR_CONTEXT(interface, ifp);
1283 struct zebra_if *zif = ifp->info;
1284
1285 if (if_is_loopback(ifp)
1286 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1287 vty_out(vty,
1288 "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1289 return CMD_WARNING_CONFIG_FAILED;
1290 }
1291
1292 zif->rtadv.AdvRetransTimer = interval;
1293
1294 return CMD_SUCCESS;
1295}
1296
1297DEFPY (no_ipv6_nd_ra_retrans_interval,
1298 no_ipv6_nd_ra_retrans_interval_cmd,
1299 "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1300 NO_STR
1301 "Interface IPv6 config commands\n"
1302 "Neighbor discovery\n"
1303 "Advertisement Retransmit Interval\n"
1304 "Advertisement Retransmit Interval in msec\n")
1305{
1306 VTY_DECLVAR_CONTEXT(interface, ifp);
1307 struct zebra_if *zif = ifp->info;
1308
1309 if (if_is_loopback(ifp)
1310 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1311 vty_out(vty,
1312 "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1313 return CMD_WARNING_CONFIG_FAILED;
1314 }
1315
1316 zif->rtadv.AdvRetransTimer = 0;
1317
1318 return CMD_SUCCESS;
1319}
1320
718e3744 1321DEFUN (ipv6_nd_suppress_ra,
1322 ipv6_nd_suppress_ra_cmd,
1323 "ipv6 nd suppress-ra",
3e31cded 1324 "Interface IPv6 config commands\n"
718e3744 1325 "Neighbor discovery\n"
1326 "Suppress Router Advertisement\n")
1327{
d62a17ae 1328 VTY_DECLVAR_CONTEXT(interface, ifp);
1329 struct zebra_if *zif = ifp->info;
1330
1331 if (if_is_loopback(ifp)
1332 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1333 vty_out(vty,
1334 "Cannot configure IPv6 Router Advertisements on this interface\n");
1335 return CMD_WARNING_CONFIG_FAILED;
1336 }
1337
3ea48364
DS
1338 if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1339 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
1340
1341 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
d62a17ae 1342 return CMD_SUCCESS;
718e3744 1343}
1344
718e3744 1345DEFUN (no_ipv6_nd_suppress_ra,
1346 no_ipv6_nd_suppress_ra_cmd,
1347 "no ipv6 nd suppress-ra",
1348 NO_STR
3e31cded 1349 "Interface IPv6 config commands\n"
718e3744 1350 "Neighbor discovery\n"
1351 "Suppress Router Advertisement\n")
1352{
d62a17ae 1353 VTY_DECLVAR_CONTEXT(interface, ifp);
1354 struct zebra_if *zif = ifp->info;
1355
1356 if (if_is_loopback(ifp)
1357 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1358 vty_out(vty,
1359 "Cannot configure IPv6 Router Advertisements on this interface\n");
1360 return CMD_WARNING_CONFIG_FAILED;
1361 }
1362
1363 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
3ea48364 1364 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
d62a17ae 1365 return CMD_SUCCESS;
718e3744 1366}
1367
7cee1bb1 1368DEFUN (ipv6_nd_ra_interval_msec,
1369 ipv6_nd_ra_interval_msec_cmd,
6147e2c6 1370 "ipv6 nd ra-interval msec (70-1800000)",
7cee1bb1 1371 "Interface IPv6 config commands\n"
1372 "Neighbor discovery\n"
1373 "Router Advertisement interval\n"
3a2d747c 1374 "Router Advertisement interval in milliseconds\n"
7cee1bb1 1375 "Router Advertisement interval in milliseconds\n")
1376{
d62a17ae 1377 int idx_number = 4;
1378 VTY_DECLVAR_CONTEXT(interface, ifp);
1379 unsigned interval;
1380 struct zebra_if *zif = ifp->info;
df9c8c57
PG
1381 struct zebra_vrf *zvrf;
1382
a36898e7 1383 zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 1384
d62a17ae 1385 interval = strtoul(argv[idx_number]->arg, NULL, 10);
1386 if ((zif->rtadv.AdvDefaultLifetime != -1
1387 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
1388 vty_out(vty,
1389 "This ra-interval would conflict with configured ra-lifetime!\n");
1390 return CMD_WARNING_CONFIG_FAILED;
1391 }
1392
1393 if (zif->rtadv.MaxRtrAdvInterval % 1000)
df9c8c57 1394 zvrf->rtadv.adv_msec_if_count--;
d62a17ae 1395
1396 if (interval % 1000)
df9c8c57 1397 zvrf->rtadv.adv_msec_if_count++;
d62a17ae 1398
3ea48364 1399 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
d62a17ae 1400 zif->rtadv.MaxRtrAdvInterval = interval;
1401 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1402 zif->rtadv.AdvIntervalTimer = 0;
1403
1404 return CMD_SUCCESS;
7cee1bb1 1405}
1406
718e3744 1407DEFUN (ipv6_nd_ra_interval,
1408 ipv6_nd_ra_interval_cmd,
6147e2c6 1409 "ipv6 nd ra-interval (1-1800)",
3e31cded 1410 "Interface IPv6 config commands\n"
718e3744 1411 "Neighbor discovery\n"
1412 "Router Advertisement interval\n"
1413 "Router Advertisement interval in seconds\n")
1414{
d62a17ae 1415 int idx_number = 3;
1416 VTY_DECLVAR_CONTEXT(interface, ifp);
1417 unsigned interval;
1418 struct zebra_if *zif = ifp->info;
df9c8c57
PG
1419 struct zebra_vrf *zvrf;
1420
a36898e7 1421 zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 1422
d62a17ae 1423 interval = strtoul(argv[idx_number]->arg, NULL, 10);
1424 if ((zif->rtadv.AdvDefaultLifetime != -1
1425 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
1426 vty_out(vty,
1427 "This ra-interval would conflict with configured ra-lifetime!\n");
1428 return CMD_WARNING_CONFIG_FAILED;
1429 }
1430
1431 if (zif->rtadv.MaxRtrAdvInterval % 1000)
df9c8c57 1432 zvrf->rtadv.adv_msec_if_count--;
d62a17ae 1433
1434 /* convert to milliseconds */
1435 interval = interval * 1000;
1436
3ea48364 1437 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
d62a17ae 1438 zif->rtadv.MaxRtrAdvInterval = interval;
1439 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1440 zif->rtadv.AdvIntervalTimer = 0;
1441
1442 return CMD_SUCCESS;
718e3744 1443}
1444
1445DEFUN (no_ipv6_nd_ra_interval,
1446 no_ipv6_nd_ra_interval_cmd,
34ccea1e 1447 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
718e3744 1448 NO_STR
3e31cded 1449 "Interface IPv6 config commands\n"
718e3744 1450 "Neighbor discovery\n"
34ccea1e
QY
1451 "Router Advertisement interval\n"
1452 "Router Advertisement interval in seconds\n"
1453 "Specify millisecond router advertisement interval\n"
1454 "Router Advertisement interval in milliseconds\n")
718e3744 1455{
d62a17ae 1456 VTY_DECLVAR_CONTEXT(interface, ifp);
1457 struct zebra_if *zif = ifp->info;
df9c8c57
PG
1458 struct zebra_vrf *zvrf = NULL;
1459
a36898e7 1460 zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 1461
1462 if (zif->rtadv.MaxRtrAdvInterval % 1000)
df9c8c57 1463 zvrf->rtadv.adv_msec_if_count--;
d62a17ae 1464
3ea48364
DS
1465 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1466
1467 if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1468 zif->rtadv.MaxRtrAdvInterval = 10000;
1469 else
1470 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
1471
d62a17ae 1472 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
3ea48364 1473 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
d62a17ae 1474
1475 return CMD_SUCCESS;
718e3744 1476}
1477
1478DEFUN (ipv6_nd_ra_lifetime,
1479 ipv6_nd_ra_lifetime_cmd,
6147e2c6 1480 "ipv6 nd ra-lifetime (0-9000)",
3e31cded 1481 "Interface IPv6 config commands\n"
718e3744 1482 "Neighbor discovery\n"
1483 "Router lifetime\n"
4afa50b3 1484 "Router lifetime in seconds (0 stands for a non-default gw)\n")
718e3744 1485{
d62a17ae 1486 int idx_number = 3;
1487 VTY_DECLVAR_CONTEXT(interface, ifp);
1488 struct zebra_if *zif = ifp->info;
1489 int lifetime;
1490
1491 lifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1492
1493 /* The value to be placed in the Router Lifetime field
1494 * of Router Advertisements sent from the interface,
1495 * in seconds. MUST be either zero or between
1496 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1497 if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) {
1498 vty_out(vty,
1499 "This ra-lifetime would conflict with configured ra-interval\n");
1500 return CMD_WARNING_CONFIG_FAILED;
1501 }
1502
1503 zif->rtadv.AdvDefaultLifetime = lifetime;
1504
1505 return CMD_SUCCESS;
718e3744 1506}
1507
1508DEFUN (no_ipv6_nd_ra_lifetime,
1509 no_ipv6_nd_ra_lifetime_cmd,
34ccea1e 1510 "no ipv6 nd ra-lifetime [(0-9000)]",
718e3744 1511 NO_STR
3e31cded 1512 "Interface IPv6 config commands\n"
718e3744 1513 "Neighbor discovery\n"
34ccea1e
QY
1514 "Router lifetime\n"
1515 "Router lifetime in seconds (0 stands for a non-default gw)\n")
718e3744 1516{
d62a17ae 1517 VTY_DECLVAR_CONTEXT(interface, ifp);
1518 struct zebra_if *zif = ifp->info;
718e3744 1519
d62a17ae 1520 zif->rtadv.AdvDefaultLifetime = -1;
718e3744 1521
d62a17ae 1522 return CMD_SUCCESS;
718e3744 1523}
1524
1525DEFUN (ipv6_nd_reachable_time,
1526 ipv6_nd_reachable_time_cmd,
6147e2c6 1527 "ipv6 nd reachable-time (1-3600000)",
3e31cded 1528 "Interface IPv6 config commands\n"
718e3744 1529 "Neighbor discovery\n"
1530 "Reachable time\n"
1531 "Reachable time in milliseconds\n")
1532{
d62a17ae 1533 int idx_number = 3;
1534 VTY_DECLVAR_CONTEXT(interface, ifp);
1535 struct zebra_if *zif = ifp->info;
1536 zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10);
1537 return CMD_SUCCESS;
718e3744 1538}
1539
1540DEFUN (no_ipv6_nd_reachable_time,
1541 no_ipv6_nd_reachable_time_cmd,
34ccea1e 1542 "no ipv6 nd reachable-time [(1-3600000)]",
718e3744 1543 NO_STR
3e31cded 1544 "Interface IPv6 config commands\n"
718e3744 1545 "Neighbor discovery\n"
34ccea1e
QY
1546 "Reachable time\n"
1547 "Reachable time in milliseconds\n")
718e3744 1548{
d62a17ae 1549 VTY_DECLVAR_CONTEXT(interface, ifp);
1550 struct zebra_if *zif = ifp->info;
718e3744 1551
d62a17ae 1552 zif->rtadv.AdvReachableTime = 0;
718e3744 1553
d62a17ae 1554 return CMD_SUCCESS;
718e3744 1555}
1556
7cee1bb1 1557DEFUN (ipv6_nd_homeagent_preference,
1558 ipv6_nd_homeagent_preference_cmd,
6147e2c6 1559 "ipv6 nd home-agent-preference (0-65535)",
7cee1bb1 1560 "Interface IPv6 config commands\n"
1561 "Neighbor discovery\n"
1562 "Home Agent preference\n"
4afa50b3 1563 "preference value (default is 0, least preferred)\n")
7cee1bb1 1564{
d62a17ae 1565 int idx_number = 3;
1566 VTY_DECLVAR_CONTEXT(interface, ifp);
1567 struct zebra_if *zif = ifp->info;
1568 zif->rtadv.HomeAgentPreference =
1569 strtoul(argv[idx_number]->arg, NULL, 10);
1570 return CMD_SUCCESS;
7cee1bb1 1571}
1572
1573DEFUN (no_ipv6_nd_homeagent_preference,
1574 no_ipv6_nd_homeagent_preference_cmd,
34ccea1e 1575 "no ipv6 nd home-agent-preference [(0-65535)]",
7cee1bb1 1576 NO_STR
1577 "Interface IPv6 config commands\n"
1578 "Neighbor discovery\n"
34ccea1e
QY
1579 "Home Agent preference\n"
1580 "preference value (default is 0, least preferred)\n")
7cee1bb1 1581{
d62a17ae 1582 VTY_DECLVAR_CONTEXT(interface, ifp);
1583 struct zebra_if *zif = ifp->info;
7cee1bb1 1584
d62a17ae 1585 zif->rtadv.HomeAgentPreference = 0;
7cee1bb1 1586
d62a17ae 1587 return CMD_SUCCESS;
7cee1bb1 1588}
1589
1590DEFUN (ipv6_nd_homeagent_lifetime,
1591 ipv6_nd_homeagent_lifetime_cmd,
6147e2c6 1592 "ipv6 nd home-agent-lifetime (0-65520)",
7cee1bb1 1593 "Interface IPv6 config commands\n"
1594 "Neighbor discovery\n"
1595 "Home Agent lifetime\n"
4afa50b3 1596 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
7cee1bb1 1597{
d62a17ae 1598 int idx_number = 3;
1599 VTY_DECLVAR_CONTEXT(interface, ifp);
1600 struct zebra_if *zif = ifp->info;
1601 zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1602 return CMD_SUCCESS;
7cee1bb1 1603}
1604
1605DEFUN (no_ipv6_nd_homeagent_lifetime,
1606 no_ipv6_nd_homeagent_lifetime_cmd,
34ccea1e 1607 "no ipv6 nd home-agent-lifetime [(0-65520)]",
7cee1bb1 1608 NO_STR
1609 "Interface IPv6 config commands\n"
1610 "Neighbor discovery\n"
34ccea1e
QY
1611 "Home Agent lifetime\n"
1612 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
7cee1bb1 1613{
d62a17ae 1614 VTY_DECLVAR_CONTEXT(interface, ifp);
1615 struct zebra_if *zif = ifp->info;
7cee1bb1 1616
d62a17ae 1617 zif->rtadv.HomeAgentLifetime = -1;
7cee1bb1 1618
d62a17ae 1619 return CMD_SUCCESS;
7cee1bb1 1620}
1621
718e3744 1622DEFUN (ipv6_nd_managed_config_flag,
1623 ipv6_nd_managed_config_flag_cmd,
1624 "ipv6 nd managed-config-flag",
3e31cded 1625 "Interface IPv6 config commands\n"
718e3744 1626 "Neighbor discovery\n"
1627 "Managed address configuration flag\n")
1628{
d62a17ae 1629 VTY_DECLVAR_CONTEXT(interface, ifp);
1630 struct zebra_if *zif = ifp->info;
718e3744 1631
d62a17ae 1632 zif->rtadv.AdvManagedFlag = 1;
718e3744 1633
d62a17ae 1634 return CMD_SUCCESS;
718e3744 1635}
1636
1637DEFUN (no_ipv6_nd_managed_config_flag,
1638 no_ipv6_nd_managed_config_flag_cmd,
1639 "no ipv6 nd managed-config-flag",
1640 NO_STR
3e31cded 1641 "Interface IPv6 config commands\n"
718e3744 1642 "Neighbor discovery\n"
1643 "Managed address configuration flag\n")
1644{
d62a17ae 1645 VTY_DECLVAR_CONTEXT(interface, ifp);
1646 struct zebra_if *zif = ifp->info;
718e3744 1647
d62a17ae 1648 zif->rtadv.AdvManagedFlag = 0;
718e3744 1649
d62a17ae 1650 return CMD_SUCCESS;
718e3744 1651}
1652
7cee1bb1 1653DEFUN (ipv6_nd_homeagent_config_flag,
1654 ipv6_nd_homeagent_config_flag_cmd,
1655 "ipv6 nd home-agent-config-flag",
1656 "Interface IPv6 config commands\n"
1657 "Neighbor discovery\n"
1658 "Home Agent configuration flag\n")
1659{
d62a17ae 1660 VTY_DECLVAR_CONTEXT(interface, ifp);
1661 struct zebra_if *zif = ifp->info;
7cee1bb1 1662
d62a17ae 1663 zif->rtadv.AdvHomeAgentFlag = 1;
7cee1bb1 1664
d62a17ae 1665 return CMD_SUCCESS;
7cee1bb1 1666}
1667
1668DEFUN (no_ipv6_nd_homeagent_config_flag,
1669 no_ipv6_nd_homeagent_config_flag_cmd,
1670 "no ipv6 nd home-agent-config-flag",
1671 NO_STR
1672 "Interface IPv6 config commands\n"
1673 "Neighbor discovery\n"
1674 "Home Agent configuration flag\n")
1675{
d62a17ae 1676 VTY_DECLVAR_CONTEXT(interface, ifp);
1677 struct zebra_if *zif = ifp->info;
7cee1bb1 1678
d62a17ae 1679 zif->rtadv.AdvHomeAgentFlag = 0;
7cee1bb1 1680
d62a17ae 1681 return CMD_SUCCESS;
7cee1bb1 1682}
1683
1684DEFUN (ipv6_nd_adv_interval_config_option,
1685 ipv6_nd_adv_interval_config_option_cmd,
1686 "ipv6 nd adv-interval-option",
1687 "Interface IPv6 config commands\n"
1688 "Neighbor discovery\n"
1689 "Advertisement Interval Option\n")
1690{
d62a17ae 1691 VTY_DECLVAR_CONTEXT(interface, ifp);
1692 struct zebra_if *zif = ifp->info;
7cee1bb1 1693
d62a17ae 1694 zif->rtadv.AdvIntervalOption = 1;
7cee1bb1 1695
d62a17ae 1696 return CMD_SUCCESS;
7cee1bb1 1697}
1698
1699DEFUN (no_ipv6_nd_adv_interval_config_option,
1700 no_ipv6_nd_adv_interval_config_option_cmd,
1701 "no ipv6 nd adv-interval-option",
1702 NO_STR
1703 "Interface IPv6 config commands\n"
1704 "Neighbor discovery\n"
1705 "Advertisement Interval Option\n")
1706{
d62a17ae 1707 VTY_DECLVAR_CONTEXT(interface, ifp);
1708 struct zebra_if *zif = ifp->info;
7cee1bb1 1709
d62a17ae 1710 zif->rtadv.AdvIntervalOption = 0;
7cee1bb1 1711
d62a17ae 1712 return CMD_SUCCESS;
7cee1bb1 1713}
1714
718e3744 1715DEFUN (ipv6_nd_other_config_flag,
1716 ipv6_nd_other_config_flag_cmd,
1717 "ipv6 nd other-config-flag",
3e31cded 1718 "Interface IPv6 config commands\n"
718e3744 1719 "Neighbor discovery\n"
1720 "Other statefull configuration flag\n")
1721{
d62a17ae 1722 VTY_DECLVAR_CONTEXT(interface, ifp);
1723 struct zebra_if *zif = ifp->info;
718e3744 1724
d62a17ae 1725 zif->rtadv.AdvOtherConfigFlag = 1;
718e3744 1726
d62a17ae 1727 return CMD_SUCCESS;
718e3744 1728}
1729
1730DEFUN (no_ipv6_nd_other_config_flag,
1731 no_ipv6_nd_other_config_flag_cmd,
1732 "no ipv6 nd other-config-flag",
1733 NO_STR
3e31cded 1734 "Interface IPv6 config commands\n"
718e3744 1735 "Neighbor discovery\n"
1736 "Other statefull configuration flag\n")
1737{
d62a17ae 1738 VTY_DECLVAR_CONTEXT(interface, ifp);
1739 struct zebra_if *zif = ifp->info;
718e3744 1740
d62a17ae 1741 zif->rtadv.AdvOtherConfigFlag = 0;
718e3744 1742
d62a17ae 1743 return CMD_SUCCESS;
718e3744 1744}
1745
3e31cded 1746DEFUN (ipv6_nd_prefix,
1747 ipv6_nd_prefix_cmd,
34ccea1e 1748 "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
3e31cded 1749 "Interface IPv6 config commands\n"
718e3744 1750 "Neighbor discovery\n"
1751 "Prefix information\n"
1752 "IPv6 prefix\n"
1753 "Valid lifetime in seconds\n"
3e31cded 1754 "Infinite valid lifetime\n"
718e3744 1755 "Preferred lifetime in seconds\n"
3e31cded 1756 "Infinite preferred lifetime\n"
34ccea1e 1757 "Set Router Address flag\n"
3e31cded 1758 "Do not use prefix for onlink determination\n"
7cee1bb1 1759 "Do not use prefix for autoconfiguration\n"
34ccea1e
QY
1760 "Do not use prefix for autoconfiguration\n"
1761 "Do not use prefix for onlink determination\n")
718e3744 1762{
d62a17ae 1763 /* prelude */
1764 char *prefix = argv[3]->arg;
9d303b37
DL
1765 int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
1766 || strmatch(argv[4]->text, "infinite"));
d62a17ae 1767 int routeropts = lifetimes ? argc > 6 : argc > 4;
1768
1769 int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
1770
1771 char *lifetime = NULL, *preflifetime = NULL;
1772 int routeraddr = 0, offlink = 0, noautoconf = 0;
1773 if (lifetimes) {
1774 lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
1775 : argv[4]->text;
1776 preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg
1777 : argv[5]->text;
1778 }
1779 if (routeropts) {
1780 routeraddr =
1781 strmatch(argv[idx_routeropts]->text, "router-address");
1782 if (!routeraddr) {
1783 offlink = (argc > idx_routeropts + 1
1784 || strmatch(argv[idx_routeropts]->text,
1785 "off-link"));
1786 noautoconf = (argc > idx_routeropts + 1
1787 || strmatch(argv[idx_routeropts]->text,
1788 "no-autoconfig"));
1789 }
1790 }
1791
1792 /* business */
1793 VTY_DECLVAR_CONTEXT(interface, ifp);
1794 struct zebra_if *zebra_if = ifp->info;
1795 int ret;
1796 struct rtadv_prefix rp;
1797
1798 ret = str2prefix_ipv6(prefix, &rp.prefix);
1799 if (!ret) {
1800 vty_out(vty, "Malformed IPv6 prefix\n");
1801 return CMD_WARNING_CONFIG_FAILED;
1802 }
1803 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
1804 rp.AdvOnLinkFlag = !offlink;
1805 rp.AdvAutonomousFlag = !noautoconf;
1806 rp.AdvRouterAddressFlag = routeraddr;
1807 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1808 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
2a855763 1809 rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
d62a17ae 1810
1811 if (lifetimes) {
1812 rp.AdvValidLifetime = strmatch(lifetime, "infinite")
1813 ? UINT32_MAX
1814 : strtoll(lifetime, NULL, 10);
1815 rp.AdvPreferredLifetime =
1816 strmatch(preflifetime, "infinite")
1817 ? UINT32_MAX
1818 : strtoll(preflifetime, NULL, 10);
1819 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) {
1820 vty_out(vty, "Invalid preferred lifetime\n");
1821 return CMD_WARNING_CONFIG_FAILED;
1822 }
1823 }
1824
1825 rtadv_prefix_set(zebra_if, &rp);
1826
1827 return CMD_SUCCESS;
718e3744 1828}
1829
3e31cded 1830DEFUN (no_ipv6_nd_prefix,
1831 no_ipv6_nd_prefix_cmd,
34ccea1e
QY
1832 "no ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
1833 NO_STR
3e31cded 1834 "Interface IPv6 config commands\n"
718e3744 1835 "Neighbor discovery\n"
1836 "Prefix information\n"
34ccea1e
QY
1837 "IPv6 prefix\n"
1838 "Valid lifetime in seconds\n"
1839 "Infinite valid lifetime\n"
1840 "Preferred lifetime in seconds\n"
1841 "Infinite preferred lifetime\n"
1842 "Set Router Address flag\n"
1843 "Do not use prefix for onlink determination\n"
1844 "Do not use prefix for autoconfiguration\n"
1845 "Do not use prefix for autoconfiguration\n"
1846 "Do not use prefix for onlink determination\n")
718e3744 1847{
d62a17ae 1848 VTY_DECLVAR_CONTEXT(interface, ifp);
1849 struct zebra_if *zebra_if = ifp->info;
1850 int ret;
1851 struct rtadv_prefix rp;
1852 char *prefix = argv[4]->arg;
1853
1854 ret = str2prefix_ipv6(prefix, &rp.prefix);
1855 if (!ret) {
1856 vty_out(vty, "Malformed IPv6 prefix\n");
1857 return CMD_WARNING_CONFIG_FAILED;
1858 }
1859 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
2a855763 1860 rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
d62a17ae 1861
1862 ret = rtadv_prefix_reset(zebra_if, &rp);
1863 if (!ret) {
1864 vty_out(vty, "Non-existant IPv6 prefix\n");
1865 return CMD_WARNING_CONFIG_FAILED;
1866 }
1867
1868 return CMD_SUCCESS;
718e3744 1869}
b60668d0
CC
1870
1871DEFUN (ipv6_nd_router_preference,
1872 ipv6_nd_router_preference_cmd,
6147e2c6 1873 "ipv6 nd router-preference <high|medium|low>",
b60668d0
CC
1874 "Interface IPv6 config commands\n"
1875 "Neighbor discovery\n"
1876 "Default router preference\n"
1877 "High default router preference\n"
58f1b7cc
DS
1878 "Medium default router preference (default)\n"
1879 "Low default router preference\n")
b60668d0 1880{
d62a17ae 1881 int idx_high_medium_low = 3;
1882 VTY_DECLVAR_CONTEXT(interface, ifp);
1883 struct zebra_if *zif = ifp->info;
1884 int i = 0;
1885
1886 while (0 != rtadv_pref_strs[i]) {
1887 if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i],
1888 1)
1889 == 0) {
1890 zif->rtadv.DefaultPreference = i;
1891 return CMD_SUCCESS;
1892 }
1893 i++;
b60668d0 1894 }
b60668d0 1895
d62a17ae 1896 return CMD_ERR_NO_MATCH;
b60668d0
CC
1897}
1898
1899DEFUN (no_ipv6_nd_router_preference,
1900 no_ipv6_nd_router_preference_cmd,
34ccea1e 1901 "no ipv6 nd router-preference [<high|medium|low>]",
b60668d0
CC
1902 NO_STR
1903 "Interface IPv6 config commands\n"
1904 "Neighbor discovery\n"
34ccea1e
QY
1905 "Default router preference\n"
1906 "High default router preference\n"
1907 "Medium default router preference (default)\n"
1908 "Low default router preference\n")
b60668d0 1909{
d62a17ae 1910 VTY_DECLVAR_CONTEXT(interface, ifp);
1911 struct zebra_if *zif = ifp->info;
b60668d0 1912
d62a17ae 1913 zif->rtadv.DefaultPreference =
1914 RTADV_PREF_MEDIUM; /* Default per RFC4191. */
b60668d0 1915
d62a17ae 1916 return CMD_SUCCESS;
b60668d0
CC
1917}
1918
6ae93c05
DO
1919DEFUN (ipv6_nd_mtu,
1920 ipv6_nd_mtu_cmd,
6147e2c6 1921 "ipv6 nd mtu (1-65535)",
6ae93c05
DO
1922 "Interface IPv6 config commands\n"
1923 "Neighbor discovery\n"
1924 "Advertised MTU\n"
1925 "MTU in bytes\n")
1926{
d62a17ae 1927 int idx_number = 3;
1928 VTY_DECLVAR_CONTEXT(interface, ifp);
1929 struct zebra_if *zif = ifp->info;
1930 zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10);
1931 return CMD_SUCCESS;
6ae93c05
DO
1932}
1933
1934DEFUN (no_ipv6_nd_mtu,
1935 no_ipv6_nd_mtu_cmd,
34ccea1e 1936 "no ipv6 nd mtu [(1-65535)]",
6ae93c05
DO
1937 NO_STR
1938 "Interface IPv6 config commands\n"
1939 "Neighbor discovery\n"
34ccea1e
QY
1940 "Advertised MTU\n"
1941 "MTU in bytes\n")
6ae93c05 1942{
d62a17ae 1943 VTY_DECLVAR_CONTEXT(interface, ifp);
1944 struct zebra_if *zif = ifp->info;
1945 zif->rtadv.AdvLinkMTU = 0;
1946 return CMD_SUCCESS;
6ae93c05
DO
1947}
1948
3eb4fbb0
LS
1949static struct rtadv_rdnss *rtadv_rdnss_new(void)
1950{
1951 return XCALLOC(MTYPE_RTADV_RDNSS, sizeof(struct rtadv_rdnss));
1952}
1953
1954static void rtadv_rdnss_free(struct rtadv_rdnss *rdnss)
1955{
1956 XFREE(MTYPE_RTADV_RDNSS, rdnss);
1957}
1958
1959static struct rtadv_rdnss *rtadv_rdnss_lookup(struct list *list,
1960 struct rtadv_rdnss *rdnss)
1961{
1962 struct listnode *node;
1963 struct rtadv_rdnss *p;
1964
1965 for (ALL_LIST_ELEMENTS_RO(list, node, p))
1966 if (IPV6_ADDR_SAME(&p->addr, &rdnss->addr))
1967 return p;
1968 return NULL;
1969}
1970
1971static struct rtadv_rdnss *rtadv_rdnss_get(struct list *list,
1972 struct rtadv_rdnss *rdnss)
1973{
1974 struct rtadv_rdnss *p;
1975
1976 p = rtadv_rdnss_lookup(list, rdnss);
1977 if (p)
1978 return p;
1979
1980 p = rtadv_rdnss_new();
1981 memcpy(p, rdnss, sizeof(struct rtadv_rdnss));
1982 listnode_add(list, p);
1983
1984 return p;
1985}
1986
1987static void rtadv_rdnss_set(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
1988{
1989 struct rtadv_rdnss *p;
1990
1991 p = rtadv_rdnss_get(zif->rtadv.AdvRDNSSList, rdnss);
1992 p->lifetime = rdnss->lifetime;
1993 p->lifetime_set = rdnss->lifetime_set;
1994}
1995
1996static int rtadv_rdnss_reset(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
1997{
1998 struct rtadv_rdnss *p;
1999
2000 p = rtadv_rdnss_lookup(zif->rtadv.AdvRDNSSList, rdnss);
2001 if (p) {
2002 listnode_delete(zif->rtadv.AdvRDNSSList, p);
2003 rtadv_rdnss_free(p);
2004 return 1;
2005 }
2006
2007 return 0;
2008}
2009
2010static struct rtadv_dnssl *rtadv_dnssl_new(void)
2011{
2012 return XCALLOC(MTYPE_RTADV_DNSSL, sizeof(struct rtadv_dnssl));
2013}
2014
2015static void rtadv_dnssl_free(struct rtadv_dnssl *dnssl)
2016{
2017 XFREE(MTYPE_RTADV_DNSSL, dnssl);
2018}
2019
2020static struct rtadv_dnssl *rtadv_dnssl_lookup(struct list *list,
2021 struct rtadv_dnssl *dnssl)
2022{
2023 struct listnode *node;
2024 struct rtadv_dnssl *p;
2025
2026 for (ALL_LIST_ELEMENTS_RO(list, node, p))
2027 if (!strcasecmp(p->name, dnssl->name))
2028 return p;
2029 return NULL;
2030}
2031
2032static struct rtadv_dnssl *rtadv_dnssl_get(struct list *list,
2033 struct rtadv_dnssl *dnssl)
2034{
2035 struct rtadv_dnssl *p;
2036
2037 p = rtadv_dnssl_lookup(list, dnssl);
2038 if (p)
2039 return p;
2040
2041 p = rtadv_dnssl_new();
2042 memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
2043 listnode_add(list, p);
2044
2045 return p;
2046}
2047
2048static void rtadv_dnssl_set(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
2049{
2050 struct rtadv_dnssl *p;
2051
2052 p = rtadv_dnssl_get(zif->rtadv.AdvDNSSLList, dnssl);
2053 memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
2054}
2055
2056static int rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
2057{
2058 struct rtadv_dnssl *p;
2059
2060 p = rtadv_dnssl_lookup(zif->rtadv.AdvDNSSLList, dnssl);
2061 if (p) {
2062 listnode_delete(zif->rtadv.AdvDNSSLList, p);
2063 rtadv_dnssl_free(p);
2064 return 1;
2065 }
2066
2067 return 0;
2068}
2069
2070/*
2071 * Convert dotted domain name (with or without trailing root zone dot) to
2072 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2073 * to strlen(in) + 2 octets to out.
2074 *
2075 * Returns the number of octets written to out or -1 if in does not constitute
2076 * a valid domain name.
2077 */
2078static int rtadv_dnssl_encode(uint8_t *out, const char *in)
2079{
2080 const char *label_start, *label_end;
2081 size_t outp;
2082
2083 outp = 0;
2084 label_start = in;
2085
2086 while (*label_start) {
2087 size_t label_len;
2088
2089 label_end = strchr(label_start, '.');
2090 if (label_end == NULL)
2091 label_end = label_start + strlen(label_start);
2092
2093 label_len = label_end - label_start;
2094 if (label_len >= 64)
2095 return -1; /* labels must be 63 octets or less */
2096
2097 out[outp++] = (uint8_t)label_len;
2098 memcpy(out + outp, label_start, label_len);
2099 outp += label_len;
2100 label_start += label_len;
2101 if (*label_start == '.')
2102 label_start++;
2103 }
2104
2105 out[outp++] = '\0';
2106 return outp;
2107}
2108
2109DEFUN(ipv6_nd_rdnss,
2110 ipv6_nd_rdnss_cmd,
2111 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2112 "Interface IPv6 config commands\n"
2113 "Neighbor discovery\n"
2114 "Recursive DNS server information\n"
2115 "IPv6 address\n"
2116 "Valid lifetime in seconds\n"
2117 "Infinite valid lifetime\n")
2118{
2119 VTY_DECLVAR_CONTEXT(interface, ifp);
2120 struct zebra_if *zif = ifp->info;
844e9180 2121 struct rtadv_rdnss rdnss = {};
3eb4fbb0
LS
2122
2123 if (inet_pton(AF_INET6, argv[3]->arg, &rdnss.addr) != 1) {
2124 vty_out(vty, "Malformed IPv6 address\n");
2125 return CMD_WARNING_CONFIG_FAILED;
2126 }
2127 if (argc > 4) {
2128 char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
2129 : argv[4]->text;
2130 rdnss.lifetime = strmatch(lifetime, "infinite")
2131 ? UINT32_MAX
2132 : strtoll(lifetime, NULL, 10);
2133 rdnss.lifetime_set = 1;
2134 }
2135
2136 rtadv_rdnss_set(zif, &rdnss);
2137
2138 return CMD_SUCCESS;
2139}
2140
2141DEFUN(no_ipv6_nd_rdnss,
2142 no_ipv6_nd_rdnss_cmd,
2143 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2144 NO_STR
2145 "Interface IPv6 config commands\n"
2146 "Neighbor discovery\n"
2147 "Recursive DNS server information\n"
2148 "IPv6 address\n"
2149 "Valid lifetime in seconds\n"
2150 "Infinite valid lifetime\n")
2151{
2152 VTY_DECLVAR_CONTEXT(interface, ifp);
2153 struct zebra_if *zif = ifp->info;
844e9180 2154 struct rtadv_rdnss rdnss = {};
3eb4fbb0
LS
2155
2156 if (inet_pton(AF_INET6, argv[4]->arg, &rdnss.addr) != 1) {
2157 vty_out(vty, "Malformed IPv6 address\n");
2158 return CMD_WARNING_CONFIG_FAILED;
2159 }
2160 if (rtadv_rdnss_reset(zif, &rdnss) != 1) {
2161 vty_out(vty, "Non-existant RDNSS address\n");
2162 return CMD_WARNING_CONFIG_FAILED;
2163 }
2164
2165 return CMD_SUCCESS;
2166}
2167
2168DEFUN(ipv6_nd_dnssl,
2169 ipv6_nd_dnssl_cmd,
2170 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2171 "Interface IPv6 config commands\n"
2172 "Neighbor discovery\n"
2173 "DNS search list information\n"
2174 "Domain name suffix\n"
2175 "Valid lifetime in seconds\n"
2176 "Infinite valid lifetime\n")
2177{
2178 VTY_DECLVAR_CONTEXT(interface, ifp);
2179 struct zebra_if *zif = ifp->info;
844e9180 2180 struct rtadv_dnssl dnssl = {};
3eb4fbb0
LS
2181 size_t len;
2182 int ret;
2183
2184 len = strlcpy(dnssl.name, argv[3]->arg, sizeof(dnssl.name));
2185 if (len == 0 || len >= sizeof(dnssl.name)) {
2186 vty_out(vty, "Malformed DNS search domain\n");
2187 return CMD_WARNING_CONFIG_FAILED;
2188 }
2189 if (dnssl.name[len - 1] == '.') {
2190 /*
2191 * Allow, but don't require, a trailing dot signifying the root
2192 * zone. Canonicalize by cutting it off if present.
2193 */
2194 dnssl.name[len - 1] = '\0';
2195 len--;
2196 }
2197 if (argc > 4) {
2198 char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
2199 : argv[4]->text;
2200 dnssl.lifetime = strmatch(lifetime, "infinite")
2201 ? UINT32_MAX
2202 : strtoll(lifetime, NULL, 10);
2203 dnssl.lifetime_set = 1;
2204 }
2205
2206 ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
2207 if (ret < 0) {
2208 vty_out(vty, "Malformed DNS search domain\n");
2209 return CMD_WARNING_CONFIG_FAILED;
2210 }
2211 dnssl.encoded_len = ret;
2212 rtadv_dnssl_set(zif, &dnssl);
2213
2214 return CMD_SUCCESS;
2215}
2216
2217DEFUN(no_ipv6_nd_dnssl,
2218 no_ipv6_nd_dnssl_cmd,
2219 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2220 NO_STR
2221 "Interface IPv6 config commands\n"
2222 "Neighbor discovery\n"
2223 "DNS search list information\n"
2224 "Domain name suffix\n"
2225 "Valid lifetime in seconds\n"
2226 "Infinite valid lifetime\n")
2227{
2228 VTY_DECLVAR_CONTEXT(interface, ifp);
2229 struct zebra_if *zif = ifp->info;
844e9180 2230 struct rtadv_dnssl dnssl = {};
3eb4fbb0
LS
2231 size_t len;
2232
2233 len = strlcpy(dnssl.name, argv[4]->arg, sizeof(dnssl.name));
2234 if (len == 0 || len >= sizeof(dnssl.name)) {
2235 vty_out(vty, "Malformed DNS search domain\n");
2236 return CMD_WARNING_CONFIG_FAILED;
2237 }
2238 if (dnssl.name[len - 1] == '.') {
2239 dnssl.name[len - 1] = '\0';
2240 len--;
2241 }
2242 if (rtadv_dnssl_reset(zif, &dnssl) != 1) {
2243 vty_out(vty, "Non-existant DNS search domain\n");
2244 return CMD_WARNING_CONFIG_FAILED;
2245 }
2246
2247 return CMD_SUCCESS;
2248}
2249
2250
2eb27eec
DL
2251/* Dump interface ND information to vty. */
2252static int nd_dump_vty(struct vty *vty, struct interface *ifp)
2253{
2254 struct zebra_if *zif;
2255 struct rtadvconf *rtadv;
2256 int interval;
2257
2258 zif = (struct zebra_if *)ifp->info;
2259 rtadv = &zif->rtadv;
2260
2261 if (rtadv->AdvSendAdvertisements) {
2262 vty_out(vty,
2263 " ND advertised reachable time is %d milliseconds\n",
2264 rtadv->AdvReachableTime);
2265 vty_out(vty,
b19ac878 2266 " ND advertised retransmit interval is %u milliseconds\n",
2eb27eec 2267 rtadv->AdvRetransTimer);
fae01935
DS
2268 vty_out(vty, " ND advertised hop-count limit is %d hops\n",
2269 rtadv->AdvCurHopLimit);
2eb27eec
DL
2270 vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n",
2271 zif->ra_sent, zif->ra_rcvd);
2272 interval = rtadv->MaxRtrAdvInterval;
2273 if (interval % 1000)
2274 vty_out(vty,
3efd0893 2275 " ND router advertisements are sent every %d milliseconds\n",
2eb27eec
DL
2276 interval);
2277 else
2278 vty_out(vty,
3efd0893 2279 " ND router advertisements are sent every %d seconds\n",
2eb27eec 2280 interval / 1000);
adee8f21
DS
2281 if (!rtadv->UseFastRexmit)
2282 vty_out(vty,
2283 " ND router advertisements do not use fast retransmit\n");
2284
2eb27eec
DL
2285 if (rtadv->AdvDefaultLifetime != -1)
2286 vty_out(vty,
2287 " ND router advertisements live for %d seconds\n",
2288 rtadv->AdvDefaultLifetime);
2289 else
2290 vty_out(vty,
2291 " ND router advertisements lifetime tracks ra-interval\n");
2292 vty_out(vty,
3efd0893 2293 " ND router advertisement default router preference is %s\n",
2eb27eec
DL
2294 rtadv_pref_strs[rtadv->DefaultPreference]);
2295 if (rtadv->AdvManagedFlag)
2296 vty_out(vty,
2297 " Hosts use DHCP to obtain routable addresses.\n");
2298 else
2299 vty_out(vty,
2300 " Hosts use stateless autoconfig for addresses.\n");
2301 if (rtadv->AdvHomeAgentFlag) {
2302 vty_out(vty,
2303 " ND router advertisements with Home Agent flag bit set.\n");
2304 if (rtadv->HomeAgentLifetime != -1)
2305 vty_out(vty,
2306 " Home Agent lifetime is %u seconds\n",
2307 rtadv->HomeAgentLifetime);
2308 else
2309 vty_out(vty,
2310 " Home Agent lifetime tracks ra-lifetime\n");
2311 vty_out(vty, " Home Agent preference is %u\n",
2312 rtadv->HomeAgentPreference);
2313 }
2314 if (rtadv->AdvIntervalOption)
2315 vty_out(vty,
2316 " ND router advertisements with Adv. Interval option.\n");
2317 }
2318 return 0;
2319}
2320
6ae93c05 2321
718e3744 2322/* Write configuration about router advertisement. */
2eb27eec 2323static int rtadv_config_write(struct vty *vty, struct interface *ifp)
718e3744 2324{
d62a17ae 2325 struct zebra_if *zif;
2326 struct listnode *node;
2327 struct rtadv_prefix *rprefix;
3eb4fbb0
LS
2328 struct rtadv_rdnss *rdnss;
2329 struct rtadv_dnssl *dnssl;
d62a17ae 2330 int interval;
2331
2332 zif = ifp->info;
2333
2334 if (!(if_is_loopback(ifp)
2335 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) {
3ea48364
DS
2336 if (zif->rtadv.AdvSendAdvertisements
2337 && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
d62a17ae 2338 vty_out(vty, " no ipv6 nd suppress-ra\n");
2339 }
2340
2341 interval = zif->rtadv.MaxRtrAdvInterval;
3ea48364
DS
2342 if (CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) {
2343 if (interval % 1000)
2344 vty_out(vty, " ipv6 nd ra-interval msec %d\n",
2345 interval);
2346 else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
2347 vty_out(vty, " ipv6 nd ra-interval %d\n",
2348 interval / 1000);
2349 }
d62a17ae 2350
2351 if (zif->rtadv.AdvIntervalOption)
2352 vty_out(vty, " ipv6 nd adv-interval-option\n");
2353
adee8f21
DS
2354 if (!zif->rtadv.UseFastRexmit)
2355 vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
2356
b19ac878
DS
2357 if (zif->rtadv.AdvRetransTimer != 0)
2358 vty_out(vty, " ipv6 nd ra-retrans-interval %u\n",
2359 zif->rtadv.AdvRetransTimer);
2360
fae01935
DS
2361 if (zif->rtadv.AdvCurHopLimit != RTADV_DEFAULT_HOPLIMIT)
2362 vty_out(vty, " ipv6 nd ra-hop-limit %d\n",
2363 zif->rtadv.AdvCurHopLimit);
2364
d62a17ae 2365 if (zif->rtadv.AdvDefaultLifetime != -1)
2366 vty_out(vty, " ipv6 nd ra-lifetime %d\n",
2367 zif->rtadv.AdvDefaultLifetime);
2368
2369 if (zif->rtadv.HomeAgentPreference)
2370 vty_out(vty, " ipv6 nd home-agent-preference %u\n",
2371 zif->rtadv.HomeAgentPreference);
2372
2373 if (zif->rtadv.HomeAgentLifetime != -1)
2374 vty_out(vty, " ipv6 nd home-agent-lifetime %u\n",
2375 zif->rtadv.HomeAgentLifetime);
2376
2377 if (zif->rtadv.AdvHomeAgentFlag)
2378 vty_out(vty, " ipv6 nd home-agent-config-flag\n");
2379
2380 if (zif->rtadv.AdvReachableTime)
2381 vty_out(vty, " ipv6 nd reachable-time %d\n",
2382 zif->rtadv.AdvReachableTime);
2383
2384 if (zif->rtadv.AdvManagedFlag)
2385 vty_out(vty, " ipv6 nd managed-config-flag\n");
2386
2387 if (zif->rtadv.AdvOtherConfigFlag)
2388 vty_out(vty, " ipv6 nd other-config-flag\n");
2389
2390 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
2391 vty_out(vty, " ipv6 nd router-preference %s\n",
2392 rtadv_pref_strs[zif->rtadv.DefaultPreference]);
2393
2394 if (zif->rtadv.AdvLinkMTU)
2395 vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU);
2396
2397 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) {
2a855763
DS
2398 if ((rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
2399 || (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH)) {
2dbe669b 2400 vty_out(vty, " ipv6 nd prefix %pFX", &rprefix->prefix);
2a855763
DS
2401 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME)
2402 || (rprefix->AdvPreferredLifetime
2403 != RTADV_PREFERRED_LIFETIME)) {
2404 if (rprefix->AdvValidLifetime == UINT32_MAX)
2405 vty_out(vty, " infinite");
2406 else
2407 vty_out(vty, " %u",
2408 rprefix->AdvValidLifetime);
2409 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
2410 vty_out(vty, " infinite");
2411 else
2412 vty_out(vty, " %u",
2413 rprefix->AdvPreferredLifetime);
2414 }
2415 if (!rprefix->AdvOnLinkFlag)
2416 vty_out(vty, " off-link");
2417 if (!rprefix->AdvAutonomousFlag)
2418 vty_out(vty, " no-autoconfig");
2419 if (rprefix->AdvRouterAddressFlag)
2420 vty_out(vty, " router-address");
2421 vty_out(vty, "\n");
d62a17ae 2422 }
3e31cded 2423 }
2a855763 2424
3eb4fbb0
LS
2425 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
2426 char buf[INET6_ADDRSTRLEN];
2427
2428 vty_out(vty, " ipv6 nd rdnss %s",
2429 inet_ntop(AF_INET6, &rdnss->addr, buf, sizeof(buf)));
2430 if (rdnss->lifetime_set) {
2431 if (rdnss->lifetime == UINT32_MAX)
2432 vty_out(vty, " infinite");
2433 else
2434 vty_out(vty, " %u", rdnss->lifetime);
2435 }
2436 vty_out(vty, "\n");
2437 }
2438 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
2439 vty_out(vty, " ipv6 nd dnssl %s", dnssl->name);
2440 if (dnssl->lifetime_set) {
2441 if (dnssl->lifetime == UINT32_MAX)
2442 vty_out(vty, " infinite");
2443 else
2444 vty_out(vty, " %u", dnssl->lifetime);
2445 }
2446 vty_out(vty, "\n");
2447 }
2eb27eec 2448 return 0;
718e3744 2449}
2450
718e3744 2451
df9c8c57 2452static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
718e3744 2453{
df9c8c57 2454 struct rtadv *rtadv = &zvrf->rtadv;
d62a17ae 2455
60077146
DS
2456 if (IS_ZEBRA_DEBUG_EVENT) {
2457 struct vrf *vrf = zvrf->vrf;
2458
2459 zlog_debug("%s(%s) with event: %d and val: %d", __func__,
2460 VRF_LOGNAME(vrf), event, val);
2461 }
2462
d62a17ae 2463 switch (event) {
2464 case RTADV_START:
df9c8c57 2465 thread_add_read(zrouter.master, rtadv_read, zvrf, val,
d62a17ae 2466 &rtadv->ra_read);
df9c8c57 2467 thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
d62a17ae 2468 &rtadv->ra_timer);
2469 break;
2470 case RTADV_STOP:
311c15ee
DS
2471 THREAD_OFF(rtadv->ra_timer);
2472 THREAD_OFF(rtadv->ra_read);
d62a17ae 2473 break;
2474 case RTADV_TIMER:
df9c8c57 2475 thread_add_timer(zrouter.master, rtadv_timer, zvrf, val,
d62a17ae 2476 &rtadv->ra_timer);
2477 break;
2478 case RTADV_TIMER_MSEC:
df9c8c57 2479 thread_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val,
d62a17ae 2480 &rtadv->ra_timer);
2481 break;
2482 case RTADV_READ:
df9c8c57 2483 thread_add_read(zrouter.master, rtadv_read, zvrf, val,
d62a17ae 2484 &rtadv->ra_read);
2485 break;
2486 default:
2487 break;
718e3744 2488 }
d62a17ae 2489 return;
718e3744 2490}
2491
df9c8c57 2492void rtadv_init(struct zebra_vrf *zvrf)
718e3744 2493{
9245fe61
PG
2494 if (vrf_is_backend_netns()) {
2495 zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
2496 zrouter.rtadv_sock = -1;
311c15ee 2497 } else {
9245fe61 2498 zvrf->rtadv.sock = -1;
311c15ee
DS
2499 if (zrouter.rtadv_sock < 0)
2500 zrouter.rtadv_sock =
2501 rtadv_make_socket(zvrf->zns->ns_id);
9245fe61 2502 }
cd80d74f 2503}
718e3744 2504
aab5893a 2505void rtadv_vrf_terminate(struct zebra_vrf *zvrf)
cd80d74f 2506{
df9c8c57
PG
2507 rtadv_event(zvrf, RTADV_STOP, 0);
2508 if (zvrf->rtadv.sock >= 0) {
2509 close(zvrf->rtadv.sock);
2510 zvrf->rtadv.sock = -1;
d62a17ae 2511 }
aab5893a 2512
df9c8c57
PG
2513 zvrf->rtadv.adv_if_count = 0;
2514 zvrf->rtadv.adv_msec_if_count = 0;
cd80d74f 2515}
718e3744 2516
aab5893a
DS
2517void rtadv_terminate(void)
2518{
2519 if (zrouter.rtadv_sock >= 0) {
2520 close(zrouter.rtadv_sock);
2521 zrouter.rtadv_sock = -1;
2522 }
2523}
2524
d62a17ae 2525void rtadv_cmd_init(void)
cd80d74f 2526{
2eb27eec
DL
2527 hook_register(zebra_if_extra_info, nd_dump_vty);
2528 hook_register(zebra_if_config_wr, rtadv_config_write);
2529
adee8f21
DS
2530 install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
2531 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
b19ac878
DS
2532 install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
2533 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_retrans_interval_cmd);
fae01935
DS
2534 install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd);
2535 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_hop_limit_cmd);
d62a17ae 2536 install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
2537 install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
2538 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
2539 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
2540 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
2541 install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
2542 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
2543 install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
2544 install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
2545 install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
2546 install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
2547 install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
2548 install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
2549 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
2550 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
2551 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
2552 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
2553 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
2554 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
2555 install_element(INTERFACE_NODE,
2556 &ipv6_nd_adv_interval_config_option_cmd);
2557 install_element(INTERFACE_NODE,
2558 &no_ipv6_nd_adv_interval_config_option_cmd);
2559 install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
2560 install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
2561 install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
2562 install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
2563 install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
2564 install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
3eb4fbb0
LS
2565 install_element(INTERFACE_NODE, &ipv6_nd_rdnss_cmd);
2566 install_element(INTERFACE_NODE, &no_ipv6_nd_rdnss_cmd);
2567 install_element(INTERFACE_NODE, &ipv6_nd_dnssl_cmd);
2568 install_element(INTERFACE_NODE, &no_ipv6_nd_dnssl_cmd);
718e3744 2569}
2570
d62a17ae 2571static int if_join_all_router(int sock, struct interface *ifp)
718e3744 2572{
d62a17ae 2573 int ret;
718e3744 2574
d62a17ae 2575 struct ipv6_mreq mreq;
718e3744 2576
d62a17ae 2577 memset(&mreq, 0, sizeof(struct ipv6_mreq));
2578 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2579 mreq.ipv6mr_interface = ifp->ifindex;
718e3744 2580
d62a17ae 2581 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq,
0d6f7fd6 2582 sizeof(mreq));
d62a17ae 2583 if (ret < 0)
450971aa 2584 flog_err_sys(EC_LIB_SOCKET,
9df414fe
QY
2585 "%s(%u): Failed to join group, socket %u error %s",
2586 ifp->name, ifp->ifindex, sock,
2587 safe_strerror(errno));
718e3744 2588
60077146
DS
2589 if (IS_ZEBRA_DEBUG_EVENT) {
2590 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
2591
d62a17ae 2592 zlog_debug(
60077146
DS
2593 "%s(%s:%u): Join All-Routers multicast group, socket %u",
2594 ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, sock);
2595 }
718e3744 2596
d62a17ae 2597 return 0;
718e3744 2598}
2599
d62a17ae 2600static int if_leave_all_router(int sock, struct interface *ifp)
718e3744 2601{
d62a17ae 2602 int ret;
718e3744 2603
d62a17ae 2604 struct ipv6_mreq mreq;
718e3744 2605
d62a17ae 2606 memset(&mreq, 0, sizeof(struct ipv6_mreq));
2607 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2608 mreq.ipv6mr_interface = ifp->ifindex;
718e3744 2609
d62a17ae 2610 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
0d6f7fd6 2611 sizeof(mreq));
60077146
DS
2612 if (ret < 0) {
2613 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
2614
9df414fe 2615 flog_err_sys(
450971aa 2616 EC_LIB_SOCKET,
60077146
DS
2617 "%s(%s:%u): Failed to leave group, socket %u error %s",
2618 ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, sock,
2619 safe_strerror(errno));
2620 }
2621 if (IS_ZEBRA_DEBUG_EVENT) {
2622 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
718e3744 2623
d62a17ae 2624 zlog_debug(
60077146
DS
2625 "%s(%s:%u): Leave All-Routers multicast group, socket %u",
2626 ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, sock);
2627 }
d62a17ae 2628 return 0;
718e3744 2629}
2630
2631#else
df9c8c57 2632void rtadv_init(struct zebra_vrf *zvrf)
cd80d74f 2633{
d62a17ae 2634 /* Empty.*/;
cd80d74f 2635}
d3f604f0 2636void rtadv_terminate(void)
cd80d74f 2637{
d62a17ae 2638 /* Empty.*/;
cd80d74f 2639}
d62a17ae 2640void rtadv_cmd_init(void)
718e3744 2641{
d62a17ae 2642 /* Empty.*/;
718e3744 2643}
0af3d691
MS
2644
2645void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p)
2646{
2647 /* Empty.*/;
2648}
2649
2650void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
2651{
2652 /* Empty.*/;
2653}
2654
2655void rtadv_stop_ra(struct interface *ifp)
2656{
2657 /* Empty.*/;
2658}
2659
2660void rtadv_stop_ra_all(void)
2661{
2662 /* Empty.*/;
2663}
2664
e748c7a4
DS
2665/*
2666 * If the end user does not have RADV enabled we should
2667 * handle this better
2668 */
2669void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
2670{
2671 if (IS_ZEBRA_DEBUG_PACKET)
2672 zlog_debug(
2673 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
2674 zserv_command_string(hdr->command));
2675
2676 return;
2677}
2678
2679void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
2680{
2681 if (IS_ZEBRA_DEBUG_PACKET)
2682 zlog_debug(
2683 "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
2684 zserv_command_string(hdr->command));
2685
2686 return;
2687}
2688
56c1f7d8 2689#endif /* HAVE_RTADV */