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