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