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