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