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