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