1 /* Router advertisement
2  * Copyright (C) 2016 Cumulus Networks
3  * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
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  *
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
21  */
22 
23 #include <zebra.h>
24 
25 #include "memory.h"
26 #include "zebra_memory.h"
27 #include "sockopt.h"
28 #include "thread.h"
29 #include "if.h"
30 #include "stream.h"
31 #include "log.h"
32 #include "prefix.h"
33 #include "linklist.h"
34 #include "command.h"
35 #include "privs.h"
36 #include "vrf.h"
37 #include "ns.h"
38 #include "lib_errors.h"
39 
40 #include "zebra/interface.h"
41 #include "zebra/rtadv.h"
42 #include "zebra/debug.h"
43 #include "zebra/rib.h"
44 #include "zebra/zapi_msg.h"
45 #include "zebra/zebra_vrf.h"
46 #include "zebra/zebra_errors.h"
47 #include "zebra/zebra_router.h"
48 
49 extern struct zebra_privs_t zserv_privs;
50 
51 #if defined(HAVE_RTADV)
52 
53 #ifndef VTYSH_EXTRACT_PL
54 #include "zebra/rtadv_clippy.c"
55 #endif
56 
57 DEFINE_MTYPE_STATIC(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix")
58 
59 #ifdef OPEN_BSD
60 #include <netinet/icmp6.h>
61 #endif
62 
63 /* If RFC2133 definition is used. */
64 #ifndef IPV6_JOIN_GROUP
65 #define IPV6_JOIN_GROUP  IPV6_ADD_MEMBERSHIP
66 #endif
67 #ifndef IPV6_LEAVE_GROUP
68 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
69 #endif
70 
71 #define ALLNODE   "ff02::1"
72 #define ALLROUTER "ff02::2"
73 
74 DEFINE_MTYPE_STATIC(ZEBRA, RTADV_RDNSS, "Router Advertisement RDNSS")
75 DEFINE_MTYPE_STATIC(ZEBRA, RTADV_DNSSL, "Router Advertisement DNSSL")
76 
77 /* Order is intentional.  Matches RFC4191.  This array is also used for
78    command matching, so only modify with care. */
79 static const char *const rtadv_pref_strs[] = {
80 	"medium", "high", "INVALID", "low", 0
81 };
82 
83 enum rtadv_event {
84 	RTADV_START,
85 	RTADV_STOP,
86 	RTADV_TIMER,
87 	RTADV_TIMER_MSEC,
88 	RTADV_READ
89 };
90 
91 static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int);
92 
93 static int if_join_all_router(int, struct interface *);
94 static int if_leave_all_router(int, struct interface *);
95 
rtadv_get_socket(struct zebra_vrf * zvrf)96 static 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 
rtadv_increment_received(struct zebra_vrf * zvrf,ifindex_t * ifindex)103 static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
104 {
105 	int ret = -1;
106 	struct interface *iface;
107 	struct zebra_if *zif;
108 
109 	iface = if_lookup_by_index(*ifindex, zvrf->vrf->vrf_id);
110 	if (iface && iface->info) {
111 		zif = iface->info;
112 		zif->ra_rcvd++;
113 		ret = 0;
114 	}
115 	return ret;
116 }
117 
rtadv_recv_packet(struct zebra_vrf * zvrf,int sock,uint8_t * buf,int buflen,struct sockaddr_in6 * from,ifindex_t * ifindex,int * hoplimit)118 static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
119 			     int buflen, struct sockaddr_in6 *from,
120 			     ifindex_t *ifindex, int *hoplimit)
121 {
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. */
131 	memset(&msg, 0, sizeof(msg));
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;
137 	msg.msg_controllen = sizeof(adata);
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 
146 	for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
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 		}
164 	}
165 
166 	rtadv_increment_received(zvrf, ifindex);
167 	return ret;
168 }
169 
170 #define RTADV_MSG_SIZE 4096
171 
172 /* Send router advertisement packet. */
rtadv_send_packet(int sock,struct interface * ifp,enum ipv6_nd_suppress_ra_status stop)173 static void rtadv_send_packet(int sock, struct interface *ifp,
174 			      enum ipv6_nd_suppress_ra_status stop)
175 {
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;
188 	uint8_t all_nodes_addr[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
189 				    0,    0,    0, 0, 0, 0, 0, 1};
190 	struct listnode *node;
191 	uint16_t pkt_RouterLifetime;
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. */
201 		adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
202 
203 		if (adata == NULL) {
204 			zlog_debug(
205 				"rtadv_send_packet: can't malloc control data");
206 			exit(-1);
207 		}
208 	}
209 
210 	/* Logging of packet. */
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 	}
217 
218 	/* Fill in sockaddr_in6. */
219 	memset(&addr, 0, sizeof(struct sockaddr_in6));
220 	addr.sin6_family = AF_INET6;
221 #ifdef SIN6_LEN
222 	addr.sin6_len = sizeof(struct sockaddr_in6);
223 #endif /* SIN6_LEN */
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 
237 	rtadv->nd_ra_curhoplimit = zif->rtadv.AdvCurHopLimit;
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);
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);
267 	rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime);
268 	rtadv->nd_ra_retransmit = htonl(zif->rtadv.AdvRetransTimer);
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*/
301 			      );
302 		len += sizeof(struct nd_opt_homeagent_info);
303 	}
304 
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;
319 
320 		pinfo = (struct nd_opt_prefix_info *)(buf + len);
321 
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 
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 
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 
380 	/* Recursive DNS servers */
381 	struct rtadv_rdnss *rdnss;
382 
383 	for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
384 		size_t opt_len =
385 			sizeof(struct nd_opt_rdnss) + sizeof(struct in6_addr);
386 
387 		if (len + opt_len > max_len) {
388 			struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
389 
390 			zlog_warn(
391 				"%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
392 				ifp->name, VRF_LOGNAME(vrf), ifp->ifindex);
393 			goto no_more_opts;
394 		}
395 		struct nd_opt_rdnss *opt = (struct nd_opt_rdnss *)(buf + len);
396 
397 		opt->nd_opt_rdnss_type = ND_OPT_RDNSS;
398 		opt->nd_opt_rdnss_len = opt_len / 8;
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);
406 
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)) {
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 		}
424 		struct nd_opt_dnssl *opt = (struct nd_opt_dnssl *)(buf + len);
425 
426 		opt->nd_opt_dnssl_type = ND_OPT_DNSSL;
427 		opt->nd_opt_dnssl_len = opt_len / 8;
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 
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';
442 	}
443 
444 no_more_opts:
445 
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 
456 	cmsgptr = CMSG_FIRSTHDR(&msg);
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) {
467 		flog_err_sys(EC_LIB_SOCKET,
468 			     "%s(%u): Tx RA failed, socket %u error %d (%s)",
469 			     ifp->name, ifp->ifindex, sock, errno,
470 			     safe_strerror(errno));
471 	} else
472 		zif->ra_sent++;
473 }
474 
rtadv_timer(struct thread * thread)475 static int rtadv_timer(struct thread *thread)
476 {
477 	struct zebra_vrf *zvrf = THREAD_ARG(thread);
478 	struct vrf *vrf;
479 	struct interface *ifp;
480 	struct zebra_if *zif;
481 	int period;
482 
483 	zvrf->rtadv.ra_timer = NULL;
484 	if (zvrf->rtadv.adv_msec_if_count == 0) {
485 		period = 1000; /* 1 s */
486 		rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
487 	} else {
488 		period = 10; /* 10 ms */
489 		rtadv_event(zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
490 	}
491 
492 	RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
493 		FOR_ALL_INTERFACES (vrf, ifp) {
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) {
503 				if (zif->rtadv.inFastRexmit
504 				    && zif->rtadv.UseFastRexmit) {
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 
512 					if (IS_ZEBRA_DEBUG_SEND) {
513 						struct vrf *vrf =
514 							vrf_lookup_by_id(
515 								ifp->vrf_id);
516 
517 						zlog_debug(
518 							"Fast RA Rexmit on interface %s(%s:%u)",
519 							ifp->name,
520 							VRF_LOGNAME(vrf),
521 							ifp->ifindex);
522 					}
523 
524 					rtadv_send_packet(rtadv_get_socket(zvrf),
525 							  ifp, RA_ENABLE);
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(
538 							  rtadv_get_socket(zvrf),
539 							  ifp, RA_ENABLE);
540 					}
541 				}
542 			}
543 		}
544 
545 	return 0;
546 }
547 
rtadv_process_solicit(struct interface * ifp)548 static void rtadv_process_solicit(struct interface *ifp)
549 {
550 	struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
551 	struct zebra_if *zif;
552 
553 	assert(zvrf);
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))) {
569 		rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_ENABLE);
570 		zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
571 	} else
572 		zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS;
573 }
574 
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  */
rtadv_process_optional(uint8_t * optional,unsigned int len,struct interface * ifp,struct sockaddr_in6 * addr)583 static 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 
rtadv_process_advert(uint8_t * msg,unsigned int len,struct interface * ifp,struct sockaddr_in6 * addr)607 static void rtadv_process_advert(uint8_t *msg, unsigned int len,
608 				 struct interface *ifp,
609 				 struct sockaddr_in6 *addr)
610 {
611 	struct nd_router_advert *radvert;
612 	char addr_str[INET6_ADDRSTRLEN];
613 	struct zebra_if *zif;
614 	struct prefix p;
615 
616 	zif = ifp->info;
617 
618 	inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
619 
620 	if (len < sizeof(struct nd_router_advert)) {
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 		}
629 		return;
630 	}
631 
632 	if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
633 		rtadv_process_optional(msg + sizeof(struct nd_router_advert),
634 				       len - sizeof(struct nd_router_advert),
635 				       ifp, addr);
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 		}
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)) {
651 		flog_warn(
652 			EC_ZEBRA_RA_PARAM_MISMATCH,
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) {
659 		flog_warn(
660 			EC_ZEBRA_RA_PARAM_MISMATCH,
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) {
667 		flog_warn(
668 			EC_ZEBRA_RA_PARAM_MISMATCH,
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)) {
676 		flog_warn(
677 			EC_ZEBRA_RA_PARAM_MISMATCH,
678 			"%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
679 			ifp->name, ifp->ifindex, addr_str);
680 	}
681 
682 	if ((ntohl(radvert->nd_ra_retransmit)
683 	     != (unsigned int)zif->rtadv.AdvRetransTimer)) {
684 		flog_warn(
685 			EC_ZEBRA_RA_PARAM_MISMATCH,
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;
692 	IPV6_ADDR_COPY(&p.u.prefix6, &addr->sin6_addr);
693 	p.prefixlen = IPV6_MAX_PREFIXLEN;
694 
695 	if (!nbr_connected_check(ifp, &p))
696 		nbr_connected_add_ipv6(ifp, &addr->sin6_addr);
697 }
698 
699 
rtadv_process_packet(uint8_t * buf,unsigned int len,ifindex_t ifindex,int hoplimit,struct sockaddr_in6 * from,struct zebra_vrf * zvrf)700 static void rtadv_process_packet(uint8_t *buf, unsigned int len,
701 				 ifindex_t ifindex, int hoplimit,
702 				 struct sockaddr_in6 *from,
703 				 struct zebra_vrf *zvrf)
704 {
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. */
713 	ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
714 	if (ifp == NULL) {
715 		flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
716 			  "RA/RS received on unknown IF %u from %s", ifindex,
717 			  addr_str);
718 		return;
719 	}
720 
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 	}
727 
728 	if (if_is_loopback(ifp)
729 	    || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
730 		return;
731 
732 	/* Check interface configuration. */
733 	zif = ifp->info;
734 	if (!zif->rtadv.AdvSendAdvertisements)
735 		return;
736 
737 	/* ICMP message length check. */
738 	if (len < sizeof(struct icmp6_hdr)) {
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);
744 		return;
745 	}
746 
747 	icmph = (struct icmp6_hdr *)buf;
748 
749 	/* ICMP message type check. */
750 	if (icmph->icmp6_type != ND_ROUTER_SOLICIT
751 	    && icmph->icmp6_type != ND_ROUTER_ADVERT) {
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);
757 		return;
758 	}
759 
760 	/* Hoplimit check. */
761 	if (hoplimit >= 0 && hoplimit != 255) {
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);
766 		return;
767 	}
768 
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);
774 
775 	return;
776 }
777 
rtadv_read(struct thread * thread)778 static int rtadv_read(struct thread *thread)
779 {
780 	int sock;
781 	int len;
782 	uint8_t buf[RTADV_MSG_SIZE];
783 	struct sockaddr_in6 from;
784 	ifindex_t ifindex = 0;
785 	int hoplimit = -1;
786 	struct zebra_vrf *zvrf = THREAD_ARG(thread);
787 
788 	sock = THREAD_FD(thread);
789 	zvrf->rtadv.ra_read = NULL;
790 
791 	/* Register myself. */
792 	rtadv_event(zvrf, RTADV_READ, sock);
793 
794 	len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
795 				&hoplimit);
796 
797 	if (len < 0) {
798 		flog_err_sys(EC_LIB_SOCKET,
799 			     "RA/RS recv failed, socket %u error %s", sock,
800 			     safe_strerror(errno));
801 		return len;
802 	}
803 
804 	rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf);
805 
806 	return 0;
807 }
808 
rtadv_make_socket(ns_id_t ns_id)809 static int rtadv_make_socket(ns_id_t ns_id)
810 {
811 	int sock = -1;
812 	int ret = 0;
813 	struct icmp6_filter filter;
814 
815 	frr_with_privs(&zserv_privs) {
816 
817 		sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
818 
819 	}
820 
821 	if (sock < 0) {
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));
859 		close(sock);
860 		return ret;
861 	}
862 
863 	return sock;
864 }
865 
rtadv_prefix_new(void)866 static struct rtadv_prefix *rtadv_prefix_new(void)
867 {
868 	return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix));
869 }
870 
rtadv_prefix_free(struct rtadv_prefix * rtadv_prefix)871 static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix)
872 {
873 	XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix);
874 }
875 
rtadv_prefix_lookup(struct list * rplist,struct prefix_ipv6 * p)876 static 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;
887 }
888 
rtadv_prefix_get(struct list * rplist,struct prefix_ipv6 * p)889 static struct rtadv_prefix *rtadv_prefix_get(struct list *rplist,
890 					     struct prefix_ipv6 *p)
891 {
892 	struct rtadv_prefix *rprefix;
893 
894 	rprefix = rtadv_prefix_lookup(rplist, p);
895 	if (rprefix)
896 		return rprefix;
897 
898 	rprefix = rtadv_prefix_new();
899 	memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6));
900 	listnode_add(rplist, rprefix);
901 
902 	return rprefix;
903 }
904 
rtadv_prefix_set_defaults(struct rtadv_prefix * rp)905 static 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 
rtadv_prefix_set(struct zebra_if * zif,struct rtadv_prefix * rp)914 static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
915 {
916 	struct rtadv_prefix *rprefix;
917 
918 	rprefix = rtadv_prefix_get(zif->rtadv.AdvPrefixList, &rp->prefix);
919 
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 	}
947 }
948 
rtadv_prefix_reset(struct zebra_if * zif,struct rtadv_prefix * rp)949 static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
950 {
951 	struct rtadv_prefix *rprefix;
952 
953 	rprefix = rtadv_prefix_lookup(zif->rtadv.AdvPrefixList, &rp->prefix);
954 	if (rprefix != NULL) {
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 
976 		listnode_delete(zif->rtadv.AdvPrefixList, (void *)rprefix);
977 		rtadv_prefix_free(rprefix);
978 		return 1;
979 	} else
980 		return 0;
981 }
982 
983 /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
rtadv_add_prefix(struct zebra_if * zif,const struct prefix_ipv6 * p)984 void 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 */
rtadv_delete_prefix(struct zebra_if * zif,const struct prefix * p)995 void 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 
ipv6_nd_suppress_ra_set(struct interface * ifp,enum ipv6_nd_suppress_ra_status status)1005 static void ipv6_nd_suppress_ra_set(struct interface *ifp,
1006 				    enum ipv6_nd_suppress_ra_status status)
1007 {
1008 	struct zebra_if *zif;
1009 	struct zebra_vrf *zvrf;
1010 
1011 	zif = ifp->info;
1012 	zvrf = vrf_info_lookup(ifp->vrf_id);
1013 
1014 	if (status == RA_SUPPRESS) {
1015 		/* RA is currently enabled */
1016 		if (zif->rtadv.AdvSendAdvertisements) {
1017 			rtadv_send_packet(rtadv_get_socket(zvrf), ifp,
1018 					  RA_SUPPRESS);
1019 			zif->rtadv.AdvSendAdvertisements = 0;
1020 			zif->rtadv.AdvIntervalTimer = 0;
1021 			zvrf->rtadv.adv_if_count--;
1022 
1023 			if_leave_all_router(rtadv_get_socket(zvrf), ifp);
1024 
1025 			if (zvrf->rtadv.adv_if_count == 0)
1026 				rtadv_event(zvrf, RTADV_STOP, 0);
1027 		}
1028 	} else {
1029 		if (!zif->rtadv.AdvSendAdvertisements) {
1030 			zif->rtadv.AdvSendAdvertisements = 1;
1031 			zif->rtadv.AdvIntervalTimer = 0;
1032 			zvrf->rtadv.adv_if_count++;
1033 
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 				 */
1040 				zif->rtadv.inFastRexmit = 1;
1041 				zif->rtadv.NumFastReXmitsRemain =
1042 					RTADV_NUM_FAST_REXMITS;
1043 			}
1044 
1045 			if_join_all_router(rtadv_get_socket(zvrf), ifp);
1046 
1047 			if (zvrf->rtadv.adv_if_count == 1)
1048 				rtadv_event(zvrf, RTADV_START,
1049 					    rtadv_get_socket(zvrf));
1050 		}
1051 	}
1052 }
1053 
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
1058  * if the operator has explicitly enabled RA. The enable request can also
1059  * specify a RA interval (in seconds).
1060  */
zebra_interface_radv_set(ZAPI_HANDLER_ARGS,int enable)1061 static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
1062 {
1063 	struct stream *s;
1064 	ifindex_t ifindex;
1065 	struct interface *ifp;
1066 	struct zebra_if *zif;
1067 	int ra_interval_rxd;
1068 
1069 	s = msg;
1070 
1071 	/* Get interface index and RA interval. */
1072 	STREAM_GETL(s, ifindex);
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;
1083 
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,
1089 			   enable ? "enable" : "disable",
1090 			   zebra_route_string(client->proto), ra_interval);
1091 	}
1092 
1093 	/* Locate interface and check VRF match. */
1094 	ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
1095 	if (!ifp) {
1096 		struct vrf *vrf = zvrf->vrf;
1097 
1098 		flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
1099 			  "%s:%u: IF %u RA %s client %s - interface unknown",
1100 			  VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
1101 			  enable ? "enable" : "disable",
1102 			  zebra_route_string(client->proto));
1103 		return;
1104 	}
1105 	if (ifp->vrf_id != zvrf_id(zvrf)) {
1106 		struct vrf *vrf = zvrf->vrf;
1107 
1108 		zlog_debug(
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",
1112 			zebra_route_string(client->proto), ifp->vrf_id);
1113 		return;
1114 	}
1115 
1116 	zif = ifp->info;
1117 	if (enable) {
1118 		SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
1119 		ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
1120 		if (ra_interval
1121 		    && (ra_interval * 1000) < (unsigned int) zif->rtadv.MaxRtrAdvInterval
1122 		    && !CHECK_FLAG(zif->rtadv.ra_configured,
1123 				   VTY_RA_INTERVAL_CONFIGURED))
1124 			zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
1125 	} else {
1126 		UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
1127 		if (!CHECK_FLAG(zif->rtadv.ra_configured,
1128 				VTY_RA_INTERVAL_CONFIGURED))
1129 			zif->rtadv.MaxRtrAdvInterval =
1130 				RTADV_MAX_RTR_ADV_INTERVAL;
1131 		if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
1132 			ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
1133 	}
1134 stream_failure:
1135 	return;
1136 }
1137 
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  */
rtadv_stop_ra(struct interface * ifp)1143 void 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 /*
1156  * Send router lifetime value of zero in RAs on all interfaces since we're
1157  * ceasing to advertise globally and want to let all of our neighbors know
1158  * RFC 4861 secion 6.2.5
1159  *
1160  * Delete all ipv6 global prefixes added to the router advertisement prefix
1161  * lists prior to ceasing.
1162  */
rtadv_stop_ra_all(void)1163 void rtadv_stop_ra_all(void)
1164 {
1165 	struct vrf *vrf;
1166 	struct interface *ifp;
1167 	struct listnode *node, *nnode;
1168 	struct zebra_if *zif;
1169 	struct rtadv_prefix *rprefix;
1170 
1171 	RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
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 
1179 			rtadv_stop_ra(ifp);
1180 		}
1181 }
1182 
zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)1183 void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
1184 {
1185 	zebra_interface_radv_set(client, hdr, msg, zvrf, 0);
1186 }
zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)1187 void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
1188 {
1189 	zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
1190 }
1191 
1192 DEFUN (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 
1214 DEFUN (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 
1237 DEFPY (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 
1260 DEFPY (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 
1284 DEFPY (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 
1307 DEFPY (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 
1331 DEFUN (ipv6_nd_suppress_ra,
1332        ipv6_nd_suppress_ra_cmd,
1333        "ipv6 nd suppress-ra",
1334        "Interface IPv6 config commands\n"
1335        "Neighbor discovery\n"
1336        "Suppress Router Advertisement\n")
1337 {
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 
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);
1352 	return CMD_SUCCESS;
1353 }
1354 
1355 DEFUN (no_ipv6_nd_suppress_ra,
1356        no_ipv6_nd_suppress_ra_cmd,
1357        "no ipv6 nd suppress-ra",
1358        NO_STR
1359        "Interface IPv6 config commands\n"
1360        "Neighbor discovery\n"
1361        "Suppress Router Advertisement\n")
1362 {
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);
1374 	SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
1375 	return CMD_SUCCESS;
1376 }
1377 
1378 DEFUN (ipv6_nd_ra_interval_msec,
1379        ipv6_nd_ra_interval_msec_cmd,
1380        "ipv6 nd ra-interval msec (70-1800000)",
1381        "Interface IPv6 config commands\n"
1382        "Neighbor discovery\n"
1383        "Router Advertisement interval\n"
1384        "Router Advertisement interval in milliseconds\n"
1385        "Router Advertisement interval in milliseconds\n")
1386 {
1387 	int idx_number = 4;
1388 	VTY_DECLVAR_CONTEXT(interface, ifp);
1389 	unsigned interval;
1390 	struct zebra_if *zif = ifp->info;
1391 	struct zebra_vrf *zvrf;
1392 
1393 	zvrf = vrf_info_lookup(ifp->vrf_id);
1394 
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)
1404 		zvrf->rtadv.adv_msec_if_count--;
1405 
1406 	if (interval % 1000)
1407 		zvrf->rtadv.adv_msec_if_count++;
1408 
1409 	SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1410 	zif->rtadv.MaxRtrAdvInterval = interval;
1411 	zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1412 	zif->rtadv.AdvIntervalTimer = 0;
1413 
1414 	return CMD_SUCCESS;
1415 }
1416 
1417 DEFUN (ipv6_nd_ra_interval,
1418        ipv6_nd_ra_interval_cmd,
1419        "ipv6 nd ra-interval (1-1800)",
1420        "Interface IPv6 config commands\n"
1421        "Neighbor discovery\n"
1422        "Router Advertisement interval\n"
1423        "Router Advertisement interval in seconds\n")
1424 {
1425 	int idx_number = 3;
1426 	VTY_DECLVAR_CONTEXT(interface, ifp);
1427 	unsigned interval;
1428 	struct zebra_if *zif = ifp->info;
1429 	struct zebra_vrf *zvrf;
1430 
1431 	zvrf = vrf_info_lookup(ifp->vrf_id);
1432 
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)
1442 		zvrf->rtadv.adv_msec_if_count--;
1443 
1444 	/* convert to milliseconds */
1445 	interval = interval * 1000;
1446 
1447 	SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1448 	zif->rtadv.MaxRtrAdvInterval = interval;
1449 	zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1450 	zif->rtadv.AdvIntervalTimer = 0;
1451 
1452 	return CMD_SUCCESS;
1453 }
1454 
1455 DEFUN (no_ipv6_nd_ra_interval,
1456        no_ipv6_nd_ra_interval_cmd,
1457        "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1458        NO_STR
1459        "Interface IPv6 config commands\n"
1460        "Neighbor discovery\n"
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")
1465 {
1466 	VTY_DECLVAR_CONTEXT(interface, ifp);
1467 	struct zebra_if *zif = ifp->info;
1468 	struct zebra_vrf *zvrf = NULL;
1469 
1470 	zvrf = vrf_info_lookup(ifp->vrf_id);
1471 
1472 	if (zif->rtadv.MaxRtrAdvInterval % 1000)
1473 		zvrf->rtadv.adv_msec_if_count--;
1474 
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 
1482 	zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
1483 	zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
1484 
1485 	return CMD_SUCCESS;
1486 }
1487 
1488 DEFUN (ipv6_nd_ra_lifetime,
1489        ipv6_nd_ra_lifetime_cmd,
1490        "ipv6 nd ra-lifetime (0-9000)",
1491        "Interface IPv6 config commands\n"
1492        "Neighbor discovery\n"
1493        "Router lifetime\n"
1494        "Router lifetime in seconds (0 stands for a non-default gw)\n")
1495 {
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;
1516 }
1517 
1518 DEFUN (no_ipv6_nd_ra_lifetime,
1519        no_ipv6_nd_ra_lifetime_cmd,
1520        "no ipv6 nd ra-lifetime [(0-9000)]",
1521        NO_STR
1522        "Interface IPv6 config commands\n"
1523        "Neighbor discovery\n"
1524        "Router lifetime\n"
1525        "Router lifetime in seconds (0 stands for a non-default gw)\n")
1526 {
1527 	VTY_DECLVAR_CONTEXT(interface, ifp);
1528 	struct zebra_if *zif = ifp->info;
1529 
1530 	zif->rtadv.AdvDefaultLifetime = -1;
1531 
1532 	return CMD_SUCCESS;
1533 }
1534 
1535 DEFUN (ipv6_nd_reachable_time,
1536        ipv6_nd_reachable_time_cmd,
1537        "ipv6 nd reachable-time (1-3600000)",
1538        "Interface IPv6 config commands\n"
1539        "Neighbor discovery\n"
1540        "Reachable time\n"
1541        "Reachable time in milliseconds\n")
1542 {
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;
1548 }
1549 
1550 DEFUN (no_ipv6_nd_reachable_time,
1551        no_ipv6_nd_reachable_time_cmd,
1552        "no ipv6 nd reachable-time [(1-3600000)]",
1553        NO_STR
1554        "Interface IPv6 config commands\n"
1555        "Neighbor discovery\n"
1556        "Reachable time\n"
1557        "Reachable time in milliseconds\n")
1558 {
1559 	VTY_DECLVAR_CONTEXT(interface, ifp);
1560 	struct zebra_if *zif = ifp->info;
1561 
1562 	zif->rtadv.AdvReachableTime = 0;
1563 
1564 	return CMD_SUCCESS;
1565 }
1566 
1567 DEFUN (ipv6_nd_homeagent_preference,
1568        ipv6_nd_homeagent_preference_cmd,
1569        "ipv6 nd home-agent-preference (0-65535)",
1570        "Interface IPv6 config commands\n"
1571        "Neighbor discovery\n"
1572        "Home Agent preference\n"
1573        "preference value (default is 0, least preferred)\n")
1574 {
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;
1581 }
1582 
1583 DEFUN (no_ipv6_nd_homeagent_preference,
1584        no_ipv6_nd_homeagent_preference_cmd,
1585        "no ipv6 nd home-agent-preference [(0-65535)]",
1586        NO_STR
1587        "Interface IPv6 config commands\n"
1588        "Neighbor discovery\n"
1589        "Home Agent preference\n"
1590        "preference value (default is 0, least preferred)\n")
1591 {
1592 	VTY_DECLVAR_CONTEXT(interface, ifp);
1593 	struct zebra_if *zif = ifp->info;
1594 
1595 	zif->rtadv.HomeAgentPreference = 0;
1596 
1597 	return CMD_SUCCESS;
1598 }
1599 
1600 DEFUN (ipv6_nd_homeagent_lifetime,
1601        ipv6_nd_homeagent_lifetime_cmd,
1602        "ipv6 nd home-agent-lifetime (0-65520)",
1603        "Interface IPv6 config commands\n"
1604        "Neighbor discovery\n"
1605        "Home Agent lifetime\n"
1606        "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1607 {
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;
1613 }
1614 
1615 DEFUN (no_ipv6_nd_homeagent_lifetime,
1616        no_ipv6_nd_homeagent_lifetime_cmd,
1617        "no ipv6 nd home-agent-lifetime [(0-65520)]",
1618        NO_STR
1619        "Interface IPv6 config commands\n"
1620        "Neighbor discovery\n"
1621        "Home Agent lifetime\n"
1622        "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1623 {
1624 	VTY_DECLVAR_CONTEXT(interface, ifp);
1625 	struct zebra_if *zif = ifp->info;
1626 
1627 	zif->rtadv.HomeAgentLifetime = -1;
1628 
1629 	return CMD_SUCCESS;
1630 }
1631 
1632 DEFUN (ipv6_nd_managed_config_flag,
1633        ipv6_nd_managed_config_flag_cmd,
1634        "ipv6 nd managed-config-flag",
1635        "Interface IPv6 config commands\n"
1636        "Neighbor discovery\n"
1637        "Managed address configuration flag\n")
1638 {
1639 	VTY_DECLVAR_CONTEXT(interface, ifp);
1640 	struct zebra_if *zif = ifp->info;
1641 
1642 	zif->rtadv.AdvManagedFlag = 1;
1643 
1644 	return CMD_SUCCESS;
1645 }
1646 
1647 DEFUN (no_ipv6_nd_managed_config_flag,
1648        no_ipv6_nd_managed_config_flag_cmd,
1649        "no ipv6 nd managed-config-flag",
1650        NO_STR
1651        "Interface IPv6 config commands\n"
1652        "Neighbor discovery\n"
1653        "Managed address configuration flag\n")
1654 {
1655 	VTY_DECLVAR_CONTEXT(interface, ifp);
1656 	struct zebra_if *zif = ifp->info;
1657 
1658 	zif->rtadv.AdvManagedFlag = 0;
1659 
1660 	return CMD_SUCCESS;
1661 }
1662 
1663 DEFUN (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 {
1670 	VTY_DECLVAR_CONTEXT(interface, ifp);
1671 	struct zebra_if *zif = ifp->info;
1672 
1673 	zif->rtadv.AdvHomeAgentFlag = 1;
1674 
1675 	return CMD_SUCCESS;
1676 }
1677 
1678 DEFUN (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 {
1686 	VTY_DECLVAR_CONTEXT(interface, ifp);
1687 	struct zebra_if *zif = ifp->info;
1688 
1689 	zif->rtadv.AdvHomeAgentFlag = 0;
1690 
1691 	return CMD_SUCCESS;
1692 }
1693 
1694 DEFUN (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 {
1701 	VTY_DECLVAR_CONTEXT(interface, ifp);
1702 	struct zebra_if *zif = ifp->info;
1703 
1704 	zif->rtadv.AdvIntervalOption = 1;
1705 
1706 	return CMD_SUCCESS;
1707 }
1708 
1709 DEFUN (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 {
1717 	VTY_DECLVAR_CONTEXT(interface, ifp);
1718 	struct zebra_if *zif = ifp->info;
1719 
1720 	zif->rtadv.AdvIntervalOption = 0;
1721 
1722 	return CMD_SUCCESS;
1723 }
1724 
1725 DEFUN (ipv6_nd_other_config_flag,
1726        ipv6_nd_other_config_flag_cmd,
1727        "ipv6 nd other-config-flag",
1728        "Interface IPv6 config commands\n"
1729        "Neighbor discovery\n"
1730        "Other statefull configuration flag\n")
1731 {
1732 	VTY_DECLVAR_CONTEXT(interface, ifp);
1733 	struct zebra_if *zif = ifp->info;
1734 
1735 	zif->rtadv.AdvOtherConfigFlag = 1;
1736 
1737 	return CMD_SUCCESS;
1738 }
1739 
1740 DEFUN (no_ipv6_nd_other_config_flag,
1741        no_ipv6_nd_other_config_flag_cmd,
1742        "no ipv6 nd other-config-flag",
1743        NO_STR
1744        "Interface IPv6 config commands\n"
1745        "Neighbor discovery\n"
1746        "Other statefull configuration flag\n")
1747 {
1748 	VTY_DECLVAR_CONTEXT(interface, ifp);
1749 	struct zebra_if *zif = ifp->info;
1750 
1751 	zif->rtadv.AdvOtherConfigFlag = 0;
1752 
1753 	return CMD_SUCCESS;
1754 }
1755 
1756 DEFUN (ipv6_nd_prefix,
1757        ipv6_nd_prefix_cmd,
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]>]",
1759        "Interface IPv6 config commands\n"
1760        "Neighbor discovery\n"
1761        "Prefix information\n"
1762        "IPv6 prefix\n"
1763        "Valid lifetime in seconds\n"
1764        "Infinite valid lifetime\n"
1765        "Preferred lifetime in seconds\n"
1766        "Infinite preferred lifetime\n"
1767        "Set Router Address flag\n"
1768        "Do not use prefix for onlink determination\n"
1769        "Do not use prefix for autoconfiguration\n"
1770        "Do not use prefix for autoconfiguration\n"
1771        "Do not use prefix for onlink determination\n")
1772 {
1773 	/* prelude */
1774 	char *prefix = argv[3]->arg;
1775 	int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
1776 				       || strmatch(argv[4]->text, "infinite"));
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;
1819 	rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
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;
1838 }
1839 
1840 DEFUN (no_ipv6_nd_prefix,
1841        no_ipv6_nd_prefix_cmd,
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
1844        "Interface IPv6 config commands\n"
1845        "Neighbor discovery\n"
1846        "Prefix information\n"
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")
1857 {
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 */
1870 	rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
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;
1879 }
1880 
1881 DEFUN (ipv6_nd_router_preference,
1882        ipv6_nd_router_preference_cmd,
1883        "ipv6 nd router-preference <high|medium|low>",
1884        "Interface IPv6 config commands\n"
1885        "Neighbor discovery\n"
1886        "Default router preference\n"
1887        "High default router preference\n"
1888        "Medium default router preference (default)\n"
1889        "Low default router preference\n")
1890 {
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++;
1904 	}
1905 
1906 	return CMD_ERR_NO_MATCH;
1907 }
1908 
1909 DEFUN (no_ipv6_nd_router_preference,
1910        no_ipv6_nd_router_preference_cmd,
1911        "no ipv6 nd router-preference [<high|medium|low>]",
1912        NO_STR
1913        "Interface IPv6 config commands\n"
1914        "Neighbor discovery\n"
1915        "Default router preference\n"
1916        "High default router preference\n"
1917        "Medium default router preference (default)\n"
1918        "Low default router preference\n")
1919 {
1920 	VTY_DECLVAR_CONTEXT(interface, ifp);
1921 	struct zebra_if *zif = ifp->info;
1922 
1923 	zif->rtadv.DefaultPreference =
1924 		RTADV_PREF_MEDIUM; /* Default per RFC4191. */
1925 
1926 	return CMD_SUCCESS;
1927 }
1928 
1929 DEFUN (ipv6_nd_mtu,
1930        ipv6_nd_mtu_cmd,
1931        "ipv6 nd mtu (1-65535)",
1932        "Interface IPv6 config commands\n"
1933        "Neighbor discovery\n"
1934        "Advertised MTU\n"
1935        "MTU in bytes\n")
1936 {
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;
1942 }
1943 
1944 DEFUN (no_ipv6_nd_mtu,
1945        no_ipv6_nd_mtu_cmd,
1946        "no ipv6 nd mtu [(1-65535)]",
1947        NO_STR
1948        "Interface IPv6 config commands\n"
1949        "Neighbor discovery\n"
1950        "Advertised MTU\n"
1951        "MTU in bytes\n")
1952 {
1953 	VTY_DECLVAR_CONTEXT(interface, ifp);
1954 	struct zebra_if *zif = ifp->info;
1955 	zif->rtadv.AdvLinkMTU = 0;
1956 	return CMD_SUCCESS;
1957 }
1958 
rtadv_rdnss_new(void)1959 static struct rtadv_rdnss *rtadv_rdnss_new(void)
1960 {
1961 	return XCALLOC(MTYPE_RTADV_RDNSS, sizeof(struct rtadv_rdnss));
1962 }
1963 
rtadv_rdnss_free(struct rtadv_rdnss * rdnss)1964 static void rtadv_rdnss_free(struct rtadv_rdnss *rdnss)
1965 {
1966 	XFREE(MTYPE_RTADV_RDNSS, rdnss);
1967 }
1968 
rtadv_rdnss_lookup(struct list * list,struct rtadv_rdnss * rdnss)1969 static 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 
rtadv_rdnss_get(struct list * list,struct rtadv_rdnss * rdnss)1981 static 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 
rtadv_rdnss_set(struct zebra_if * zif,struct rtadv_rdnss * rdnss)1997 static 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 
rtadv_rdnss_reset(struct zebra_if * zif,struct rtadv_rdnss * rdnss)2006 static 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 
rtadv_dnssl_new(void)2020 static struct rtadv_dnssl *rtadv_dnssl_new(void)
2021 {
2022 	return XCALLOC(MTYPE_RTADV_DNSSL, sizeof(struct rtadv_dnssl));
2023 }
2024 
rtadv_dnssl_free(struct rtadv_dnssl * dnssl)2025 static void rtadv_dnssl_free(struct rtadv_dnssl *dnssl)
2026 {
2027 	XFREE(MTYPE_RTADV_DNSSL, dnssl);
2028 }
2029 
rtadv_dnssl_lookup(struct list * list,struct rtadv_dnssl * dnssl)2030 static 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 
rtadv_dnssl_get(struct list * list,struct rtadv_dnssl * dnssl)2042 static 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 
rtadv_dnssl_set(struct zebra_if * zif,struct rtadv_dnssl * dnssl)2058 static 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 
rtadv_dnssl_reset(struct zebra_if * zif,struct rtadv_dnssl * dnssl)2066 static 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  */
rtadv_dnssl_encode(uint8_t * out,const char * in)2088 static 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 
2119 DEFUN(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;
2131 	struct rtadv_rdnss rdnss = {};
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 
2151 DEFUN(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;
2164 	struct rtadv_rdnss rdnss = {};
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 
2178 DEFUN(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;
2190 	struct rtadv_dnssl dnssl = {};
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 
2227 DEFUN(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;
2240 	struct rtadv_dnssl dnssl = {};
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 
2261 /* Dump interface ND information to vty. */
nd_dump_vty(struct vty * vty,struct interface * ifp)2262 static 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,
2276 			"  ND advertised retransmit interval is %u milliseconds\n",
2277 			rtadv->AdvRetransTimer);
2278 		vty_out(vty, "  ND advertised hop-count limit is %d hops\n",
2279 			rtadv->AdvCurHopLimit);
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,
2285 				"  ND router advertisements are sent every %d milliseconds\n",
2286 				interval);
2287 		else
2288 			vty_out(vty,
2289 				"  ND router advertisements are sent every %d seconds\n",
2290 				interval / 1000);
2291 		if (!rtadv->UseFastRexmit)
2292 			vty_out(vty,
2293 				"  ND router advertisements do not use fast retransmit\n");
2294 
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,
2303 			"  ND router advertisement default router preference is %s\n",
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 
2331 
2332 /* Write configuration about router advertisement. */
rtadv_config_write(struct vty * vty,struct interface * ifp)2333 static int rtadv_config_write(struct vty *vty, struct interface *ifp)
2334 {
2335 	struct zebra_if *zif;
2336 	struct listnode *node;
2337 	struct rtadv_prefix *rprefix;
2338 	struct rtadv_rdnss *rdnss;
2339 	struct rtadv_dnssl *dnssl;
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))) {
2347 		if (zif->rtadv.AdvSendAdvertisements
2348 		    && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
2349 			vty_out(vty, " no ipv6 nd suppress-ra\n");
2350 	}
2351 
2352 	interval = zif->rtadv.MaxRtrAdvInterval;
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 	}
2361 
2362 	if (zif->rtadv.AdvIntervalOption)
2363 		vty_out(vty, " ipv6 nd adv-interval-option\n");
2364 
2365 	if (!zif->rtadv.UseFastRexmit)
2366 		vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
2367 
2368 	if (zif->rtadv.AdvRetransTimer != 0)
2369 		vty_out(vty, " ipv6 nd ra-retrans-interval %u\n",
2370 			zif->rtadv.AdvRetransTimer);
2371 
2372 	if (zif->rtadv.AdvCurHopLimit != RTADV_DEFAULT_HOPLIMIT)
2373 		vty_out(vty, " ipv6 nd ra-hop-limit %d\n",
2374 			zif->rtadv.AdvCurHopLimit);
2375 
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)) {
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");
2434 		}
2435 	}
2436 
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 	}
2460 	return 0;
2461 }
2462 
2463 
rtadv_event(struct zebra_vrf * zvrf,enum rtadv_event event,int val)2464 static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
2465 {
2466 	struct rtadv *rtadv = &zvrf->rtadv;
2467 
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 
2475 	switch (event) {
2476 	case RTADV_START:
2477 		thread_add_read(zrouter.master, rtadv_read, zvrf, val,
2478 				&rtadv->ra_read);
2479 		thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
2480 				 &rtadv->ra_timer);
2481 		break;
2482 	case RTADV_STOP:
2483 		THREAD_OFF(rtadv->ra_timer);
2484 		THREAD_OFF(rtadv->ra_read);
2485 		break;
2486 	case RTADV_TIMER:
2487 		thread_add_timer(zrouter.master, rtadv_timer, zvrf, val,
2488 				 &rtadv->ra_timer);
2489 		break;
2490 	case RTADV_TIMER_MSEC:
2491 		thread_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val,
2492 				      &rtadv->ra_timer);
2493 		break;
2494 	case RTADV_READ:
2495 		thread_add_read(zrouter.master, rtadv_read, zvrf, val,
2496 				&rtadv->ra_read);
2497 		break;
2498 	default:
2499 		break;
2500 	}
2501 	return;
2502 }
2503 
rtadv_init(struct zebra_vrf * zvrf)2504 void rtadv_init(struct zebra_vrf *zvrf)
2505 {
2506 	if (vrf_is_backend_netns()) {
2507 		zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
2508 		zrouter.rtadv_sock = -1;
2509 	} else {
2510 		zvrf->rtadv.sock = -1;
2511 		if (zrouter.rtadv_sock < 0)
2512 			zrouter.rtadv_sock =
2513 				rtadv_make_socket(zvrf->zns->ns_id);
2514 	}
2515 }
2516 
rtadv_vrf_terminate(struct zebra_vrf * zvrf)2517 void rtadv_vrf_terminate(struct zebra_vrf *zvrf)
2518 {
2519 	rtadv_event(zvrf, RTADV_STOP, 0);
2520 	if (zvrf->rtadv.sock >= 0) {
2521 		close(zvrf->rtadv.sock);
2522 		zvrf->rtadv.sock = -1;
2523 	}
2524 
2525 	zvrf->rtadv.adv_if_count = 0;
2526 	zvrf->rtadv.adv_msec_if_count = 0;
2527 }
2528 
rtadv_terminate(void)2529 void rtadv_terminate(void)
2530 {
2531 	if (zrouter.rtadv_sock >= 0) {
2532 		close(zrouter.rtadv_sock);
2533 		zrouter.rtadv_sock = -1;
2534 	}
2535 }
2536 
rtadv_cmd_init(void)2537 void rtadv_cmd_init(void)
2538 {
2539 	hook_register(zebra_if_extra_info, nd_dump_vty);
2540 	hook_register(zebra_if_config_wr, rtadv_config_write);
2541 
2542 	install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
2543 	install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
2544 	install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
2545 	install_element(INTERFACE_NODE, &no_ipv6_nd_ra_retrans_interval_cmd);
2546 	install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd);
2547 	install_element(INTERFACE_NODE, &no_ipv6_nd_ra_hop_limit_cmd);
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);
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);
2581 }
2582 
if_join_all_router(int sock,struct interface * ifp)2583 static int if_join_all_router(int sock, struct interface *ifp)
2584 {
2585 	int ret;
2586 
2587 	struct ipv6_mreq mreq;
2588 
2589 	memset(&mreq, 0, sizeof(struct ipv6_mreq));
2590 	inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2591 	mreq.ipv6mr_interface = ifp->ifindex;
2592 
2593 	ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq,
2594 			 sizeof(mreq));
2595 	if (ret < 0)
2596 		flog_err_sys(EC_LIB_SOCKET,
2597 			     "%s(%u): Failed to join group, socket %u error %s",
2598 			     ifp->name, ifp->ifindex, sock,
2599 			     safe_strerror(errno));
2600 
2601 	if (IS_ZEBRA_DEBUG_EVENT) {
2602 		struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
2603 
2604 		zlog_debug(
2605 			"%s(%s:%u): Join All-Routers multicast group, socket %u",
2606 			ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, sock);
2607 	}
2608 
2609 	return 0;
2610 }
2611 
if_leave_all_router(int sock,struct interface * ifp)2612 static int if_leave_all_router(int sock, struct interface *ifp)
2613 {
2614 	int ret;
2615 
2616 	struct ipv6_mreq mreq;
2617 
2618 	memset(&mreq, 0, sizeof(struct ipv6_mreq));
2619 	inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2620 	mreq.ipv6mr_interface = ifp->ifindex;
2621 
2622 	ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
2623 			 sizeof(mreq));
2624 	if (ret < 0) {
2625 		struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
2626 
2627 		flog_err_sys(
2628 			EC_LIB_SOCKET,
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);
2635 
2636 		zlog_debug(
2637 			"%s(%s:%u): Leave All-Routers multicast group, socket %u",
2638 			ifp->name, VRF_LOGNAME(vrf), ifp->ifindex, sock);
2639 	}
2640 	return 0;
2641 }
2642 
2643 #else
rtadv_init(struct zebra_vrf * zvrf)2644 void rtadv_init(struct zebra_vrf *zvrf)
2645 {
2646 	/* Empty.*/;
2647 }
rtadv_terminate(void)2648 void rtadv_terminate(void)
2649 {
2650 	/* Empty.*/;
2651 }
rtadv_cmd_init(void)2652 void rtadv_cmd_init(void)
2653 {
2654 	/* Empty.*/;
2655 }
2656 
rtadv_add_prefix(struct zebra_if * zif,const struct prefix_ipv6 * p)2657 void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p)
2658 {
2659 	/* Empty.*/;
2660 }
2661 
rtadv_delete_prefix(struct zebra_if * zif,const struct prefix * p)2662 void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
2663 {
2664 	/* Empty.*/;
2665 }
2666 
rtadv_stop_ra(struct interface * ifp)2667 void rtadv_stop_ra(struct interface *ifp)
2668 {
2669 	/* Empty.*/;
2670 }
2671 
rtadv_stop_ra_all(void)2672 void rtadv_stop_ra_all(void)
2673 {
2674 	/* Empty.*/;
2675 }
2676 
2677 /*
2678  * If the end user does not have RADV enabled we should
2679  * handle this better
2680  */
zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)2681 void 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 
zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)2691 void 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 
2701 #endif /* HAVE_RTADV */
2702