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