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