]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rtadv.c
zebra: print unknown rule family as number
[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;
133 msg.msg_controllen = sizeof adata;
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
d62a17ae 879static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
718e3744 880{
d62a17ae 881 struct rtadv_prefix *rprefix;
882
883 rprefix = rtadv_prefix_get(zif->rtadv.AdvPrefixList, &rp->prefix);
884
885 /* Set parameters. */
886 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
887 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
888 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
889 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
890 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
718e3744 891}
892
d62a17ae 893static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
718e3744 894{
d62a17ae 895 struct rtadv_prefix *rprefix;
896
897 rprefix = rtadv_prefix_lookup(zif->rtadv.AdvPrefixList, &rp->prefix);
898 if (rprefix != NULL) {
899 listnode_delete(zif->rtadv.AdvPrefixList, (void *)rprefix);
900 rtadv_prefix_free(rprefix);
901 return 1;
902 } else
903 return 0;
718e3744 904}
905
d62a17ae 906static void ipv6_nd_suppress_ra_set(struct interface *ifp,
907 ipv6_nd_suppress_ra_status status)
b6120505 908{
d62a17ae 909 struct zebra_if *zif;
910 struct zebra_vrf *zvrf;
d62a17ae 911
912 zif = ifp->info;
a36898e7 913 zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 914
915 if (status == RA_SUPPRESS) {
916 /* RA is currently enabled */
917 if (zif->rtadv.AdvSendAdvertisements) {
d7fc0e67
DS
918 rtadv_send_packet(rtadv_get_socket(zvrf), ifp,
919 RA_SUPPRESS);
d62a17ae 920 zif->rtadv.AdvSendAdvertisements = 0;
921 zif->rtadv.AdvIntervalTimer = 0;
df9c8c57 922 zvrf->rtadv.adv_if_count--;
d62a17ae 923
9245fe61 924 if_leave_all_router(rtadv_get_socket(zvrf), ifp);
d62a17ae 925
df9c8c57
PG
926 if (zvrf->rtadv.adv_if_count == 0)
927 rtadv_event(zvrf, RTADV_STOP, 0);
d62a17ae 928 }
929 } else {
930 if (!zif->rtadv.AdvSendAdvertisements) {
931 zif->rtadv.AdvSendAdvertisements = 1;
932 zif->rtadv.AdvIntervalTimer = 0;
df9c8c57 933 zvrf->rtadv.adv_if_count++;
d62a17ae 934
adee8f21
DS
935 if ((zif->rtadv.MaxRtrAdvInterval >= 1000)
936 && zif->rtadv.UseFastRexmit) {
937 /*
938 * Enable Fast RA only when RA interval is in
939 * secs and Fast RA retransmit is enabled
940 */
d62a17ae 941 zif->rtadv.inFastRexmit = 1;
942 zif->rtadv.NumFastReXmitsRemain =
943 RTADV_NUM_FAST_REXMITS;
944 }
945
9245fe61 946 if_join_all_router(rtadv_get_socket(zvrf), ifp);
d62a17ae 947
df9c8c57
PG
948 if (zvrf->rtadv.adv_if_count == 1)
949 rtadv_event(zvrf, RTADV_START,
9245fe61 950 rtadv_get_socket(zvrf));
d62a17ae 951 }
952 }
b6120505
DW
953}
954
4a04e5f7 955/*
956 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
957 * Note that while the client could request RA on an interface on which the
958 * operator has not enabled RA, RA won't be disabled upon client request
5c81b96a 959 * if the operator has explicitly enabled RA. The enable request can also
960 * specify a RA interval (in seconds).
4a04e5f7 961 */
1002497a 962static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
4a04e5f7 963{
d62a17ae 964 struct stream *s;
ec93aa12 965 ifindex_t ifindex;
d62a17ae 966 struct interface *ifp;
967 struct zebra_if *zif;
40441c3d 968 int ra_interval_rxd;
d62a17ae 969
1002497a 970 s = msg;
d62a17ae 971
972 /* Get interface index and RA interval. */
ec93aa12 973 STREAM_GETL(s, ifindex);
40441c3d
QY
974 STREAM_GETL(s, ra_interval_rxd);
975
976 if (ra_interval_rxd < 0) {
977 zlog_warn(
978 "Requested RA interval %d is garbage; ignoring request",
979 ra_interval_rxd);
980 return;
981 }
982
983 unsigned int ra_interval = ra_interval_rxd;
d62a17ae 984
985 if (IS_ZEBRA_DEBUG_EVENT)
40441c3d 986 zlog_debug("%u: IF %u RA %s from client %s, interval %ums",
1002497a
QY
987 zvrf_id(zvrf), ifindex,
988 enable ? "enable" : "disable",
d62a17ae 989 zebra_route_string(client->proto), ra_interval);
990
991 /* Locate interface and check VRF match. */
df9c8c57 992 ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
d62a17ae 993 if (!ifp) {
e914ccbe 994 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
9df414fe 995 "%u: IF %u RA %s client %s - interface unknown",
1002497a 996 zvrf_id(zvrf), ifindex, enable ? "enable" : "disable",
d62a17ae 997 zebra_route_string(client->proto));
998 return;
999 }
a36898e7 1000 if (ifp->vrf_id != zvrf_id(zvrf)) {
9df414fe
QY
1001 zlog_debug(
1002 "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1003 zvrf_id(zvrf), ifindex, enable ? "enable" : "disable",
a36898e7 1004 zebra_route_string(client->proto), ifp->vrf_id);
d62a17ae 1005 return;
1006 }
1007
1008 zif = ifp->info;
1002497a 1009 if (enable) {
3ea48364 1010 SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
d62a17ae 1011 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
1012 if (ra_interval
40441c3d 1013 && (ra_interval * 1000) < (unsigned int) zif->rtadv.MaxRtrAdvInterval
996c9314
LB
1014 && !CHECK_FLAG(zif->rtadv.ra_configured,
1015 VTY_RA_INTERVAL_CONFIGURED))
d62a17ae 1016 zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
1017 } else {
3ea48364
DS
1018 UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
1019 if (!CHECK_FLAG(zif->rtadv.ra_configured,
1020 VTY_RA_INTERVAL_CONFIGURED))
d62a17ae 1021 zif->rtadv.MaxRtrAdvInterval =
1022 RTADV_MAX_RTR_ADV_INTERVAL;
3ea48364 1023 if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
d62a17ae 1024 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
d62a17ae 1025 }
ec93aa12
DS
1026stream_failure:
1027 return;
4a04e5f7 1028}
1029
d7fc0e67
DS
1030/*
1031 * send router lifetime value of zero in RAs on this interface since we're
1032 * ceasing to advertise and want to let our neighbors know.
1033 * RFC 4861 secion 6.2.5
1034 */
1035void rtadv_stop_ra(struct interface *ifp)
1036{
1037 struct zebra_if *zif;
1038 struct zebra_vrf *zvrf;
1039
1040 zif = ifp->info;
1041 zvrf = vrf_info_lookup(ifp->vrf_id);
1042
1043 if (zif->rtadv.AdvSendAdvertisements)
1044 rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_SUPPRESS);
1045}
1046
1047/*
1048 * send router lifetime value of zero in RAs on all interfaces since we're
1049 * ceasing to advertise globally and want to let all of our neighbors know
1050 * RFC 4861 secion 6.2.5
1051 */
1052void rtadv_stop_ra_all(void)
1053{
1054 struct vrf *vrf;
1055 struct interface *ifp;
1056
1057 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1058 FOR_ALL_INTERFACES (vrf, ifp)
1059 rtadv_stop_ra(ifp);
1060}
1061
89f4e507
QY
1062void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
1063{
1002497a 1064 zebra_interface_radv_set(client, hdr, msg, zvrf, 0);
89f4e507 1065}
89f4e507
QY
1066void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
1067{
1002497a 1068 zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
89f4e507
QY
1069}
1070
adee8f21
DS
1071DEFUN (ipv6_nd_ra_fast_retrans,
1072 ipv6_nd_ra_fast_retrans_cmd,
1073 "ipv6 nd ra-fast-retrans",
1074 "Interface IPv6 config commands\n"
1075 "Neighbor discovery\n"
1076 "Fast retransmit of RA packets\n")
1077{
1078 VTY_DECLVAR_CONTEXT(interface, ifp);
1079 struct zebra_if *zif = ifp->info;
1080
1081 if (if_is_loopback(ifp)
1082 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1083 vty_out(vty,
1084 "Cannot configure IPv6 Router Advertisements on this interface\n");
1085 return CMD_WARNING_CONFIG_FAILED;
1086 }
1087
1088 zif->rtadv.UseFastRexmit = true;
1089
1090 return CMD_SUCCESS;
1091}
1092
1093DEFUN (no_ipv6_nd_ra_fast_retrans,
1094 no_ipv6_nd_ra_fast_retrans_cmd,
1095 "no ipv6 nd ra-fast-retrans",
1096 NO_STR
1097 "Interface IPv6 config commands\n"
1098 "Neighbor discovery\n"
1099 "Fast retransmit of RA packets\n")
1100{
1101 VTY_DECLVAR_CONTEXT(interface, ifp);
1102 struct zebra_if *zif = ifp->info;
1103
1104 if (if_is_loopback(ifp)
1105 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1106 vty_out(vty,
1107 "Cannot configure IPv6 Router Advertisements on this interface\n");
1108 return CMD_WARNING_CONFIG_FAILED;
1109 }
1110
1111 zif->rtadv.UseFastRexmit = false;
1112
1113 return CMD_SUCCESS;
1114}
1115
718e3744 1116DEFUN (ipv6_nd_suppress_ra,
1117 ipv6_nd_suppress_ra_cmd,
1118 "ipv6 nd suppress-ra",
3e31cded 1119 "Interface IPv6 config commands\n"
718e3744 1120 "Neighbor discovery\n"
1121 "Suppress Router Advertisement\n")
1122{
d62a17ae 1123 VTY_DECLVAR_CONTEXT(interface, ifp);
1124 struct zebra_if *zif = ifp->info;
1125
1126 if (if_is_loopback(ifp)
1127 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1128 vty_out(vty,
1129 "Cannot configure IPv6 Router Advertisements on this interface\n");
1130 return CMD_WARNING_CONFIG_FAILED;
1131 }
1132
3ea48364
DS
1133 if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1134 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
1135
1136 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
d62a17ae 1137 return CMD_SUCCESS;
718e3744 1138}
1139
718e3744 1140DEFUN (no_ipv6_nd_suppress_ra,
1141 no_ipv6_nd_suppress_ra_cmd,
1142 "no ipv6 nd suppress-ra",
1143 NO_STR
3e31cded 1144 "Interface IPv6 config commands\n"
718e3744 1145 "Neighbor discovery\n"
1146 "Suppress Router Advertisement\n")
1147{
d62a17ae 1148 VTY_DECLVAR_CONTEXT(interface, ifp);
1149 struct zebra_if *zif = ifp->info;
1150
1151 if (if_is_loopback(ifp)
1152 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
1153 vty_out(vty,
1154 "Cannot configure IPv6 Router Advertisements on this interface\n");
1155 return CMD_WARNING_CONFIG_FAILED;
1156 }
1157
1158 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
3ea48364 1159 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
d62a17ae 1160 return CMD_SUCCESS;
718e3744 1161}
1162
7cee1bb1 1163DEFUN (ipv6_nd_ra_interval_msec,
1164 ipv6_nd_ra_interval_msec_cmd,
6147e2c6 1165 "ipv6 nd ra-interval msec (70-1800000)",
7cee1bb1 1166 "Interface IPv6 config commands\n"
1167 "Neighbor discovery\n"
1168 "Router Advertisement interval\n"
3a2d747c 1169 "Router Advertisement interval in milliseconds\n"
7cee1bb1 1170 "Router Advertisement interval in milliseconds\n")
1171{
d62a17ae 1172 int idx_number = 4;
1173 VTY_DECLVAR_CONTEXT(interface, ifp);
1174 unsigned interval;
1175 struct zebra_if *zif = ifp->info;
df9c8c57
PG
1176 struct zebra_vrf *zvrf;
1177
a36898e7 1178 zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 1179
d62a17ae 1180 interval = strtoul(argv[idx_number]->arg, NULL, 10);
1181 if ((zif->rtadv.AdvDefaultLifetime != -1
1182 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
1183 vty_out(vty,
1184 "This ra-interval would conflict with configured ra-lifetime!\n");
1185 return CMD_WARNING_CONFIG_FAILED;
1186 }
1187
1188 if (zif->rtadv.MaxRtrAdvInterval % 1000)
df9c8c57 1189 zvrf->rtadv.adv_msec_if_count--;
d62a17ae 1190
1191 if (interval % 1000)
df9c8c57 1192 zvrf->rtadv.adv_msec_if_count++;
d62a17ae 1193
3ea48364 1194 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
d62a17ae 1195 zif->rtadv.MaxRtrAdvInterval = interval;
1196 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1197 zif->rtadv.AdvIntervalTimer = 0;
1198
1199 return CMD_SUCCESS;
7cee1bb1 1200}
1201
718e3744 1202DEFUN (ipv6_nd_ra_interval,
1203 ipv6_nd_ra_interval_cmd,
6147e2c6 1204 "ipv6 nd ra-interval (1-1800)",
3e31cded 1205 "Interface IPv6 config commands\n"
718e3744 1206 "Neighbor discovery\n"
1207 "Router Advertisement interval\n"
1208 "Router Advertisement interval in seconds\n")
1209{
d62a17ae 1210 int idx_number = 3;
1211 VTY_DECLVAR_CONTEXT(interface, ifp);
1212 unsigned interval;
1213 struct zebra_if *zif = ifp->info;
df9c8c57
PG
1214 struct zebra_vrf *zvrf;
1215
a36898e7 1216 zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 1217
d62a17ae 1218 interval = strtoul(argv[idx_number]->arg, NULL, 10);
1219 if ((zif->rtadv.AdvDefaultLifetime != -1
1220 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
1221 vty_out(vty,
1222 "This ra-interval would conflict with configured ra-lifetime!\n");
1223 return CMD_WARNING_CONFIG_FAILED;
1224 }
1225
1226 if (zif->rtadv.MaxRtrAdvInterval % 1000)
df9c8c57 1227 zvrf->rtadv.adv_msec_if_count--;
d62a17ae 1228
1229 /* convert to milliseconds */
1230 interval = interval * 1000;
1231
3ea48364 1232 SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
d62a17ae 1233 zif->rtadv.MaxRtrAdvInterval = interval;
1234 zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1235 zif->rtadv.AdvIntervalTimer = 0;
1236
1237 return CMD_SUCCESS;
718e3744 1238}
1239
1240DEFUN (no_ipv6_nd_ra_interval,
1241 no_ipv6_nd_ra_interval_cmd,
34ccea1e 1242 "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
718e3744 1243 NO_STR
3e31cded 1244 "Interface IPv6 config commands\n"
718e3744 1245 "Neighbor discovery\n"
34ccea1e
QY
1246 "Router Advertisement interval\n"
1247 "Router Advertisement interval in seconds\n"
1248 "Specify millisecond router advertisement interval\n"
1249 "Router Advertisement interval in milliseconds\n")
718e3744 1250{
d62a17ae 1251 VTY_DECLVAR_CONTEXT(interface, ifp);
1252 struct zebra_if *zif = ifp->info;
df9c8c57
PG
1253 struct zebra_vrf *zvrf = NULL;
1254
a36898e7 1255 zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 1256
1257 if (zif->rtadv.MaxRtrAdvInterval % 1000)
df9c8c57 1258 zvrf->rtadv.adv_msec_if_count--;
d62a17ae 1259
3ea48364
DS
1260 UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1261
1262 if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1263 zif->rtadv.MaxRtrAdvInterval = 10000;
1264 else
1265 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
1266
d62a17ae 1267 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
3ea48364 1268 zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
d62a17ae 1269
1270 return CMD_SUCCESS;
718e3744 1271}
1272
1273DEFUN (ipv6_nd_ra_lifetime,
1274 ipv6_nd_ra_lifetime_cmd,
6147e2c6 1275 "ipv6 nd ra-lifetime (0-9000)",
3e31cded 1276 "Interface IPv6 config commands\n"
718e3744 1277 "Neighbor discovery\n"
1278 "Router lifetime\n"
4afa50b3 1279 "Router lifetime in seconds (0 stands for a non-default gw)\n")
718e3744 1280{
d62a17ae 1281 int idx_number = 3;
1282 VTY_DECLVAR_CONTEXT(interface, ifp);
1283 struct zebra_if *zif = ifp->info;
1284 int lifetime;
1285
1286 lifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1287
1288 /* The value to be placed in the Router Lifetime field
1289 * of Router Advertisements sent from the interface,
1290 * in seconds. MUST be either zero or between
1291 * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1292 if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) {
1293 vty_out(vty,
1294 "This ra-lifetime would conflict with configured ra-interval\n");
1295 return CMD_WARNING_CONFIG_FAILED;
1296 }
1297
1298 zif->rtadv.AdvDefaultLifetime = lifetime;
1299
1300 return CMD_SUCCESS;
718e3744 1301}
1302
1303DEFUN (no_ipv6_nd_ra_lifetime,
1304 no_ipv6_nd_ra_lifetime_cmd,
34ccea1e 1305 "no ipv6 nd ra-lifetime [(0-9000)]",
718e3744 1306 NO_STR
3e31cded 1307 "Interface IPv6 config commands\n"
718e3744 1308 "Neighbor discovery\n"
34ccea1e
QY
1309 "Router lifetime\n"
1310 "Router lifetime in seconds (0 stands for a non-default gw)\n")
718e3744 1311{
d62a17ae 1312 VTY_DECLVAR_CONTEXT(interface, ifp);
1313 struct zebra_if *zif = ifp->info;
718e3744 1314
d62a17ae 1315 zif->rtadv.AdvDefaultLifetime = -1;
718e3744 1316
d62a17ae 1317 return CMD_SUCCESS;
718e3744 1318}
1319
1320DEFUN (ipv6_nd_reachable_time,
1321 ipv6_nd_reachable_time_cmd,
6147e2c6 1322 "ipv6 nd reachable-time (1-3600000)",
3e31cded 1323 "Interface IPv6 config commands\n"
718e3744 1324 "Neighbor discovery\n"
1325 "Reachable time\n"
1326 "Reachable time in milliseconds\n")
1327{
d62a17ae 1328 int idx_number = 3;
1329 VTY_DECLVAR_CONTEXT(interface, ifp);
1330 struct zebra_if *zif = ifp->info;
1331 zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10);
1332 return CMD_SUCCESS;
718e3744 1333}
1334
1335DEFUN (no_ipv6_nd_reachable_time,
1336 no_ipv6_nd_reachable_time_cmd,
34ccea1e 1337 "no ipv6 nd reachable-time [(1-3600000)]",
718e3744 1338 NO_STR
3e31cded 1339 "Interface IPv6 config commands\n"
718e3744 1340 "Neighbor discovery\n"
34ccea1e
QY
1341 "Reachable time\n"
1342 "Reachable time in milliseconds\n")
718e3744 1343{
d62a17ae 1344 VTY_DECLVAR_CONTEXT(interface, ifp);
1345 struct zebra_if *zif = ifp->info;
718e3744 1346
d62a17ae 1347 zif->rtadv.AdvReachableTime = 0;
718e3744 1348
d62a17ae 1349 return CMD_SUCCESS;
718e3744 1350}
1351
7cee1bb1 1352DEFUN (ipv6_nd_homeagent_preference,
1353 ipv6_nd_homeagent_preference_cmd,
6147e2c6 1354 "ipv6 nd home-agent-preference (0-65535)",
7cee1bb1 1355 "Interface IPv6 config commands\n"
1356 "Neighbor discovery\n"
1357 "Home Agent preference\n"
4afa50b3 1358 "preference value (default is 0, least preferred)\n")
7cee1bb1 1359{
d62a17ae 1360 int idx_number = 3;
1361 VTY_DECLVAR_CONTEXT(interface, ifp);
1362 struct zebra_if *zif = ifp->info;
1363 zif->rtadv.HomeAgentPreference =
1364 strtoul(argv[idx_number]->arg, NULL, 10);
1365 return CMD_SUCCESS;
7cee1bb1 1366}
1367
1368DEFUN (no_ipv6_nd_homeagent_preference,
1369 no_ipv6_nd_homeagent_preference_cmd,
34ccea1e 1370 "no ipv6 nd home-agent-preference [(0-65535)]",
7cee1bb1 1371 NO_STR
1372 "Interface IPv6 config commands\n"
1373 "Neighbor discovery\n"
34ccea1e
QY
1374 "Home Agent preference\n"
1375 "preference value (default is 0, least preferred)\n")
7cee1bb1 1376{
d62a17ae 1377 VTY_DECLVAR_CONTEXT(interface, ifp);
1378 struct zebra_if *zif = ifp->info;
7cee1bb1 1379
d62a17ae 1380 zif->rtadv.HomeAgentPreference = 0;
7cee1bb1 1381
d62a17ae 1382 return CMD_SUCCESS;
7cee1bb1 1383}
1384
1385DEFUN (ipv6_nd_homeagent_lifetime,
1386 ipv6_nd_homeagent_lifetime_cmd,
6147e2c6 1387 "ipv6 nd home-agent-lifetime (0-65520)",
7cee1bb1 1388 "Interface IPv6 config commands\n"
1389 "Neighbor discovery\n"
1390 "Home Agent lifetime\n"
4afa50b3 1391 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
7cee1bb1 1392{
d62a17ae 1393 int idx_number = 3;
1394 VTY_DECLVAR_CONTEXT(interface, ifp);
1395 struct zebra_if *zif = ifp->info;
1396 zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1397 return CMD_SUCCESS;
7cee1bb1 1398}
1399
1400DEFUN (no_ipv6_nd_homeagent_lifetime,
1401 no_ipv6_nd_homeagent_lifetime_cmd,
34ccea1e 1402 "no ipv6 nd home-agent-lifetime [(0-65520)]",
7cee1bb1 1403 NO_STR
1404 "Interface IPv6 config commands\n"
1405 "Neighbor discovery\n"
34ccea1e
QY
1406 "Home Agent lifetime\n"
1407 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
7cee1bb1 1408{
d62a17ae 1409 VTY_DECLVAR_CONTEXT(interface, ifp);
1410 struct zebra_if *zif = ifp->info;
7cee1bb1 1411
d62a17ae 1412 zif->rtadv.HomeAgentLifetime = -1;
7cee1bb1 1413
d62a17ae 1414 return CMD_SUCCESS;
7cee1bb1 1415}
1416
718e3744 1417DEFUN (ipv6_nd_managed_config_flag,
1418 ipv6_nd_managed_config_flag_cmd,
1419 "ipv6 nd managed-config-flag",
3e31cded 1420 "Interface IPv6 config commands\n"
718e3744 1421 "Neighbor discovery\n"
1422 "Managed address configuration flag\n")
1423{
d62a17ae 1424 VTY_DECLVAR_CONTEXT(interface, ifp);
1425 struct zebra_if *zif = ifp->info;
718e3744 1426
d62a17ae 1427 zif->rtadv.AdvManagedFlag = 1;
718e3744 1428
d62a17ae 1429 return CMD_SUCCESS;
718e3744 1430}
1431
1432DEFUN (no_ipv6_nd_managed_config_flag,
1433 no_ipv6_nd_managed_config_flag_cmd,
1434 "no ipv6 nd managed-config-flag",
1435 NO_STR
3e31cded 1436 "Interface IPv6 config commands\n"
718e3744 1437 "Neighbor discovery\n"
1438 "Managed address configuration flag\n")
1439{
d62a17ae 1440 VTY_DECLVAR_CONTEXT(interface, ifp);
1441 struct zebra_if *zif = ifp->info;
718e3744 1442
d62a17ae 1443 zif->rtadv.AdvManagedFlag = 0;
718e3744 1444
d62a17ae 1445 return CMD_SUCCESS;
718e3744 1446}
1447
7cee1bb1 1448DEFUN (ipv6_nd_homeagent_config_flag,
1449 ipv6_nd_homeagent_config_flag_cmd,
1450 "ipv6 nd home-agent-config-flag",
1451 "Interface IPv6 config commands\n"
1452 "Neighbor discovery\n"
1453 "Home Agent configuration flag\n")
1454{
d62a17ae 1455 VTY_DECLVAR_CONTEXT(interface, ifp);
1456 struct zebra_if *zif = ifp->info;
7cee1bb1 1457
d62a17ae 1458 zif->rtadv.AdvHomeAgentFlag = 1;
7cee1bb1 1459
d62a17ae 1460 return CMD_SUCCESS;
7cee1bb1 1461}
1462
1463DEFUN (no_ipv6_nd_homeagent_config_flag,
1464 no_ipv6_nd_homeagent_config_flag_cmd,
1465 "no ipv6 nd home-agent-config-flag",
1466 NO_STR
1467 "Interface IPv6 config commands\n"
1468 "Neighbor discovery\n"
1469 "Home Agent configuration flag\n")
1470{
d62a17ae 1471 VTY_DECLVAR_CONTEXT(interface, ifp);
1472 struct zebra_if *zif = ifp->info;
7cee1bb1 1473
d62a17ae 1474 zif->rtadv.AdvHomeAgentFlag = 0;
7cee1bb1 1475
d62a17ae 1476 return CMD_SUCCESS;
7cee1bb1 1477}
1478
1479DEFUN (ipv6_nd_adv_interval_config_option,
1480 ipv6_nd_adv_interval_config_option_cmd,
1481 "ipv6 nd adv-interval-option",
1482 "Interface IPv6 config commands\n"
1483 "Neighbor discovery\n"
1484 "Advertisement Interval Option\n")
1485{
d62a17ae 1486 VTY_DECLVAR_CONTEXT(interface, ifp);
1487 struct zebra_if *zif = ifp->info;
7cee1bb1 1488
d62a17ae 1489 zif->rtadv.AdvIntervalOption = 1;
7cee1bb1 1490
d62a17ae 1491 return CMD_SUCCESS;
7cee1bb1 1492}
1493
1494DEFUN (no_ipv6_nd_adv_interval_config_option,
1495 no_ipv6_nd_adv_interval_config_option_cmd,
1496 "no ipv6 nd adv-interval-option",
1497 NO_STR
1498 "Interface IPv6 config commands\n"
1499 "Neighbor discovery\n"
1500 "Advertisement Interval Option\n")
1501{
d62a17ae 1502 VTY_DECLVAR_CONTEXT(interface, ifp);
1503 struct zebra_if *zif = ifp->info;
7cee1bb1 1504
d62a17ae 1505 zif->rtadv.AdvIntervalOption = 0;
7cee1bb1 1506
d62a17ae 1507 return CMD_SUCCESS;
7cee1bb1 1508}
1509
718e3744 1510DEFUN (ipv6_nd_other_config_flag,
1511 ipv6_nd_other_config_flag_cmd,
1512 "ipv6 nd other-config-flag",
3e31cded 1513 "Interface IPv6 config commands\n"
718e3744 1514 "Neighbor discovery\n"
1515 "Other statefull configuration flag\n")
1516{
d62a17ae 1517 VTY_DECLVAR_CONTEXT(interface, ifp);
1518 struct zebra_if *zif = ifp->info;
718e3744 1519
d62a17ae 1520 zif->rtadv.AdvOtherConfigFlag = 1;
718e3744 1521
d62a17ae 1522 return CMD_SUCCESS;
718e3744 1523}
1524
1525DEFUN (no_ipv6_nd_other_config_flag,
1526 no_ipv6_nd_other_config_flag_cmd,
1527 "no ipv6 nd other-config-flag",
1528 NO_STR
3e31cded 1529 "Interface IPv6 config commands\n"
718e3744 1530 "Neighbor discovery\n"
1531 "Other statefull configuration flag\n")
1532{
d62a17ae 1533 VTY_DECLVAR_CONTEXT(interface, ifp);
1534 struct zebra_if *zif = ifp->info;
718e3744 1535
d62a17ae 1536 zif->rtadv.AdvOtherConfigFlag = 0;
718e3744 1537
d62a17ae 1538 return CMD_SUCCESS;
718e3744 1539}
1540
3e31cded 1541DEFUN (ipv6_nd_prefix,
1542 ipv6_nd_prefix_cmd,
34ccea1e 1543 "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 1544 "Interface IPv6 config commands\n"
718e3744 1545 "Neighbor discovery\n"
1546 "Prefix information\n"
1547 "IPv6 prefix\n"
1548 "Valid lifetime in seconds\n"
3e31cded 1549 "Infinite valid lifetime\n"
718e3744 1550 "Preferred lifetime in seconds\n"
3e31cded 1551 "Infinite preferred lifetime\n"
34ccea1e 1552 "Set Router Address flag\n"
3e31cded 1553 "Do not use prefix for onlink determination\n"
7cee1bb1 1554 "Do not use prefix for autoconfiguration\n"
34ccea1e
QY
1555 "Do not use prefix for autoconfiguration\n"
1556 "Do not use prefix for onlink determination\n")
718e3744 1557{
d62a17ae 1558 /* prelude */
1559 char *prefix = argv[3]->arg;
9d303b37
DL
1560 int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
1561 || strmatch(argv[4]->text, "infinite"));
d62a17ae 1562 int routeropts = lifetimes ? argc > 6 : argc > 4;
1563
1564 int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
1565
1566 char *lifetime = NULL, *preflifetime = NULL;
1567 int routeraddr = 0, offlink = 0, noautoconf = 0;
1568 if (lifetimes) {
1569 lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
1570 : argv[4]->text;
1571 preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg
1572 : argv[5]->text;
1573 }
1574 if (routeropts) {
1575 routeraddr =
1576 strmatch(argv[idx_routeropts]->text, "router-address");
1577 if (!routeraddr) {
1578 offlink = (argc > idx_routeropts + 1
1579 || strmatch(argv[idx_routeropts]->text,
1580 "off-link"));
1581 noautoconf = (argc > idx_routeropts + 1
1582 || strmatch(argv[idx_routeropts]->text,
1583 "no-autoconfig"));
1584 }
1585 }
1586
1587 /* business */
1588 VTY_DECLVAR_CONTEXT(interface, ifp);
1589 struct zebra_if *zebra_if = ifp->info;
1590 int ret;
1591 struct rtadv_prefix rp;
1592
1593 ret = str2prefix_ipv6(prefix, &rp.prefix);
1594 if (!ret) {
1595 vty_out(vty, "Malformed IPv6 prefix\n");
1596 return CMD_WARNING_CONFIG_FAILED;
1597 }
1598 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
1599 rp.AdvOnLinkFlag = !offlink;
1600 rp.AdvAutonomousFlag = !noautoconf;
1601 rp.AdvRouterAddressFlag = routeraddr;
1602 rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
1603 rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1604
1605 if (lifetimes) {
1606 rp.AdvValidLifetime = strmatch(lifetime, "infinite")
1607 ? UINT32_MAX
1608 : strtoll(lifetime, NULL, 10);
1609 rp.AdvPreferredLifetime =
1610 strmatch(preflifetime, "infinite")
1611 ? UINT32_MAX
1612 : strtoll(preflifetime, NULL, 10);
1613 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) {
1614 vty_out(vty, "Invalid preferred lifetime\n");
1615 return CMD_WARNING_CONFIG_FAILED;
1616 }
1617 }
1618
1619 rtadv_prefix_set(zebra_if, &rp);
1620
1621 return CMD_SUCCESS;
718e3744 1622}
1623
3e31cded 1624DEFUN (no_ipv6_nd_prefix,
1625 no_ipv6_nd_prefix_cmd,
34ccea1e
QY
1626 "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]>]",
1627 NO_STR
3e31cded 1628 "Interface IPv6 config commands\n"
718e3744 1629 "Neighbor discovery\n"
1630 "Prefix information\n"
34ccea1e
QY
1631 "IPv6 prefix\n"
1632 "Valid lifetime in seconds\n"
1633 "Infinite valid lifetime\n"
1634 "Preferred lifetime in seconds\n"
1635 "Infinite preferred lifetime\n"
1636 "Set Router Address flag\n"
1637 "Do not use prefix for onlink determination\n"
1638 "Do not use prefix for autoconfiguration\n"
1639 "Do not use prefix for autoconfiguration\n"
1640 "Do not use prefix for onlink determination\n")
718e3744 1641{
d62a17ae 1642 VTY_DECLVAR_CONTEXT(interface, ifp);
1643 struct zebra_if *zebra_if = ifp->info;
1644 int ret;
1645 struct rtadv_prefix rp;
1646 char *prefix = argv[4]->arg;
1647
1648 ret = str2prefix_ipv6(prefix, &rp.prefix);
1649 if (!ret) {
1650 vty_out(vty, "Malformed IPv6 prefix\n");
1651 return CMD_WARNING_CONFIG_FAILED;
1652 }
1653 apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
1654
1655 ret = rtadv_prefix_reset(zebra_if, &rp);
1656 if (!ret) {
1657 vty_out(vty, "Non-existant IPv6 prefix\n");
1658 return CMD_WARNING_CONFIG_FAILED;
1659 }
1660
1661 return CMD_SUCCESS;
718e3744 1662}
b60668d0
CC
1663
1664DEFUN (ipv6_nd_router_preference,
1665 ipv6_nd_router_preference_cmd,
6147e2c6 1666 "ipv6 nd router-preference <high|medium|low>",
b60668d0
CC
1667 "Interface IPv6 config commands\n"
1668 "Neighbor discovery\n"
1669 "Default router preference\n"
1670 "High default router preference\n"
58f1b7cc
DS
1671 "Medium default router preference (default)\n"
1672 "Low default router preference\n")
b60668d0 1673{
d62a17ae 1674 int idx_high_medium_low = 3;
1675 VTY_DECLVAR_CONTEXT(interface, ifp);
1676 struct zebra_if *zif = ifp->info;
1677 int i = 0;
1678
1679 while (0 != rtadv_pref_strs[i]) {
1680 if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i],
1681 1)
1682 == 0) {
1683 zif->rtadv.DefaultPreference = i;
1684 return CMD_SUCCESS;
1685 }
1686 i++;
b60668d0 1687 }
b60668d0 1688
d62a17ae 1689 return CMD_ERR_NO_MATCH;
b60668d0
CC
1690}
1691
1692DEFUN (no_ipv6_nd_router_preference,
1693 no_ipv6_nd_router_preference_cmd,
34ccea1e 1694 "no ipv6 nd router-preference [<high|medium|low>]",
b60668d0
CC
1695 NO_STR
1696 "Interface IPv6 config commands\n"
1697 "Neighbor discovery\n"
34ccea1e
QY
1698 "Default router preference\n"
1699 "High default router preference\n"
1700 "Medium default router preference (default)\n"
1701 "Low default router preference\n")
b60668d0 1702{
d62a17ae 1703 VTY_DECLVAR_CONTEXT(interface, ifp);
1704 struct zebra_if *zif = ifp->info;
b60668d0 1705
d62a17ae 1706 zif->rtadv.DefaultPreference =
1707 RTADV_PREF_MEDIUM; /* Default per RFC4191. */
b60668d0 1708
d62a17ae 1709 return CMD_SUCCESS;
b60668d0
CC
1710}
1711
6ae93c05
DO
1712DEFUN (ipv6_nd_mtu,
1713 ipv6_nd_mtu_cmd,
6147e2c6 1714 "ipv6 nd mtu (1-65535)",
6ae93c05
DO
1715 "Interface IPv6 config commands\n"
1716 "Neighbor discovery\n"
1717 "Advertised MTU\n"
1718 "MTU in bytes\n")
1719{
d62a17ae 1720 int idx_number = 3;
1721 VTY_DECLVAR_CONTEXT(interface, ifp);
1722 struct zebra_if *zif = ifp->info;
1723 zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10);
1724 return CMD_SUCCESS;
6ae93c05
DO
1725}
1726
1727DEFUN (no_ipv6_nd_mtu,
1728 no_ipv6_nd_mtu_cmd,
34ccea1e 1729 "no ipv6 nd mtu [(1-65535)]",
6ae93c05
DO
1730 NO_STR
1731 "Interface IPv6 config commands\n"
1732 "Neighbor discovery\n"
34ccea1e
QY
1733 "Advertised MTU\n"
1734 "MTU in bytes\n")
6ae93c05 1735{
d62a17ae 1736 VTY_DECLVAR_CONTEXT(interface, ifp);
1737 struct zebra_if *zif = ifp->info;
1738 zif->rtadv.AdvLinkMTU = 0;
1739 return CMD_SUCCESS;
6ae93c05
DO
1740}
1741
3eb4fbb0
LS
1742static struct rtadv_rdnss *rtadv_rdnss_new(void)
1743{
1744 return XCALLOC(MTYPE_RTADV_RDNSS, sizeof(struct rtadv_rdnss));
1745}
1746
1747static void rtadv_rdnss_free(struct rtadv_rdnss *rdnss)
1748{
1749 XFREE(MTYPE_RTADV_RDNSS, rdnss);
1750}
1751
1752static struct rtadv_rdnss *rtadv_rdnss_lookup(struct list *list,
1753 struct rtadv_rdnss *rdnss)
1754{
1755 struct listnode *node;
1756 struct rtadv_rdnss *p;
1757
1758 for (ALL_LIST_ELEMENTS_RO(list, node, p))
1759 if (IPV6_ADDR_SAME(&p->addr, &rdnss->addr))
1760 return p;
1761 return NULL;
1762}
1763
1764static struct rtadv_rdnss *rtadv_rdnss_get(struct list *list,
1765 struct rtadv_rdnss *rdnss)
1766{
1767 struct rtadv_rdnss *p;
1768
1769 p = rtadv_rdnss_lookup(list, rdnss);
1770 if (p)
1771 return p;
1772
1773 p = rtadv_rdnss_new();
1774 memcpy(p, rdnss, sizeof(struct rtadv_rdnss));
1775 listnode_add(list, p);
1776
1777 return p;
1778}
1779
1780static void rtadv_rdnss_set(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
1781{
1782 struct rtadv_rdnss *p;
1783
1784 p = rtadv_rdnss_get(zif->rtadv.AdvRDNSSList, rdnss);
1785 p->lifetime = rdnss->lifetime;
1786 p->lifetime_set = rdnss->lifetime_set;
1787}
1788
1789static int rtadv_rdnss_reset(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
1790{
1791 struct rtadv_rdnss *p;
1792
1793 p = rtadv_rdnss_lookup(zif->rtadv.AdvRDNSSList, rdnss);
1794 if (p) {
1795 listnode_delete(zif->rtadv.AdvRDNSSList, p);
1796 rtadv_rdnss_free(p);
1797 return 1;
1798 }
1799
1800 return 0;
1801}
1802
1803static struct rtadv_dnssl *rtadv_dnssl_new(void)
1804{
1805 return XCALLOC(MTYPE_RTADV_DNSSL, sizeof(struct rtadv_dnssl));
1806}
1807
1808static void rtadv_dnssl_free(struct rtadv_dnssl *dnssl)
1809{
1810 XFREE(MTYPE_RTADV_DNSSL, dnssl);
1811}
1812
1813static struct rtadv_dnssl *rtadv_dnssl_lookup(struct list *list,
1814 struct rtadv_dnssl *dnssl)
1815{
1816 struct listnode *node;
1817 struct rtadv_dnssl *p;
1818
1819 for (ALL_LIST_ELEMENTS_RO(list, node, p))
1820 if (!strcasecmp(p->name, dnssl->name))
1821 return p;
1822 return NULL;
1823}
1824
1825static struct rtadv_dnssl *rtadv_dnssl_get(struct list *list,
1826 struct rtadv_dnssl *dnssl)
1827{
1828 struct rtadv_dnssl *p;
1829
1830 p = rtadv_dnssl_lookup(list, dnssl);
1831 if (p)
1832 return p;
1833
1834 p = rtadv_dnssl_new();
1835 memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
1836 listnode_add(list, p);
1837
1838 return p;
1839}
1840
1841static void rtadv_dnssl_set(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
1842{
1843 struct rtadv_dnssl *p;
1844
1845 p = rtadv_dnssl_get(zif->rtadv.AdvDNSSLList, dnssl);
1846 memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
1847}
1848
1849static int rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
1850{
1851 struct rtadv_dnssl *p;
1852
1853 p = rtadv_dnssl_lookup(zif->rtadv.AdvDNSSLList, dnssl);
1854 if (p) {
1855 listnode_delete(zif->rtadv.AdvDNSSLList, p);
1856 rtadv_dnssl_free(p);
1857 return 1;
1858 }
1859
1860 return 0;
1861}
1862
1863/*
1864 * Convert dotted domain name (with or without trailing root zone dot) to
1865 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
1866 * to strlen(in) + 2 octets to out.
1867 *
1868 * Returns the number of octets written to out or -1 if in does not constitute
1869 * a valid domain name.
1870 */
1871static int rtadv_dnssl_encode(uint8_t *out, const char *in)
1872{
1873 const char *label_start, *label_end;
1874 size_t outp;
1875
1876 outp = 0;
1877 label_start = in;
1878
1879 while (*label_start) {
1880 size_t label_len;
1881
1882 label_end = strchr(label_start, '.');
1883 if (label_end == NULL)
1884 label_end = label_start + strlen(label_start);
1885
1886 label_len = label_end - label_start;
1887 if (label_len >= 64)
1888 return -1; /* labels must be 63 octets or less */
1889
1890 out[outp++] = (uint8_t)label_len;
1891 memcpy(out + outp, label_start, label_len);
1892 outp += label_len;
1893 label_start += label_len;
1894 if (*label_start == '.')
1895 label_start++;
1896 }
1897
1898 out[outp++] = '\0';
1899 return outp;
1900}
1901
1902DEFUN(ipv6_nd_rdnss,
1903 ipv6_nd_rdnss_cmd,
1904 "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1905 "Interface IPv6 config commands\n"
1906 "Neighbor discovery\n"
1907 "Recursive DNS server information\n"
1908 "IPv6 address\n"
1909 "Valid lifetime in seconds\n"
1910 "Infinite valid lifetime\n")
1911{
1912 VTY_DECLVAR_CONTEXT(interface, ifp);
1913 struct zebra_if *zif = ifp->info;
844e9180 1914 struct rtadv_rdnss rdnss = {};
3eb4fbb0
LS
1915
1916 if (inet_pton(AF_INET6, argv[3]->arg, &rdnss.addr) != 1) {
1917 vty_out(vty, "Malformed IPv6 address\n");
1918 return CMD_WARNING_CONFIG_FAILED;
1919 }
1920 if (argc > 4) {
1921 char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
1922 : argv[4]->text;
1923 rdnss.lifetime = strmatch(lifetime, "infinite")
1924 ? UINT32_MAX
1925 : strtoll(lifetime, NULL, 10);
1926 rdnss.lifetime_set = 1;
1927 }
1928
1929 rtadv_rdnss_set(zif, &rdnss);
1930
1931 return CMD_SUCCESS;
1932}
1933
1934DEFUN(no_ipv6_nd_rdnss,
1935 no_ipv6_nd_rdnss_cmd,
1936 "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
1937 NO_STR
1938 "Interface IPv6 config commands\n"
1939 "Neighbor discovery\n"
1940 "Recursive DNS server information\n"
1941 "IPv6 address\n"
1942 "Valid lifetime in seconds\n"
1943 "Infinite valid lifetime\n")
1944{
1945 VTY_DECLVAR_CONTEXT(interface, ifp);
1946 struct zebra_if *zif = ifp->info;
844e9180 1947 struct rtadv_rdnss rdnss = {};
3eb4fbb0
LS
1948
1949 if (inet_pton(AF_INET6, argv[4]->arg, &rdnss.addr) != 1) {
1950 vty_out(vty, "Malformed IPv6 address\n");
1951 return CMD_WARNING_CONFIG_FAILED;
1952 }
1953 if (rtadv_rdnss_reset(zif, &rdnss) != 1) {
1954 vty_out(vty, "Non-existant RDNSS address\n");
1955 return CMD_WARNING_CONFIG_FAILED;
1956 }
1957
1958 return CMD_SUCCESS;
1959}
1960
1961DEFUN(ipv6_nd_dnssl,
1962 ipv6_nd_dnssl_cmd,
1963 "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
1964 "Interface IPv6 config commands\n"
1965 "Neighbor discovery\n"
1966 "DNS search list information\n"
1967 "Domain name suffix\n"
1968 "Valid lifetime in seconds\n"
1969 "Infinite valid lifetime\n")
1970{
1971 VTY_DECLVAR_CONTEXT(interface, ifp);
1972 struct zebra_if *zif = ifp->info;
844e9180 1973 struct rtadv_dnssl dnssl = {};
3eb4fbb0
LS
1974 size_t len;
1975 int ret;
1976
1977 len = strlcpy(dnssl.name, argv[3]->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 /*
1984 * Allow, but don't require, a trailing dot signifying the root
1985 * zone. Canonicalize by cutting it off if present.
1986 */
1987 dnssl.name[len - 1] = '\0';
1988 len--;
1989 }
1990 if (argc > 4) {
1991 char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
1992 : argv[4]->text;
1993 dnssl.lifetime = strmatch(lifetime, "infinite")
1994 ? UINT32_MAX
1995 : strtoll(lifetime, NULL, 10);
1996 dnssl.lifetime_set = 1;
1997 }
1998
1999 ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
2000 if (ret < 0) {
2001 vty_out(vty, "Malformed DNS search domain\n");
2002 return CMD_WARNING_CONFIG_FAILED;
2003 }
2004 dnssl.encoded_len = ret;
2005 rtadv_dnssl_set(zif, &dnssl);
2006
2007 return CMD_SUCCESS;
2008}
2009
2010DEFUN(no_ipv6_nd_dnssl,
2011 no_ipv6_nd_dnssl_cmd,
2012 "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2013 NO_STR
2014 "Interface IPv6 config commands\n"
2015 "Neighbor discovery\n"
2016 "DNS search list information\n"
2017 "Domain name suffix\n"
2018 "Valid lifetime in seconds\n"
2019 "Infinite valid lifetime\n")
2020{
2021 VTY_DECLVAR_CONTEXT(interface, ifp);
2022 struct zebra_if *zif = ifp->info;
844e9180 2023 struct rtadv_dnssl dnssl = {};
3eb4fbb0
LS
2024 size_t len;
2025
2026 len = strlcpy(dnssl.name, argv[4]->arg, sizeof(dnssl.name));
2027 if (len == 0 || len >= sizeof(dnssl.name)) {
2028 vty_out(vty, "Malformed DNS search domain\n");
2029 return CMD_WARNING_CONFIG_FAILED;
2030 }
2031 if (dnssl.name[len - 1] == '.') {
2032 dnssl.name[len - 1] = '\0';
2033 len--;
2034 }
2035 if (rtadv_dnssl_reset(zif, &dnssl) != 1) {
2036 vty_out(vty, "Non-existant DNS search domain\n");
2037 return CMD_WARNING_CONFIG_FAILED;
2038 }
2039
2040 return CMD_SUCCESS;
2041}
2042
2043
2eb27eec
DL
2044/* Dump interface ND information to vty. */
2045static int nd_dump_vty(struct vty *vty, struct interface *ifp)
2046{
2047 struct zebra_if *zif;
2048 struct rtadvconf *rtadv;
2049 int interval;
2050
2051 zif = (struct zebra_if *)ifp->info;
2052 rtadv = &zif->rtadv;
2053
2054 if (rtadv->AdvSendAdvertisements) {
2055 vty_out(vty,
2056 " ND advertised reachable time is %d milliseconds\n",
2057 rtadv->AdvReachableTime);
2058 vty_out(vty,
2059 " ND advertised retransmit interval is %d milliseconds\n",
2060 rtadv->AdvRetransTimer);
2061 vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n",
2062 zif->ra_sent, zif->ra_rcvd);
2063 interval = rtadv->MaxRtrAdvInterval;
2064 if (interval % 1000)
2065 vty_out(vty,
2066 " ND router advertisements are sent every "
2067 "%d milliseconds\n",
2068 interval);
2069 else
2070 vty_out(vty,
2071 " ND router advertisements are sent every "
2072 "%d seconds\n",
2073 interval / 1000);
adee8f21
DS
2074 if (!rtadv->UseFastRexmit)
2075 vty_out(vty,
2076 " ND router advertisements do not use fast retransmit\n");
2077
2eb27eec
DL
2078 if (rtadv->AdvDefaultLifetime != -1)
2079 vty_out(vty,
2080 " ND router advertisements live for %d seconds\n",
2081 rtadv->AdvDefaultLifetime);
2082 else
2083 vty_out(vty,
2084 " ND router advertisements lifetime tracks ra-interval\n");
2085 vty_out(vty,
2086 " ND router advertisement default router preference is "
2087 "%s\n",
2088 rtadv_pref_strs[rtadv->DefaultPreference]);
2089 if (rtadv->AdvManagedFlag)
2090 vty_out(vty,
2091 " Hosts use DHCP to obtain routable addresses.\n");
2092 else
2093 vty_out(vty,
2094 " Hosts use stateless autoconfig for addresses.\n");
2095 if (rtadv->AdvHomeAgentFlag) {
2096 vty_out(vty,
2097 " ND router advertisements with Home Agent flag bit set.\n");
2098 if (rtadv->HomeAgentLifetime != -1)
2099 vty_out(vty,
2100 " Home Agent lifetime is %u seconds\n",
2101 rtadv->HomeAgentLifetime);
2102 else
2103 vty_out(vty,
2104 " Home Agent lifetime tracks ra-lifetime\n");
2105 vty_out(vty, " Home Agent preference is %u\n",
2106 rtadv->HomeAgentPreference);
2107 }
2108 if (rtadv->AdvIntervalOption)
2109 vty_out(vty,
2110 " ND router advertisements with Adv. Interval option.\n");
2111 }
2112 return 0;
2113}
2114
6ae93c05 2115
718e3744 2116/* Write configuration about router advertisement. */
2eb27eec 2117static int rtadv_config_write(struct vty *vty, struct interface *ifp)
718e3744 2118{
d62a17ae 2119 struct zebra_if *zif;
2120 struct listnode *node;
2121 struct rtadv_prefix *rprefix;
3eb4fbb0
LS
2122 struct rtadv_rdnss *rdnss;
2123 struct rtadv_dnssl *dnssl;
d62a17ae 2124 char buf[PREFIX_STRLEN];
2125 int interval;
2126
2127 zif = ifp->info;
2128
2129 if (!(if_is_loopback(ifp)
2130 || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) {
3ea48364
DS
2131 if (zif->rtadv.AdvSendAdvertisements
2132 && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
d62a17ae 2133 vty_out(vty, " no ipv6 nd suppress-ra\n");
2134 }
2135
2136 interval = zif->rtadv.MaxRtrAdvInterval;
3ea48364
DS
2137 if (CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) {
2138 if (interval % 1000)
2139 vty_out(vty, " ipv6 nd ra-interval msec %d\n",
2140 interval);
2141 else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
2142 vty_out(vty, " ipv6 nd ra-interval %d\n",
2143 interval / 1000);
2144 }
d62a17ae 2145
2146 if (zif->rtadv.AdvIntervalOption)
2147 vty_out(vty, " ipv6 nd adv-interval-option\n");
2148
adee8f21
DS
2149 if (!zif->rtadv.UseFastRexmit)
2150 vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
2151
d62a17ae 2152 if (zif->rtadv.AdvDefaultLifetime != -1)
2153 vty_out(vty, " ipv6 nd ra-lifetime %d\n",
2154 zif->rtadv.AdvDefaultLifetime);
2155
2156 if (zif->rtadv.HomeAgentPreference)
2157 vty_out(vty, " ipv6 nd home-agent-preference %u\n",
2158 zif->rtadv.HomeAgentPreference);
2159
2160 if (zif->rtadv.HomeAgentLifetime != -1)
2161 vty_out(vty, " ipv6 nd home-agent-lifetime %u\n",
2162 zif->rtadv.HomeAgentLifetime);
2163
2164 if (zif->rtadv.AdvHomeAgentFlag)
2165 vty_out(vty, " ipv6 nd home-agent-config-flag\n");
2166
2167 if (zif->rtadv.AdvReachableTime)
2168 vty_out(vty, " ipv6 nd reachable-time %d\n",
2169 zif->rtadv.AdvReachableTime);
2170
2171 if (zif->rtadv.AdvManagedFlag)
2172 vty_out(vty, " ipv6 nd managed-config-flag\n");
2173
2174 if (zif->rtadv.AdvOtherConfigFlag)
2175 vty_out(vty, " ipv6 nd other-config-flag\n");
2176
2177 if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
2178 vty_out(vty, " ipv6 nd router-preference %s\n",
2179 rtadv_pref_strs[zif->rtadv.DefaultPreference]);
2180
2181 if (zif->rtadv.AdvLinkMTU)
2182 vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU);
2183
2184 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) {
2185 vty_out(vty, " ipv6 nd prefix %s",
2186 prefix2str(&rprefix->prefix, buf, sizeof(buf)));
2187 if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME)
2188 || (rprefix->AdvPreferredLifetime
2189 != RTADV_PREFERRED_LIFETIME)) {
2190 if (rprefix->AdvValidLifetime == UINT32_MAX)
2191 vty_out(vty, " infinite");
2192 else
2193 vty_out(vty, " %u", rprefix->AdvValidLifetime);
2194 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
2195 vty_out(vty, " infinite");
2196 else
2197 vty_out(vty, " %u",
2198 rprefix->AdvPreferredLifetime);
2199 }
2200 if (!rprefix->AdvOnLinkFlag)
2201 vty_out(vty, " off-link");
2202 if (!rprefix->AdvAutonomousFlag)
2203 vty_out(vty, " no-autoconfig");
2204 if (rprefix->AdvRouterAddressFlag)
2205 vty_out(vty, " router-address");
2206 vty_out(vty, "\n");
3e31cded 2207 }
3eb4fbb0
LS
2208 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
2209 char buf[INET6_ADDRSTRLEN];
2210
2211 vty_out(vty, " ipv6 nd rdnss %s",
2212 inet_ntop(AF_INET6, &rdnss->addr, buf, sizeof(buf)));
2213 if (rdnss->lifetime_set) {
2214 if (rdnss->lifetime == UINT32_MAX)
2215 vty_out(vty, " infinite");
2216 else
2217 vty_out(vty, " %u", rdnss->lifetime);
2218 }
2219 vty_out(vty, "\n");
2220 }
2221 for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
2222 vty_out(vty, " ipv6 nd dnssl %s", dnssl->name);
2223 if (dnssl->lifetime_set) {
2224 if (dnssl->lifetime == UINT32_MAX)
2225 vty_out(vty, " infinite");
2226 else
2227 vty_out(vty, " %u", dnssl->lifetime);
2228 }
2229 vty_out(vty, "\n");
2230 }
2eb27eec 2231 return 0;
718e3744 2232}
2233
718e3744 2234
df9c8c57 2235static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
718e3744 2236{
df9c8c57 2237 struct rtadv *rtadv = &zvrf->rtadv;
d62a17ae 2238
2239 switch (event) {
2240 case RTADV_START:
df9c8c57 2241 thread_add_read(zrouter.master, rtadv_read, zvrf, val,
d62a17ae 2242 &rtadv->ra_read);
df9c8c57 2243 thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
d62a17ae 2244 &rtadv->ra_timer);
2245 break;
2246 case RTADV_STOP:
311c15ee
DS
2247 THREAD_OFF(rtadv->ra_timer);
2248 THREAD_OFF(rtadv->ra_read);
d62a17ae 2249 break;
2250 case RTADV_TIMER:
df9c8c57 2251 thread_add_timer(zrouter.master, rtadv_timer, zvrf, val,
d62a17ae 2252 &rtadv->ra_timer);
2253 break;
2254 case RTADV_TIMER_MSEC:
df9c8c57 2255 thread_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val,
d62a17ae 2256 &rtadv->ra_timer);
2257 break;
2258 case RTADV_READ:
df9c8c57 2259 thread_add_read(zrouter.master, rtadv_read, zvrf, val,
d62a17ae 2260 &rtadv->ra_read);
2261 break;
2262 default:
2263 break;
718e3744 2264 }
d62a17ae 2265 return;
718e3744 2266}
2267
df9c8c57 2268void rtadv_init(struct zebra_vrf *zvrf)
718e3744 2269{
9245fe61
PG
2270 if (vrf_is_backend_netns()) {
2271 zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
2272 zrouter.rtadv_sock = -1;
311c15ee 2273 } else {
9245fe61 2274 zvrf->rtadv.sock = -1;
311c15ee
DS
2275 if (zrouter.rtadv_sock < 0)
2276 zrouter.rtadv_sock =
2277 rtadv_make_socket(zvrf->zns->ns_id);
9245fe61 2278 }
cd80d74f 2279}
718e3744 2280
df9c8c57 2281void rtadv_terminate(struct zebra_vrf *zvrf)
cd80d74f 2282{
df9c8c57
PG
2283 rtadv_event(zvrf, RTADV_STOP, 0);
2284 if (zvrf->rtadv.sock >= 0) {
2285 close(zvrf->rtadv.sock);
2286 zvrf->rtadv.sock = -1;
9245fe61
PG
2287 } else if (zrouter.rtadv_sock >= 0) {
2288 close(zrouter.rtadv_sock);
2289 zrouter.rtadv_sock = -1;
d62a17ae 2290 }
df9c8c57
PG
2291 zvrf->rtadv.adv_if_count = 0;
2292 zvrf->rtadv.adv_msec_if_count = 0;
cd80d74f 2293}
718e3744 2294
d62a17ae 2295void rtadv_cmd_init(void)
cd80d74f 2296{
2eb27eec
DL
2297 hook_register(zebra_if_extra_info, nd_dump_vty);
2298 hook_register(zebra_if_config_wr, rtadv_config_write);
2299
adee8f21
DS
2300 install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
2301 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
d62a17ae 2302 install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
2303 install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
2304 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
2305 install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
2306 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
2307 install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
2308 install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
2309 install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
2310 install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
2311 install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
2312 install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
2313 install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
2314 install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
2315 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
2316 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
2317 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
2318 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
2319 install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
2320 install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
2321 install_element(INTERFACE_NODE,
2322 &ipv6_nd_adv_interval_config_option_cmd);
2323 install_element(INTERFACE_NODE,
2324 &no_ipv6_nd_adv_interval_config_option_cmd);
2325 install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
2326 install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
2327 install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
2328 install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
2329 install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
2330 install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
3eb4fbb0
LS
2331 install_element(INTERFACE_NODE, &ipv6_nd_rdnss_cmd);
2332 install_element(INTERFACE_NODE, &no_ipv6_nd_rdnss_cmd);
2333 install_element(INTERFACE_NODE, &ipv6_nd_dnssl_cmd);
2334 install_element(INTERFACE_NODE, &no_ipv6_nd_dnssl_cmd);
718e3744 2335}
2336
d62a17ae 2337static int if_join_all_router(int sock, struct interface *ifp)
718e3744 2338{
d62a17ae 2339 int ret;
718e3744 2340
d62a17ae 2341 struct ipv6_mreq mreq;
718e3744 2342
d62a17ae 2343 memset(&mreq, 0, sizeof(struct ipv6_mreq));
2344 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2345 mreq.ipv6mr_interface = ifp->ifindex;
718e3744 2346
d62a17ae 2347 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq,
2348 sizeof mreq);
2349 if (ret < 0)
450971aa 2350 flog_err_sys(EC_LIB_SOCKET,
9df414fe
QY
2351 "%s(%u): Failed to join group, socket %u error %s",
2352 ifp->name, ifp->ifindex, sock,
2353 safe_strerror(errno));
718e3744 2354
d62a17ae 2355 if (IS_ZEBRA_DEBUG_EVENT)
2356 zlog_debug(
2357 "%s(%u): Join All-Routers multicast group, socket %u",
2358 ifp->name, ifp->ifindex, sock);
718e3744 2359
d62a17ae 2360 return 0;
718e3744 2361}
2362
d62a17ae 2363static int if_leave_all_router(int sock, struct interface *ifp)
718e3744 2364{
d62a17ae 2365 int ret;
718e3744 2366
d62a17ae 2367 struct ipv6_mreq mreq;
718e3744 2368
d62a17ae 2369 memset(&mreq, 0, sizeof(struct ipv6_mreq));
2370 inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2371 mreq.ipv6mr_interface = ifp->ifindex;
718e3744 2372
d62a17ae 2373 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
2374 sizeof mreq);
2375 if (ret < 0)
9df414fe 2376 flog_err_sys(
450971aa 2377 EC_LIB_SOCKET,
9df414fe
QY
2378 "%s(%u): Failed to leave group, socket %u error %s",
2379 ifp->name, ifp->ifindex, sock, safe_strerror(errno));
718e3744 2380
d62a17ae 2381 if (IS_ZEBRA_DEBUG_EVENT)
2382 zlog_debug(
2383 "%s(%u): Leave All-Routers multicast group, socket %u",
2384 ifp->name, ifp->ifindex, sock);
718e3744 2385
d62a17ae 2386 return 0;
718e3744 2387}
2388
2389#else
df9c8c57 2390void rtadv_init(struct zebra_vrf *zvrf)
cd80d74f 2391{
d62a17ae 2392 /* Empty.*/;
cd80d74f 2393}
df9c8c57 2394void rtadv_terminate(struct zebra_vrf *zvrf)
cd80d74f 2395{
d62a17ae 2396 /* Empty.*/;
cd80d74f 2397}
d62a17ae 2398void rtadv_cmd_init(void)
718e3744 2399{
d62a17ae 2400 /* Empty.*/;
718e3744 2401}
56c1f7d8 2402#endif /* HAVE_RTADV */