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