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