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