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