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