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