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