1 /*
2 * Copyright (c) 2003-2025 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /*
30 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
31 * All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. Neither the name of the project nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 */
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/malloc.h>
60 #include <sys/mbuf.h>
61 #include <sys/socket.h>
62 #include <sys/sockio.h>
63 #include <sys/time.h>
64 #include <sys/kernel.h>
65 #include <sys/errno.h>
66 #include <sys/syslog.h>
67 #include <sys/queue.h>
68 #include <sys/mcache.h>
69 #include <sys/protosw.h>
70
71 #include <dev/random/randomdev.h>
72
73 #include <kern/locks.h>
74 #include <kern/uipc_domain.h>
75 #include <kern/zalloc.h>
76 #include <machine/machine_routines.h>
77
78 #include <net/droptap.h>
79 #include <net/if.h>
80 #include <net/if_var.h>
81 #include <net/if_types.h>
82 #include <net/if_dl.h>
83 #include <net/route.h>
84 #include <net/radix.h>
85
86 #include <netinet/in.h>
87 #include <netinet6/in6_var.h>
88 #include <netinet6/in6_ifattach.h>
89 #include <netinet/ip6.h>
90 #include <netinet6/ip6_var.h>
91 #include <netinet6/nd6.h>
92 #include <netinet/icmp6.h>
93 #include <netinet6/scope6_var.h>
94
95 #include <net/net_osdep.h>
96
97 #include <net/sockaddr_utils.h>
98
99 static void defrouter_addreq(struct nd_defrouter *, struct nd_route_info *, boolean_t);
100 static struct nd_defrouter *defrtrlist_update_common(struct nd_defrouter *,
101 struct nd_drhead *, boolean_t);
102 static void pfxrtr_add(struct nd_prefix *, struct nd_defrouter *);
103 static void pfxrtr_del(struct nd_pfxrouter *, struct nd_prefix *);
104 static struct nd_pfxrouter *find_pfxlist_reachable_router(struct nd_prefix *);
105 static void nd6_rtmsg(u_char, struct rtentry *);
106
107 static int nd6_prefix_onlink_common(struct nd_prefix *, boolean_t,
108 unsigned int);
109 static struct nd_prefix *nd6_prefix_equal_lookup(struct nd_prefix *, boolean_t);
110 static void nd6_prefix_sync(struct ifnet *);
111
112 static void in6_init_address_ltimes(struct in6_addrlifetime *);
113 static int rt6_deleteroute(struct radix_node *, void *);
114
115 static struct nd_defrouter *nddr_alloc(zalloc_flags_t);
116 static void nddr_free(struct nd_defrouter *);
117 static void nddr_trace(struct nd_defrouter *, int);
118
119 static struct nd_prefix *ndpr_alloc(int);
120 static void ndpr_free(struct nd_prefix *);
121 static void ndpr_trace(struct nd_prefix *, int);
122
123 extern int nd6_recalc_reachtm_interval;
124
125 static struct ifnet *nd6_defifp = NULL;
126 int nd6_defifindex = 0;
127 static unsigned int nd6_defrouter_genid;
128
129 int ip6_use_tempaddr = IP6_USE_TMPADDR_DEFAULT; /* use temp addr by default for testing now */
130 int ip6_ula_use_tempaddr = IP6_ULA_USE_TMPADDR_DEFAULT;
131
132 int nd6_accept_6to4 = 1;
133
134 int ip6_desync_factor;
135 u_int32_t ip6_temp_preferred_lifetime = DEF_TEMP_PREFERRED_LIFETIME;
136 u_int32_t ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME;
137 /*
138 * shorter lifetimes for debugging purposes.
139 * u_int32_t ip6_temp_preferred_lifetime = 800;
140 * static u_int32_t ip6_temp_valid_lifetime = 1800;
141 */
142 int ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
143
144 /* Serialization variables for single thread access to nd_prefix */
145 static boolean_t nd_prefix_busy;
146 static void *nd_prefix_waitchan = &nd_prefix_busy;
147 static int nd_prefix_waiters = 0;
148
149 /* Serialization variables for single thread access to nd_defrouter */
150 static boolean_t nd_defrouter_busy;
151 static void *nd_defrouter_waitchan = &nd_defrouter_busy;
152 static int nd_defrouter_waiters = 0;
153
154 void
nd_prefix_busy_wait(void)155 nd_prefix_busy_wait(void)
156 {
157 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
158
159 while (nd_prefix_busy) {
160 nd_prefix_waiters++;
161 msleep(nd_prefix_waitchan, nd6_mutex, (PZERO - 1),
162 __func__, NULL);
163 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
164 }
165 nd_prefix_busy = TRUE;
166 }
167
168 void
nd_prefix_busy_signal(void)169 nd_prefix_busy_signal(void)
170 {
171 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
172
173 VERIFY(nd_prefix_busy);
174 nd_prefix_busy = FALSE;
175 if (nd_prefix_waiters > 0) {
176 nd_prefix_waiters = 0;
177 wakeup(nd_prefix_waitchan);
178 }
179 }
180
181 #define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
182 /* RTPREF_MEDIUM has to be 0! */
183 #define RTPREF_HIGH 1
184 #define RTPREF_MEDIUM 0
185 #define RTPREF_LOW (-1)
186 #define RTPREF_RESERVED (-2)
187 #define RTPREF_INVALID (-3) /* internal */
188
189 #define NDPR_TRACE_HIST_SIZE 32 /* size of trace history */
190
191 /* For gdb */
192 __private_extern__ unsigned int ndpr_trace_hist_size = NDPR_TRACE_HIST_SIZE;
193
194 struct nd_prefix_dbg {
195 struct nd_prefix ndpr_pr; /* nd_prefix */
196 u_int16_t ndpr_refhold_cnt; /* # of ref */
197 u_int16_t ndpr_refrele_cnt; /* # of rele */
198 /*
199 * Circular lists of ndpr_addref and ndpr_remref callers.
200 */
201 ctrace_t ndpr_refhold[NDPR_TRACE_HIST_SIZE];
202 ctrace_t ndpr_refrele[NDPR_TRACE_HIST_SIZE];
203 };
204
205 static unsigned int ndpr_debug; /* debug flags */
206 ZONE_DECLARE(ndpr_zone, struct nd_prefix);
207 #define NDPR_ZONE_NAME "nd6_prefix" /* zone name */
208 zone_t ndpr_zone; /* zone for nd_prefix */
209
210 #define NDDR_TRACE_HIST_SIZE 32 /* size of trace history */
211
212 /* For gdb */
213 __private_extern__ unsigned int nddr_trace_hist_size = NDDR_TRACE_HIST_SIZE;
214
215 struct nd_defrouter_dbg {
216 struct nd_defrouter nddr_dr; /* nd_defrouter */
217 uint16_t nddr_refhold_cnt; /* # of ref */
218 uint16_t nddr_refrele_cnt; /* # of rele */
219 /*
220 * Circular lists of nddr_addref and nddr_remref callers.
221 */
222 ctrace_t nddr_refhold[NDDR_TRACE_HIST_SIZE];
223 ctrace_t nddr_refrele[NDDR_TRACE_HIST_SIZE];
224 };
225
226 static unsigned int nddr_debug; /* debug flags */
227 ZONE_DECLARE(nddr_zone, struct nd_defrouter);
228 #define NDDR_ZONE_NAME "nd6_defrouter" /* zone name */
229 zone_t nddr_zone; /* zone for nd_defrouter */
230
231 static KALLOC_TYPE_DEFINE(ndprtr_zone, struct nd_pfxrouter, NET_KT_DEFAULT);
232
233 #define TWOHOUR (120*60)
234 extern int nd6_process_rti; /* Default to 0 for now */
235
236
237 static void
nd6_prefix_glb_init(void)238 nd6_prefix_glb_init(void)
239 {
240 PE_parse_boot_argn("ifa_debug", &ndpr_debug, sizeof(ndpr_debug));
241 vm_size_t ndpr_size = (ndpr_debug == 0) ? sizeof(struct nd_prefix) :
242 sizeof(struct nd_prefix_dbg);
243 ndpr_zone = zone_create(NDPR_ZONE_NAME, ndpr_size, ZC_ZFREE_CLEARMEM);
244 }
245
246 static void
nd6_defrouter_glb_init(void)247 nd6_defrouter_glb_init(void)
248 {
249 PE_parse_boot_argn("ifa_debug", &nddr_debug, sizeof(nddr_debug));
250 vm_size_t nddr_size = (nddr_debug == 0) ? sizeof(struct nd_defrouter) :
251 sizeof(struct nd_defrouter_dbg);
252 nddr_zone = zone_create(NDDR_ZONE_NAME, nddr_size, ZC_ZFREE_CLEARMEM);
253 }
254
255 void
nd6_rtr_init(void)256 nd6_rtr_init(void)
257 {
258 nd6_prefix_glb_init();
259 nd6_defrouter_glb_init();
260 }
261
262 /*
263 * Receive Router Solicitation Message - just for routers.
264 * Router solicitation/advertisement is mostly managed by userland program
265 * (rtadvd) so here we have no function like nd6_ra_output().
266 *
267 * Based on RFC 2461
268 */
269 void
nd6_rs_input(struct mbuf * m,int off,int icmp6len)270 nd6_rs_input(
271 struct mbuf *m,
272 int off,
273 int icmp6len)
274 {
275 struct ifnet *ifp = m->m_pkthdr.rcvif;
276 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
277 struct nd_router_solicit *nd_rs = NULL;
278 struct in6_addr saddr6 = ip6->ip6_src;
279 char *lladdr = NULL;
280 int lladdrlen = 0;
281 union nd_opts ndopts = {};
282 drop_reason_t drop_reason = DROP_REASON_UNSPECIFIED;
283
284 /* Expect 32-bit aligned data pointer on strict-align platforms */
285 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
286
287 /* If I'm not a router, ignore it. */
288 if (!ip6_forwarding || ifp->if_ipv6_router_mode == IPV6_ROUTER_MODE_DISABLED) {
289 goto freeit;
290 }
291
292 /* Sanity checks */
293 if (ip6->ip6_hlim != IPV6_MAXHLIM) {
294 nd6log0(error,
295 "nd6_rs_input: invalid hlim (%d) from %s to %s on %s\n",
296 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
297 ip6_sprintf(&ip6->ip6_dst), if_name(ifp));
298 drop_reason = DROP_REASON_IP6_BAD_HLIM;
299 goto bad;
300 }
301
302 /*
303 * Don't update the neighbor cache, if src = :: or a non-neighbor.
304 * The former case indicates that the src has no IP address assigned
305 * yet. See nd6_ns_input() for the latter case.
306 */
307 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
308 goto freeit;
309 } else {
310 struct sockaddr_in6 src_sa6;
311
312 SOCKADDR_ZERO(&src_sa6, sizeof(src_sa6));
313 src_sa6.sin6_family = AF_INET6;
314 src_sa6.sin6_len = sizeof(src_sa6);
315 src_sa6.sin6_addr = ip6->ip6_src;
316 src_sa6.sin6_scope_id = (!in6_embedded_scope && IN6_IS_SCOPE_EMBED(&src_sa6.sin6_addr)) ? ip6_input_getsrcifscope(m) : IFSCOPE_NONE;
317 if (!nd6_is_addr_neighbor(&src_sa6, ifp, 0)) {
318 nd6log(info, "nd6_rs_input: "
319 "RS packet from non-neighbor\n");
320 goto freeit;
321 }
322 }
323
324 IP6_EXTHDR_CHECK(m, off, icmp6len, return );
325 ip6 = mtod(m, struct ip6_hdr *);
326 nd_rs = (struct nd_router_solicit *)((caddr_t)ip6 + off);
327
328 icmp6len -= sizeof(*nd_rs);
329
330 nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
331 if (nd6_options(&ndopts) < 0) {
332 nd6log(info,
333 "nd6_rs_input: invalid ND option, ignored\n");
334 /* nd6_options have incremented stats */
335 goto freeit;
336 }
337
338 if (ndopts.nd_opts_src_lladdr) {
339 ND_OPT_LLADDR(ndopts.nd_opts_src_lladdr, nd_opt_len, lladdr, lladdrlen);
340 }
341
342 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
343 nd6log(info,
344 "nd6_rs_input: lladdrlen mismatch for %s "
345 "(if %d, RS packet %d)\n",
346 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2);
347 drop_reason = DROP_REASON_IP6_RS_BAD_LLADDR_LEN;
348 goto bad;
349 }
350
351 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0, NULL);
352
353 freeit:
354 m_freem(m);
355 return;
356
357 bad:
358 icmp6stat.icp6s_badrs++;
359 m_drop(m, DROPTAP_FLAG_DIR_IN | DROPTAP_FLAG_L2_MISSING, drop_reason, NULL, 0);
360 }
361
362 #define ND_OPT_LEN_TO_BYTE_SCALE 3 /* ND opt len is in units of 8 octets */
363
364 #define ND_OPT_LEN_RTI_MIN 1
365 #define ND_OPT_LEN_RTI_MAX 3
366 #define ND_OPT_RTI_PFXLEN_MAX 128
367 /*
368 * Receive Router Advertisement Message.
369 *
370 * Based on RFC 2461
371 * TODO: on-link bit on prefix information
372 * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
373 */
374 void
nd6_ra_input(struct mbuf * m,int off,int icmp6len)375 nd6_ra_input(
376 struct mbuf *m,
377 int off,
378 int icmp6len)
379 {
380 ifnet_ref_t ifp = m->m_pkthdr.rcvif;
381 struct nd_ifinfo *ndi = NULL;
382 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
383 struct nd_router_advert *nd_ra;
384 struct in6_addr saddr6 = ip6->ip6_src;
385 int mcast = 0;
386 union nd_opts ndopts;
387 struct nd_defrouter *dr = NULL;
388 u_int32_t mtu = 0;
389 char *lladdr = NULL;
390 u_int32_t lladdrlen = 0;
391 struct nd_prefix_list *nd_prefix_list_head = NULL;
392 u_int32_t nd_prefix_list_length = 0;
393 struct in6_ifaddr *ia6 = NULL;
394 struct nd_prefix_list *__single prfl;
395 struct nd_defrouter dr0 = {0};
396 u_int32_t advreachable;
397 boolean_t rti_defrtr_processed = FALSE;
398 boolean_t is_local_ra = FALSE;
399 drop_reason_t drop_reason = DROP_REASON_UNSPECIFIED;
400
401 #if (DEVELOPMENT || DEBUG)
402 if (ip6_accept_rtadv == 0) {
403 goto freeit;
404 }
405 #endif /* (DEVELOPMENT || DEBUG) */
406 /* Expect 32-bit aligned data pointer on strict-align platforms */
407 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
408
409 /*
410 * Accept the RA if IFEF_ACCEPT_RTADV is set, or when
411 * the RA is locally generated.
412 *
413 * For convenience, we allow locally generated (rtadvd)
414 * RAs to be processed on the advertising interface, as a router.
415 *
416 * Note that we don't test against ip6_forwarding as we could be
417 * both a host and a router on different interfaces, hence the
418 * check against the per-interface flags.
419 */
420
421 is_local_ra = (ia6 = ifa_foraddr6(&saddr6)) != NULL;
422 if (ia6 != NULL) {
423 ifa_remref(&ia6->ia_ifa);
424 ia6 = NULL;
425 }
426
427 if ((ifp->if_eflags & IFEF_ACCEPT_RTADV) == 0) {
428 if (is_local_ra) {
429 /* accept locally generated RA */
430 } else {
431 nd6log(debug,
432 "%s: skipping RA from %s to %s on %s, accept RA: %d local RA=%d\n",
433 __func__,
434 ip6_sprintf(&ip6->ip6_src),
435 ip6_sprintf(&ip6->ip6_dst), if_name(ifp),
436 (ifp->if_eflags & IFEF_ACCEPT_RTADV) == 0, is_local_ra);
437 goto freeit;
438 }
439 }
440
441 if (ip6->ip6_hlim != IPV6_MAXHLIM) {
442 nd6log0(error,
443 "nd6_ra_input: invalid hlim (%d) from %s to %s on %s\n",
444 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
445 ip6_sprintf(&ip6->ip6_dst), if_name(ifp));
446 drop_reason = DROP_REASON_IP6_BAD_HLIM;
447 goto bad;
448 }
449
450 if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
451 nd6log0(error,
452 "nd6_ra_input: src %s is not link-local\n",
453 ip6_sprintf(&saddr6));
454 drop_reason = DROP_REASON_IP6_RA_NOT_LL;
455 goto bad;
456 }
457
458 nd6log(debug, "%s: accepting RA from %s to %s on %s, local RA=%d\n",
459 __func__,
460 ip6_sprintf(&ip6->ip6_src),
461 ip6_sprintf(&ip6->ip6_dst), if_name(ifp), is_local_ra);
462
463 IP6_EXTHDR_CHECK(m, off, icmp6len, return );
464 ip6 = mtod(m, struct ip6_hdr *);
465 nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off);
466
467 icmp6len -= sizeof(*nd_ra);
468
469 nd6_option_init(nd_ra + 1, icmp6len, &ndopts);
470 if (nd6_options(&ndopts) < 0) {
471 nd6log(info,
472 "nd6_ra_input: invalid ND option, ignored\n");
473 /* nd6_options have incremented stats */
474 goto freeit;
475 }
476
477 advreachable = nd_ra->nd_ra_reachable;
478
479 /* remember if this is a multicasted advertisement */
480 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
481 mcast = 1;
482 }
483
484 ndi = ND_IFINFO(ifp);
485 VERIFY(NULL != ndi && TRUE == ndi->initialized);
486 lck_mtx_lock(&ndi->lock);
487 /* unspecified or not? (RFC 2461 6.3.4) */
488 if (advreachable) {
489 advreachable = ntohl(advreachable);
490 if (advreachable <= MAX_REACHABLE_TIME &&
491 ndi->basereachable != advreachable) {
492 ndi->basereachable = advreachable;
493 ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable);
494 ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */
495 }
496 }
497 if (nd_ra->nd_ra_retransmit) {
498 u_int32_t retrans = ntohl(nd_ra->nd_ra_retransmit);
499 if (retrans < MAX_RA_RETRANS_TIMER) {
500 ndi->retrans = retrans;
501 } else {
502 nd6log0(info, "%s: ignoring retrans time of %u in RA from %s ;"
503 " Using default of %u",
504 __func__,
505 retrans, ip6_sprintf(&ip6->ip6_src), ndi->retrans);
506 }
507 }
508 if (nd_ra->nd_ra_curhoplimit) {
509 if (ndi->chlim < nd_ra->nd_ra_curhoplimit) {
510 ndi->chlim = nd_ra->nd_ra_curhoplimit;
511 } else if (ndi->chlim != nd_ra->nd_ra_curhoplimit) {
512 nd6log0(error,
513 "RA with a lower CurHopLimit sent from "
514 "%s on %s (current = %d, received = %d). "
515 "Ignored.\n", ip6_sprintf(&ip6->ip6_src),
516 if_name(ifp), ndi->chlim,
517 nd_ra->nd_ra_curhoplimit);
518 }
519 }
520 lck_mtx_unlock(&ndi->lock);
521
522 /* Initialize nd_defrouter invariants for RA processing */
523 bzero(&dr0, sizeof(dr0));
524 dr0.rtaddr = saddr6;
525 dr0.ifp = ifp;
526 if (is_local_ra == TRUE) {
527 dr0.stateflags |= NDDRF_LOCAL;
528 }
529
530 /*
531 * Route Information Option (RIO)
532 */
533 if (ndopts.nd_opts_rti && IFNET_IS_ETHERNET(ifp)) {
534 struct nd_opt_hdr *rt = NULL;
535 struct sockaddr_in6 rti_gateway = {0};
536
537 rti_gateway.sin6_family = AF_INET6;
538 rti_gateway.sin6_len = sizeof(rti_gateway);
539 memcpy(&rti_gateway.sin6_addr, &saddr6, sizeof(rti_gateway.sin6_addr));
540
541 for (rt = TAKE_ND_NEXT_OPT(ndopts.nd_opts_rti, nd_opts_rti, nd_opts_last);
542 rt <= (struct nd_opt_hdr *)ndopts.nd_opts_rti_end;
543 rt = (struct nd_opt_hdr *)((caddr_t)rt +
544 (rt->nd_opt_len << ND_OPT_LEN_TO_BYTE_SCALE))) {
545 struct sockaddr_in6 rti_prefix = {};
546 struct nd_route_info rti = {};
547 struct nd_opt_route_info *rti_opt = NULL;
548 u_int32_t rounded_prefix_bytes = 0;
549
550 if (rt->nd_opt_type != ND_OPT_ROUTE_INFO) {
551 continue;
552 }
553
554 rti_opt = (struct nd_opt_route_info *)rt;
555 if ((rti_opt->nd_opt_rti_len < ND_OPT_LEN_RTI_MIN) ||
556 (rti_opt->nd_opt_rti_len > ND_OPT_LEN_RTI_MAX)) {
557 nd6log(info,
558 "%s: invalid option "
559 "len %d for route information option, "
560 "ignored\n", __func__,
561 rti_opt->nd_opt_rti_len);
562 continue;
563 }
564
565 if (rti_opt->nd_opt_rti_prefixlen > ND_OPT_RTI_PFXLEN_MAX) {
566 nd6log(info,
567 "%s: invalid prefix length %d "
568 "in the route information option, "
569 "ignored\n", __func__, rti_opt->nd_opt_rti_prefixlen);
570 continue;
571 }
572
573 if (rti_opt->nd_opt_rti_prefixlen != 0 &&
574 rti_opt->nd_opt_rti_prefixlen <= 64 &&
575 rti_opt->nd_opt_rti_len == ND_OPT_LEN_RTI_MIN) {
576 nd6log(info,
577 "%s: invalid prefix "
578 "len %d is OOB for route information option, "
579 "with total option length of %d. Ignored.\n",
580 __func__, rti_opt->nd_opt_rti_prefixlen,
581 rti_opt->nd_opt_rti_len);
582 continue;
583 }
584
585 if (rti_opt->nd_opt_rti_prefixlen > 64 &&
586 rti_opt->nd_opt_rti_len != ND_OPT_LEN_RTI_MAX) {
587 nd6log(info,
588 "%s: invalid prefix "
589 "len %d is OOB for route information option, "
590 "with total option length of %d. Ignored.\n",
591 __func__, rti_opt->nd_opt_rti_prefixlen,
592 rti_opt->nd_opt_rti_len);
593 continue;
594 }
595
596 if ((rti_opt->nd_opt_rti_flags & ND_RA_FLAG_RTPREF_MASK) ==
597 ND_RA_FLAG_RTPREF_RSV) {
598 nd6log(info,
599 "%s: using reserved preference mask, "
600 "ignored\n", __func__);
601 continue;
602 }
603
604 rti_prefix.sin6_family = AF_INET6;
605 rti_prefix.sin6_len = sizeof(rti_prefix);
606
607 rounded_prefix_bytes = rti_opt->nd_opt_rti_prefixlen >> 3;
608 if (rti_opt->nd_opt_rti_prefixlen & 0x7) {
609 rounded_prefix_bytes++;
610 }
611 memcpy(&rti_prefix.sin6_addr, rti_opt + 1, rounded_prefix_bytes);
612
613 nd6log(info, "%s: received RA with route opt, "
614 "prefix %s/%u pref %u lifetime %u\n", __func__,
615 ip6_sprintf(&rti_prefix.sin6_addr),
616 rti_opt->nd_opt_rti_prefixlen,
617 rti_opt->nd_opt_rti_flags,
618 ntohl(rti_opt->nd_opt_rti_lifetime));
619
620 dr0.flags = rti_opt->nd_opt_rti_flags;
621
622 /*
623 * https://tools.ietf.org/html/rfc4191#section-3.1
624 * Type C Host requirements:
625 * The Router Preference and Lifetime values in a
626 * ::/0 Route Information Option override the
627 * preference and lifetime values in the Router
628 * Advertisement header.
629 */
630 if (IN6_IS_ADDR_UNSPECIFIED(&rti_prefix.sin6_addr)
631 && rti_opt->nd_opt_rti_prefixlen == 0) {
632 rti_defrtr_processed = TRUE;
633 /*
634 * If the router lifetime is 0, set the state flag
635 * to dummy, so that it is skipped and not used as a
636 * default router.
637 * Set the lifetime to 2 hrs to make sure we get rid
638 * of the router eventually if this was indeed for a router
639 * going away.
640 *
641 * We partly have to do this to ensure advertised prefixes
642 * stay onlink.
643 * A periodic RA would also keep refreshing the cached
644 * neighbor cache entry if it contains source link layer
645 * information.
646 */
647 if (rti_opt->nd_opt_rti_lifetime == 0) {
648 dr0.rtlifetime = TWOHOUR;
649 dr0.stateflags |= NDDRF_INELIGIBLE;
650 } else {
651 dr0.rtlifetime = ntohl(rti_opt->nd_opt_rti_lifetime);
652 }
653 dr0.expire = net_uptime() + dr0.rtlifetime;
654
655 lck_mtx_lock(nd6_mutex);
656 dr = defrtrlist_update(&dr0, NULL);
657 if (dr != NULL) {
658 dr->is_reachable = TRUE;
659 }
660 lck_mtx_unlock(nd6_mutex);
661 continue;
662 }
663
664 dr0.rtlifetime = ntohl(rti_opt->nd_opt_rti_lifetime);
665 dr0.expire = net_uptime() + dr0.rtlifetime;
666 bzero(&rti, sizeof(rti));
667 rti.nd_rti_prefixlen = rti_opt->nd_opt_rti_prefixlen;
668 rti.nd_rti_prefix = rti_prefix.sin6_addr;
669 nd6_rtilist_update(&rti, &dr0);
670 }
671 }
672
673 if (!rti_defrtr_processed) {
674 dr0.flags = nd_ra->nd_ra_flags_reserved;
675
676 /*
677 * If the router lifetime is 0, set the state flag
678 * to dummy, so that it is skipped and not used as a
679 * default router.
680 * Set the lifetime to 2 hrs to make sure we get rid
681 * of the router eventually if this was indeed for a router
682 * going away.
683 *
684 * We partly have to do this to ensure advertised prefixes
685 * stay onlink.
686 * A periodic RA would also keep refreshing the cached
687 * neighbor cache entry if it contains source link layer
688 * information.
689 */
690 if (nd_ra->nd_ra_router_lifetime == 0) {
691 dr0.rtlifetime = TWOHOUR;
692 dr0.stateflags |= NDDRF_INELIGIBLE;
693 } else {
694 dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
695 }
696 dr0.expire = net_uptime() + dr0.rtlifetime;
697 lck_mtx_lock(nd6_mutex);
698 dr = defrtrlist_update(&dr0, NULL);
699 if (dr != NULL) {
700 dr->is_reachable = TRUE;
701 }
702 lck_mtx_unlock(nd6_mutex);
703 }
704
705 /*
706 * prefix (PIO)
707 */
708 if (ndopts.nd_opts_pi) {
709 struct nd_opt_hdr *pt;
710 struct nd_opt_prefix_info *__single pi = NULL;
711 struct nd_prefix pr;
712
713 for (pt = TAKE_ND_NEXT_OPT(ndopts.nd_opts_pi, nd_opts_pi, nd_opts_last);
714 pt <= (struct nd_opt_hdr *)ndopts.nd_opts_pi_end;
715 pt = (struct nd_opt_hdr *)((caddr_t)pt +
716 (pt->nd_opt_len << ND_OPT_LEN_TO_BYTE_SCALE))) {
717 struct in6_addr pi_mask;
718 bzero(&pi_mask, sizeof(pi_mask));
719
720 if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION) {
721 continue;
722 }
723 pi = (struct nd_opt_prefix_info *)pt;
724
725 if (pi->nd_opt_pi_len != 4) {
726 nd6log(info,
727 "nd6_ra_input: invalid option "
728 "len %d for prefix information option, "
729 "ignored\n", pi->nd_opt_pi_len);
730 continue;
731 }
732
733 if (128 < pi->nd_opt_pi_prefix_len) {
734 nd6log(info,
735 "nd6_ra_input: invalid prefix "
736 "len %d for prefix information option, "
737 "ignored\n", pi->nd_opt_pi_prefix_len);
738 continue;
739 }
740
741 /*
742 * To ignore ::/64 make sure bits beyond prefixlen
743 * are set to zero
744 */
745 in6_prefixlen2mask(&pi_mask, pi->nd_opt_pi_prefix_len);
746 pi->nd_opt_pi_prefix.s6_addr32[0] &= pi_mask.s6_addr32[0];
747 pi->nd_opt_pi_prefix.s6_addr32[1] &= pi_mask.s6_addr32[1];
748 pi->nd_opt_pi_prefix.s6_addr32[2] &= pi_mask.s6_addr32[2];
749 pi->nd_opt_pi_prefix.s6_addr32[3] &= pi_mask.s6_addr32[3];
750
751 if (IN6_IS_ADDR_UNSPECIFIED(&pi->nd_opt_pi_prefix) ||
752 IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix) ||
753 IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
754 nd6log(info,
755 "%s: invalid prefix %s, ignored\n",
756 __func__,
757 ip6_sprintf(&pi->nd_opt_pi_prefix));
758 continue;
759 }
760
761 bzero(&pr, sizeof(pr));
762 lck_mtx_init(&pr.ndpr_lock, &ifa_mtx_grp, &ifa_mtx_attr);
763 NDPR_LOCK(&pr);
764 pr.ndpr_prefix.sin6_family = AF_INET6;
765 pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix);
766 pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix;
767 pr.ndpr_ifp = m->m_pkthdr.rcvif;
768
769 pr.ndpr_raf_onlink = (pi->nd_opt_pi_flags_reserved &
770 ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
771 pr.ndpr_raf_auto = (pi->nd_opt_pi_flags_reserved &
772 ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
773 pr.ndpr_plen = pi->nd_opt_pi_prefix_len;
774 pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time);
775 pr.ndpr_pltime =
776 ntohl(pi->nd_opt_pi_preferred_time);
777
778 /*
779 * Exceptions to stateless autoconfiguration processing:
780 * + nd6_accept_6to4 == 0 && address has 6to4 prefix
781 * + ip6_only_allow_rfc4193_prefix != 0 &&
782 * address not RFC 4193
783 */
784 if (ip6_only_allow_rfc4193_prefix &&
785 !IN6_IS_ADDR_UNIQUE_LOCAL(&pi->nd_opt_pi_prefix)) {
786 nd6log(info,
787 "nd6_ra_input: no SLAAC on prefix %s "
788 "[not RFC 4193]\n",
789 ip6_sprintf(&pi->nd_opt_pi_prefix));
790 pr.ndpr_raf_auto = 0;
791 } else if (!nd6_accept_6to4 &&
792 IN6_IS_ADDR_6TO4(&pi->nd_opt_pi_prefix)) {
793 nd6log(info,
794 "%s: no SLAAC on prefix %s "
795 "[6to4]\n", __func__,
796 ip6_sprintf(&pi->nd_opt_pi_prefix));
797 pr.ndpr_raf_auto = 0;
798 }
799
800 if (in6_init_prefix_ltimes(&pr)) {
801 NDPR_UNLOCK(&pr);
802 lck_mtx_destroy(&pr.ndpr_lock, &ifa_mtx_grp);
803 continue; /* prefix lifetime init failed */
804 } else {
805 NDPR_UNLOCK(&pr);
806 }
807 (void) prelist_update(&pr, dr, m, mcast);
808 lck_mtx_destroy(&pr.ndpr_lock, &ifa_mtx_grp);
809
810 /*
811 * We have to copy the values out after the
812 * prelist_update call since some of these values won't
813 * be properly set until after the router advertisement
814 * updating can vet the values.
815 */
816 prfl = kalloc_type(struct nd_prefix_list,
817 Z_WAITOK | Z_ZERO | Z_NOFAIL);
818
819 /* this is only for nd6_post_msg(), otherwise unused */
820 SOCKADDR_COPY(&pr.ndpr_prefix, &prfl->pr.ndpr_prefix,
821 sizeof(prfl->pr.ndpr_prefix));
822 prfl->pr.ndpr_raf = pr.ndpr_raf;
823 prfl->pr.ndpr_plen = pr.ndpr_plen;
824 prfl->pr.ndpr_vltime = pr.ndpr_vltime;
825 prfl->pr.ndpr_pltime = pr.ndpr_pltime;
826 prfl->pr.ndpr_expire = pr.ndpr_expire;
827 prfl->pr.ndpr_base_calendartime =
828 pr.ndpr_base_calendartime;
829 prfl->pr.ndpr_base_uptime = pr.ndpr_base_uptime;
830 prfl->pr.ndpr_stateflags = pr.ndpr_stateflags;
831 prfl->pr.ndpr_addrcnt = pr.ndpr_addrcnt;
832 prfl->pr.ndpr_ifp = pr.ndpr_ifp;
833
834 prfl->next = nd_prefix_list_head;
835 nd_prefix_list_head = prfl;
836 nd_prefix_list_length++;
837 }
838 }
839
840
841 /*
842 * MTU
843 */
844 if (ndopts.nd_opts_mtu && ndopts.nd_opts_mtu->nd_opt_mtu_len == 1) {
845 mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
846 /* lower bound */
847 if (mtu < IPV6_MMTU) {
848 nd6log(info, "nd6_ra_input: bogus mtu option "
849 "mtu=%d sent from %s, ignoring\n",
850 mtu, ip6_sprintf(&ip6->ip6_src));
851 goto skip;
852 }
853
854 lck_mtx_lock(&ndi->lock);
855 /* upper bound */
856 if (ndi->maxmtu) {
857 if (mtu <= ndi->maxmtu) {
858 int change = (ndi->linkmtu != mtu);
859
860 ndi->linkmtu = mtu;
861 lck_mtx_unlock(&ndi->lock);
862 if (change) { /* in6_maxmtu may change */
863 in6_setmaxmtu();
864 }
865 } else {
866 nd6log(info, "nd6_ra_input: bogus mtu "
867 "mtu=%d sent from %s; "
868 "exceeds maxmtu %d, ignoring\n",
869 mtu, ip6_sprintf(&ip6->ip6_src),
870 ndi->maxmtu);
871 lck_mtx_unlock(&ndi->lock);
872 }
873 } else {
874 lck_mtx_unlock(&ndi->lock);
875 nd6log(info, "nd6_ra_input: mtu option "
876 "mtu=%d sent from %s; maxmtu unknown, "
877 "ignoring\n",
878 mtu, ip6_sprintf(&ip6->ip6_src));
879 }
880 }
881
882 skip:
883
884 /*
885 * Source link layer address
886 */
887 if (ndopts.nd_opts_src_lladdr) {
888 ND_OPT_LLADDR(ndopts.nd_opts_src_lladdr, nd_opt_len, lladdr, lladdrlen);
889 }
890
891 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
892 nd6log(info,
893 "nd6_ra_input: lladdrlen mismatch for %s "
894 "(if %d, RA packet %d)\n",
895 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2);
896 drop_reason = DROP_REASON_IP6_RA_BAD_LLADDR_LEN;
897 goto bad;
898 }
899
900 if (dr && dr->stateflags & NDDRF_MAPPED) {
901 saddr6 = dr->rtaddr_mapped;
902 }
903
904 nd6_cache_lladdr(ifp, &saddr6, lladdr, (int)lladdrlen,
905 ND_ROUTER_ADVERT, 0, NULL);
906
907 /* Post message */
908 nd6_post_msg(KEV_ND6_RA, nd_prefix_list_head, nd_prefix_list_length,
909 mtu);
910
911 /*
912 * Installing a link-layer address might change the state of the
913 * router's neighbor cache, which might also affect our on-link
914 * detection of adveritsed prefixes.
915 */
916 lck_mtx_lock(nd6_mutex);
917 pfxlist_onlink_check(false);
918 lck_mtx_unlock(nd6_mutex);
919
920 freeit:
921 if (m) {
922 m_freem(m);
923 }
924 if (dr) {
925 NDDR_REMREF(dr);
926 }
927
928 prfl = NULL;
929 while ((prfl = nd_prefix_list_head) != NULL) {
930 nd_prefix_list_head = prfl->next;
931 kfree_type(struct nd_prefix_list, prfl);
932 }
933
934 return;
935
936 bad:
937 m_drop(m, DROPTAP_FLAG_DIR_IN | DROPTAP_FLAG_L2_MISSING, drop_reason, NULL, 0);
938 m = NULL;
939
940 icmp6stat.icp6s_badra++;
941 goto freeit;
942 }
943
944 /*
945 * default router list processing sub routines
946 */
947
948 /* tell the change to user processes watching the routing socket. */
949 static void
nd6_rtmsg(u_char cmd,struct rtentry * rt)950 nd6_rtmsg(u_char cmd, struct rtentry *rt)
951 {
952 struct rt_addrinfo info;
953 struct ifnet *ifp = rt->rt_ifp;
954
955 RT_LOCK_ASSERT_HELD(rt);
956
957 bzero((caddr_t)&info, sizeof(info));
958 /* It's not necessary to lock ifp for if_lladdr */
959 info.rti_info[RTAX_DST] = rt_key(rt);
960 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
961 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
962 /*
963 * ifa_addr pointers for both should always be valid
964 * in this context; no need to hold locks.
965 */
966 info.rti_info[RTAX_IFP] = ifp->if_lladdr->ifa_addr;
967 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
968
969 rt_missmsg(cmd, &info, rt->rt_flags, 0);
970 }
971
972 static void
defrouter_addreq(struct nd_defrouter * new,struct nd_route_info * rti,boolean_t scoped)973 defrouter_addreq(struct nd_defrouter *new, struct nd_route_info *rti, boolean_t scoped)
974 {
975 struct sockaddr_in6 key, mask, gate;
976 struct rtentry *newrt __single = NULL;
977 unsigned int ifscope;
978 int err;
979 struct nd_ifinfo *ndi = ND_IFINFO(new->ifp);
980 int rtflags = RTF_GATEWAY;
981 if (rti) {
982 nd6log(info, "%s: defrouter_addreq prefix %s scoped=%d", __func__, ip6_sprintf(&rti->nd_rti_prefix), scoped);
983 } else {
984 nd6log(info, "%s: defrouter_addreq scoped=%d", __func__, scoped);
985 }
986
987 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
988 NDDR_LOCK_ASSERT_NOTHELD(new);
989 /*
990 * We're free to lock and unlock NDDR because our callers
991 * are holding an extra reference for us.
992 */
993
994 NDDR_LOCK(new);
995 if (new->stateflags & NDDRF_INSTALLED) {
996 nd6log(info, "%s: defrouter_addreq already installed", __func__);
997 goto out;
998 }
999 if (new->ifp->if_ipv6_router_mode == IPV6_ROUTER_MODE_EXCLUSIVE) {
1000 nd6log2(info, "%s: ignoring router %s, scoped=%d, "
1001 "static=%d on advertising interface\n", if_name(new->ifp),
1002 ip6_sprintf(&new->rtaddr), scoped,
1003 (new->stateflags & NDDRF_STATIC) ? 1 : 0);
1004 goto out;
1005 }
1006
1007 nd6log2(info, "%s: adding default router %s, scoped=%d, "
1008 "static=%d\n", if_name(new->ifp), ip6_sprintf(&new->rtaddr),
1009 scoped, (new->stateflags & NDDRF_STATIC) ? 1 : 0);
1010
1011 Bzero(&key, sizeof(key));
1012 Bzero(&mask, sizeof(mask));
1013 Bzero(&gate, sizeof(gate));
1014
1015 key.sin6_len = mask.sin6_len = gate.sin6_len
1016 = sizeof(struct sockaddr_in6);
1017 key.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
1018
1019 if (rti != NULL) {
1020 key.sin6_addr = rti->nd_rti_prefix;
1021 in6_len2mask(&mask.sin6_addr, rti->nd_rti_prefixlen);
1022 if (rti->nd_rti_prefixlen == ND_OPT_RTI_PFXLEN_MAX) {
1023 rtflags |= RTF_HOST;
1024 } else {
1025 rtflags |= RTF_PRCLONING;
1026 }
1027
1028 if (IN6_IS_SCOPE_EMBED(&key.sin6_addr) ||
1029 IN6_IS_ADDR_LOOPBACK(&key.sin6_addr)) {
1030 nd6log2(info, "%s: ignoring router %s, rti prefix %s, scoped=%d, "
1031 "static=%d on advertising interface\n", if_name(new->ifp),
1032 ip6_sprintf(&new->rtaddr), ip6_sprintf(&rti->nd_rti_prefix), scoped,
1033 (new->stateflags & NDDRF_STATIC) ? 1 : 0);
1034 goto out;
1035 }
1036 }
1037
1038 if (new->stateflags & NDDRF_MAPPED) {
1039 gate.sin6_addr = new->rtaddr_mapped;
1040 } else {
1041 gate.sin6_addr = new->rtaddr;
1042 }
1043 if (!in6_embedded_scope && IN6_IS_SCOPE_EMBED(&gate.sin6_addr)) {
1044 gate.sin6_scope_id = new->ifp->if_index;
1045 }
1046
1047 ifscope = scoped ? new->ifp->if_index : IFSCOPE_NONE;
1048 NDDR_UNLOCK(new);
1049
1050 /*
1051 * Cellular networks may have buggy deployments
1052 * with gateway IPv6 link local address with same
1053 * interface identifier as the one that has been
1054 * assigned for the cellular context.
1055 * If gateway is same as locally configured link local
1056 * interface on cellular interface, generated a different one
1057 * and store it in the nd_defrouter entry and use it to work
1058 * on routing table
1059 */
1060 if (new->ifp->if_type == IFT_CELLULAR &&
1061 !(new->stateflags & NDDRF_STATIC) &&
1062 !(new->stateflags & NDDRF_MAPPED) &&
1063 IN6_IS_ADDR_LINKLOCAL(&gate.sin6_addr) &&
1064 ndi && !(ndi->flags & ND6_IFF_PERFORMNUD)) {
1065 struct in6_ifaddr *tmp_ia6 = in6ifa_ifpforlinklocal(new->ifp, 0);
1066
1067 if (tmp_ia6 != NULL &&
1068 !(tmp_ia6->ia6_flags & IN6_IFF_NOTMANUAL) &&
1069 IN6_ARE_ADDR_EQUAL(&tmp_ia6->ia_addr.sin6_addr,
1070 &gate.sin6_addr)) {
1071 gate.sin6_addr.s6_addr8[15] += 1;
1072 new->rtaddr_mapped = gate.sin6_addr;
1073 new->stateflags |= NDDRF_MAPPED;
1074
1075 nd6log(info, "%s: %s Default router %s mapped "
1076 "to ", __func__, if_name(new->ifp), ip6_sprintf(&new->rtaddr));
1077 nd6log(info, "%s\n", ip6_sprintf(&new->rtaddr_mapped));
1078 nd6log(info, "%s\n", ip6_sprintf(&new->rtaddr_mapped));
1079 }
1080 }
1081
1082 err = rtrequest_scoped(RTM_ADD, SA(&key), SA(&gate), SA(&mask),
1083 rtflags, &newrt, ifscope);
1084
1085 if (newrt) {
1086 RT_LOCK(newrt);
1087 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
1088 RT_REMREF_LOCKED(newrt);
1089 RT_UNLOCK(newrt);
1090 NDDR_LOCK(new);
1091 new->stateflags |= NDDRF_INSTALLED;
1092 if (ifscope != IFSCOPE_NONE) {
1093 new->stateflags |= NDDRF_IFSCOPE;
1094 }
1095 } else {
1096 nd6log0(error, "%s: failed to add default router "
1097 "%s on %s scoped %d (errno = %d)\n", __func__,
1098 ip6_sprintf(&gate.sin6_addr), if_name(new->ifp),
1099 (ifscope != IFSCOPE_NONE), err);
1100 NDDR_LOCK(new);
1101 }
1102 new->err = err;
1103
1104 out:
1105 NDDR_UNLOCK(new);
1106 }
1107
1108 void
defrouter_set_reachability(struct in6_addr * addr,struct ifnet * ifp,boolean_t is_reachable)1109 defrouter_set_reachability(
1110 struct in6_addr *addr,
1111 struct ifnet *ifp,
1112 boolean_t is_reachable)
1113 {
1114 struct nd_defrouter *dr = NULL;
1115
1116 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
1117
1118 lck_mtx_lock(nd6_mutex);
1119 dr = defrouter_lookup(NULL, addr, ifp);
1120 if (dr != NULL) {
1121 dr->is_reachable = is_reachable;
1122 NDDR_REMREF(dr);
1123 }
1124 lck_mtx_unlock(nd6_mutex);
1125 }
1126
1127 struct nd_defrouter *
defrouter_lookup(struct nd_drhead * nd_router_listp,struct in6_addr * addr,struct ifnet * ifp)1128 defrouter_lookup(
1129 struct nd_drhead *nd_router_listp,
1130 struct in6_addr *addr,
1131 struct ifnet *ifp)
1132 {
1133 struct nd_defrouter *dr;
1134
1135 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1136
1137 if (nd_router_listp == NULL) {
1138 nd_router_listp = &nd_defrouter_list;
1139 }
1140
1141 for (dr = TAILQ_FIRST(nd_router_listp); dr;
1142 dr = TAILQ_NEXT(dr, dr_entry)) {
1143 NDDR_LOCK(dr);
1144 if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr)) {
1145 NDDR_ADDREF(dr);
1146 NDDR_UNLOCK(dr);
1147 return dr;
1148 }
1149 NDDR_UNLOCK(dr);
1150 }
1151
1152 return NULL; /* search failed */
1153 }
1154
1155 /* Remove the default route for a given router */
1156 void
defrouter_delreq(struct nd_defrouter * dr,struct nd_route_info * rti)1157 defrouter_delreq(struct nd_defrouter *dr, struct nd_route_info *rti)
1158 {
1159 struct sockaddr_in6 key, mask, gate;
1160 struct rtentry *oldrt __single = NULL;
1161 unsigned int ifscope;
1162 int err;
1163
1164 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
1165 NDDR_LOCK_ASSERT_NOTHELD(dr);
1166 /*
1167 * We're free to lock and unlock NDDR because our callers
1168 * are holding an extra reference for us.
1169 */
1170 NDDR_LOCK(dr);
1171 /* ifp would be NULL for the "drany" case */
1172 if (dr->ifp != NULL && !(dr->stateflags & NDDRF_INSTALLED)) {
1173 goto out;
1174 }
1175
1176 nd6log2(info, "%s: removing default router %s, scoped=%d, "
1177 "static=%d\n", dr->ifp != NULL ? if_name(dr->ifp) : "ANY",
1178 ip6_sprintf(&dr->rtaddr), (dr->stateflags & NDDRF_IFSCOPE) ? 1 : 0,
1179 (dr->stateflags & NDDRF_STATIC) ? 1 : 0);
1180
1181 Bzero(&key, sizeof(key));
1182 Bzero(&mask, sizeof(mask));
1183 Bzero(&gate, sizeof(gate));
1184
1185 key.sin6_len = mask.sin6_len = gate.sin6_len
1186 = sizeof(struct sockaddr_in6);
1187 key.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
1188
1189
1190 if (rti != NULL) {
1191 key.sin6_addr = rti->nd_rti_prefix;
1192 in6_len2mask(&mask.sin6_addr, rti->nd_rti_prefixlen);
1193 }
1194 /*
1195 * The router entry may be mapped to a different address.
1196 * If that is the case, use the mapped address as gateway
1197 * to do operation on the routing table.
1198 * To get more context, read the related comment in
1199 * defrouter_addreq
1200 */
1201 if (dr->stateflags & NDDRF_MAPPED) {
1202 gate.sin6_addr = dr->rtaddr_mapped;
1203 } else {
1204 gate.sin6_addr = dr->rtaddr;
1205 }
1206
1207 if (dr->ifp != NULL) {
1208 ifscope = (dr->stateflags & NDDRF_IFSCOPE) ?
1209 dr->ifp->if_index : IFSCOPE_NONE;
1210 } else {
1211 ifscope = IFSCOPE_NONE;
1212 }
1213 NDDR_UNLOCK(dr);
1214
1215 err = rtrequest_scoped(RTM_DELETE, SA(&key), SA(&gate), SA(&mask),
1216 RTF_GATEWAY, &oldrt, ifscope);
1217
1218 if (oldrt) {
1219 RT_LOCK(oldrt);
1220 nd6_rtmsg(RTM_DELETE, oldrt);
1221 RT_UNLOCK(oldrt);
1222 rtfree(oldrt);
1223 } else if (err != ESRCH) {
1224 nd6log0(error, "%s: failed to delete default router "
1225 "%s on %s scoped %d (errno = %d)\n", __func__,
1226 ip6_sprintf(&gate.sin6_addr), dr->ifp != NULL ?
1227 if_name(dr->ifp) : "ANY", (ifscope != IFSCOPE_NONE), err);
1228 }
1229 NDDR_LOCK(dr);
1230 /* ESRCH means it's no longer in the routing table; ignore it */
1231 if (oldrt != NULL || err == ESRCH) {
1232 dr->stateflags &= ~NDDRF_INSTALLED;
1233 if (ifscope != IFSCOPE_NONE) {
1234 dr->stateflags &= ~NDDRF_IFSCOPE;
1235 }
1236 }
1237 dr->err = 0;
1238 out:
1239 NDDR_UNLOCK(dr);
1240 }
1241
1242
1243 /*
1244 * remove all default routes from default router list
1245 */
1246 void
defrouter_reset(void)1247 defrouter_reset(void)
1248 {
1249 struct nd_defrouter *dr, drany;
1250
1251 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1252
1253 dr = TAILQ_FIRST(&nd_defrouter_list);
1254 while (dr) {
1255 NDDR_LOCK(dr);
1256 if (dr->stateflags & NDDRF_INSTALLED) {
1257 NDDR_ADDREF(dr);
1258 NDDR_UNLOCK(dr);
1259 lck_mtx_unlock(nd6_mutex);
1260 defrouter_delreq(dr, NULL);
1261 lck_mtx_lock(nd6_mutex);
1262 NDDR_REMREF(dr);
1263 dr = TAILQ_FIRST(&nd_defrouter_list);
1264 } else {
1265 NDDR_UNLOCK(dr);
1266 dr = TAILQ_NEXT(dr, dr_entry);
1267 }
1268 }
1269
1270 /* Nuke primary (non-scoped) default router */
1271 bzero(&drany, sizeof(drany));
1272 lck_mtx_init(&drany.nddr_lock, &ifa_mtx_grp, &ifa_mtx_attr);
1273 lck_mtx_unlock(nd6_mutex);
1274 defrouter_delreq(&drany, NULL);
1275 lck_mtx_destroy(&drany.nddr_lock, &ifa_mtx_grp);
1276 lck_mtx_lock(nd6_mutex);
1277 }
1278
1279 int
defrtrlist_ioctl(u_long cmd,caddr_t __sized_by (IOCPARM_LEN (cmd))data)1280 defrtrlist_ioctl(u_long cmd, caddr_t __sized_by(IOCPARM_LEN(cmd)) data)
1281 {
1282 struct nd_defrouter dr0;
1283 unsigned int ifindex;
1284 struct ifnet *dr_ifp;
1285 int error = 0, add = 0;
1286
1287 /* XXX Handle mapped default router entries */
1288 switch (cmd) {
1289 case SIOCDRADD_IN6_32: /* struct in6_defrouter_32 */
1290 case SIOCDRADD_IN6_64: /* struct in6_defrouter_64 */
1291 ++add;
1292 OS_FALLTHROUGH;
1293 case SIOCDRDEL_IN6_32: /* struct in6_defrouter_32 */
1294 case SIOCDRDEL_IN6_64: /* struct in6_defrouter_64 */
1295 bzero(&dr0, sizeof(dr0));
1296 if (cmd == SIOCDRADD_IN6_64 || cmd == SIOCDRDEL_IN6_64) {
1297 struct in6_defrouter_64 *r_64 =
1298 (struct in6_defrouter_64 *)(void *)data;
1299 u_int16_t i;
1300
1301 bcopy(&r_64->rtaddr.sin6_addr, &dr0.rtaddr,
1302 sizeof(dr0.rtaddr));
1303 dr0.flags = r_64->flags;
1304 bcopy(&r_64->if_index, &i, sizeof(i));
1305 ifindex = i;
1306 } else {
1307 struct in6_defrouter_32 *__single r_32 =
1308 (struct in6_defrouter_32 *)(void *)data;
1309 u_int16_t i;
1310
1311 bcopy(&r_32->rtaddr.sin6_addr, &dr0.rtaddr,
1312 sizeof(dr0.rtaddr));
1313 dr0.flags = r_32->flags;
1314 bcopy(&r_32->if_index, &i, sizeof(i));
1315 ifindex = i;
1316 }
1317 ifnet_head_lock_shared();
1318 /* Don't need to check is ifindex is < 0 since it's unsigned */
1319 if (!IF_INDEX_IN_RANGE(ifindex) ||
1320 (dr_ifp = ifindex2ifnet[ifindex]) == NULL) {
1321 ifnet_head_done();
1322 error = EINVAL;
1323 break;
1324 }
1325 dr0.ifp = dr_ifp;
1326 ifnet_head_done();
1327
1328 if (ND_IFINFO(dr_ifp) == NULL ||
1329 !ND_IFINFO(dr_ifp)->initialized) {
1330 error = ENXIO;
1331 break;
1332 }
1333
1334 if (IN6_IS_SCOPE_EMBED(&dr0.rtaddr) && in6_embedded_scope) {
1335 uint16_t *scope = &dr0.rtaddr.s6_addr16[1];
1336
1337 if (*scope == 0) {
1338 *scope = htons(dr_ifp->if_index);
1339 } else if (*scope != htons(dr_ifp->if_index)) {
1340 error = EINVAL;
1341 break;
1342 }
1343 }
1344 if (add) {
1345 error = defrtrlist_add_static(&dr0);
1346 }
1347 if (!add || error != 0) {
1348 int err = defrtrlist_del_static(&dr0);
1349 if (!add) {
1350 error = err;
1351 }
1352 }
1353 break;
1354
1355 default:
1356 error = EOPNOTSUPP; /* check for safety */
1357 break;
1358 }
1359
1360 return error;
1361 }
1362
1363 /*
1364 * XXX Please make sure to remove dr from the
1365 * global default router tailq list before this
1366 * function call.
1367 * Also ensure that you release the list reference
1368 * only after calling this routine.
1369 */
1370 void
defrtrlist_del(struct nd_defrouter * dr,struct nd_drhead * nd_router_listp)1371 defrtrlist_del(struct nd_defrouter *dr, struct nd_drhead *nd_router_listp)
1372 {
1373 #if (DEVELOPMENT || DEBUG)
1374 struct nd_defrouter *dr_itr = NULL;
1375 #endif
1376 struct nd_prefix *pr;
1377 struct ifnet *ifp = dr->ifp;
1378 struct nd_ifinfo *ndi = NULL;
1379 boolean_t resetmtu = FALSE;
1380 struct nd_route_info *rti = NULL;
1381
1382 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1383
1384 if (nd_router_listp == NULL) {
1385 nd_router_listp = &nd_defrouter_list;
1386 }
1387
1388 if (nd_router_listp != &nd_defrouter_list) {
1389 rti = (struct nd_route_info *)nd_router_listp;
1390 }
1391
1392 #if (DEVELOPMENT || DEBUG)
1393 /*
1394 * Verify that the router is not in the global default
1395 * router list.
1396 * Can't use defrouter_lookup here because that just works
1397 * with address and ifp pointer.
1398 * We have to compare the memory here.
1399 * Also we can't use ASSERT here as that is not defined
1400 * for development builds.
1401 */
1402 TAILQ_FOREACH(dr_itr, nd_router_listp, dr_entry)
1403 VERIFY(dr != dr_itr);
1404 #endif
1405 ++nd6_defrouter_genid;
1406 /*
1407 * Flush all the routing table entries that use the router
1408 * as a next hop.
1409 *
1410 * XXX Note that for a router advertising itself as default router
1411 * and also advertising route information option, the following
1412 * code will have the default router entry and router entry of
1413 * RTI step over each other.
1414 * The following therefore may not be efficient but won't be
1415 * causing blocking issues.
1416 */
1417 NDDR_ADDREF(dr);
1418 lck_mtx_unlock(nd6_mutex);
1419 if (dr->stateflags & NDDRF_MAPPED) {
1420 rt6_flush(&dr->rtaddr_mapped, ifp);
1421 } else {
1422 rt6_flush(&dr->rtaddr, ifp);
1423 }
1424 lck_mtx_lock(nd6_mutex);
1425 NDDR_REMREF(dr);
1426 nd6log2(info, "%s: freeing route to %s with gateway %s\n", if_name(dr->ifp),
1427 (rti == NULL)? "::" : ip6_sprintf(&rti->nd_rti_prefix),
1428 ip6_sprintf(&dr->rtaddr));
1429 /*
1430 * Delete it from the routing table.
1431 */
1432 NDDR_ADDREF(dr);
1433 lck_mtx_unlock(nd6_mutex);
1434 defrouter_delreq(dr, rti);
1435 lck_mtx_lock(nd6_mutex);
1436 NDDR_REMREF(dr);
1437
1438 /*
1439 * The following should mostly be limited to when we are working
1440 * with a default router entry and not a router entry from
1441 * rti router list.
1442 */
1443 if (rti == NULL) {
1444 /*
1445 * Also delete all the pointers to the router in each prefix lists.
1446 */
1447 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1448 struct nd_pfxrouter *__single pfxrtr;
1449
1450 NDPR_LOCK(pr);
1451 if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL) {
1452 pfxrtr_del(pfxrtr, pr);
1453 }
1454 NDPR_UNLOCK(pr);
1455 }
1456 pfxlist_onlink_check(false);
1457 }
1458 ndi = ND_IFINFO(ifp);
1459 VERIFY(NULL != ndi && TRUE == ndi->initialized);
1460 lck_mtx_lock(&ndi->lock);
1461 VERIFY(ndi->ndefrouters >= 0);
1462 if (ndi->ndefrouters > 0 && --ndi->ndefrouters == 0) {
1463 nd6_ifreset(ifp);
1464 resetmtu = TRUE;
1465 }
1466 lck_mtx_unlock(&ndi->lock);
1467 /*
1468 * If the router is the primary one, choose a new one.
1469 * We always try to pick another eligible router
1470 * on this interface as we do scoped routing
1471 */
1472 defrouter_select(ifp, nd_router_listp);
1473
1474 if (resetmtu) {
1475 nd6_setmtu(ifp);
1476 }
1477 }
1478
1479 int
defrtrlist_add_static(struct nd_defrouter * new)1480 defrtrlist_add_static(struct nd_defrouter *new)
1481 {
1482 struct nd_defrouter *dr;
1483 int err = 0;
1484
1485 new->rtlifetime = -1;
1486 new->stateflags |= NDDRF_STATIC;
1487
1488 /* we only want the preference level */
1489 new->flags &= ND_RA_FLAG_RTPREF_MASK;
1490
1491 lck_mtx_lock(nd6_mutex);
1492 dr = defrouter_lookup(NULL, &new->rtaddr, new->ifp);
1493 if (dr != NULL && !(dr->stateflags & NDDRF_STATIC)) {
1494 err = EINVAL;
1495 } else {
1496 if (dr != NULL) {
1497 NDDR_REMREF(dr);
1498 }
1499 dr = defrtrlist_update(new, NULL);
1500 if (dr != NULL) {
1501 err = dr->err;
1502 } else {
1503 err = ENOMEM;
1504 }
1505 }
1506 if (dr != NULL) {
1507 NDDR_REMREF(dr);
1508 }
1509 lck_mtx_unlock(nd6_mutex);
1510
1511 return err;
1512 }
1513
1514 int
defrtrlist_del_static(struct nd_defrouter * new)1515 defrtrlist_del_static(struct nd_defrouter *new)
1516 {
1517 struct nd_defrouter *dr;
1518
1519 lck_mtx_lock(nd6_mutex);
1520 dr = defrouter_lookup(NULL, &new->rtaddr, new->ifp);
1521 if (dr == NULL || !(dr->stateflags & NDDRF_STATIC)) {
1522 if (dr != NULL) {
1523 NDDR_REMREF(dr);
1524 }
1525 dr = NULL;
1526 } else {
1527 TAILQ_REMOVE(&nd_defrouter_list, dr, dr_entry);
1528 defrtrlist_del(dr, NULL);
1529 NDDR_REMREF(dr); /* remove list reference */
1530 NDDR_REMREF(dr);
1531 }
1532 lck_mtx_unlock(nd6_mutex);
1533
1534 return dr != NULL ? 0 : EINVAL;
1535 }
1536
1537 /*
1538 * for default router selection
1539 * regards router-preference field as a 2-bit signed integer
1540 */
1541 static int
rtpref(struct nd_defrouter * dr)1542 rtpref(struct nd_defrouter *dr)
1543 {
1544 switch (dr->flags & ND_RA_FLAG_RTPREF_MASK) {
1545 case ND_RA_FLAG_RTPREF_HIGH:
1546 return RTPREF_HIGH;
1547 case ND_RA_FLAG_RTPREF_MEDIUM:
1548 case ND_RA_FLAG_RTPREF_RSV:
1549 return RTPREF_MEDIUM;
1550 case ND_RA_FLAG_RTPREF_LOW:
1551 return RTPREF_LOW;
1552 default:
1553 /*
1554 * This case should never happen. If it did, it would mean a
1555 * serious bug of kernel internal. We thus always bark here.
1556 * Or, can we even panic?
1557 */
1558 log(LOG_ERR, "rtpref: impossible RA flag %x\n", dr->flags);
1559 return RTPREF_INVALID;
1560 }
1561 /* NOTREACHED */
1562 }
1563
1564 /*
1565 * Default Router Selection according to Section 6.3.6 of RFC 2461 and RFC 4191:
1566 *
1567 * 1) Routers that are reachable or probably reachable should be preferred.
1568 * If we have more than one (probably) reachable router, prefer ones
1569 * with the highest router preference.
1570 * 2) When no routers on the list are known to be reachable or
1571 * probably reachable, routers SHOULD be selected in a round-robin
1572 * fashion, regardless of router preference values.
1573 * 3) If the Default Router List is empty, assume that all
1574 * destinations are on-link.
1575 *
1576 * When Scoped Routing is enabled, the selection logic is amended as follows:
1577 *
1578 * a) When a default interface is specified, the primary/non-scoped default
1579 * router will be set to the reachable router on that link (if any) with
1580 * the highest router preference.
1581 * b) When there are more than one routers on the same link, the one with
1582 * the highest router preference will be installed, either as scoped or
1583 * non-scoped route entry. If they all share the same preference value,
1584 * the one installed will be the static or the first encountered reachable
1585 * router, i.e. static one wins over dynamic.
1586 * c) When no routers on the list are known to be reachable, or probably
1587 * reachable, no round-robin selection will take place when the default
1588 * interface is set.
1589 *
1590 * We assume nd_defrouter is sorted by router preference value.
1591 * Since the code below covers both with and without router preference cases,
1592 * we do not need to classify the cases by ifdef.
1593 */
1594 void
defrouter_select(struct ifnet * ifp,struct nd_drhead * nd_router_listp)1595 defrouter_select(struct ifnet *ifp, struct nd_drhead *nd_router_listp)
1596 {
1597 struct nd_defrouter *dr = NULL;
1598 struct nd_defrouter *selected_dr = NULL;
1599 struct nd_defrouter *installed_dr = NULL;
1600 struct llinfo_nd6 *__single ln = NULL;
1601 struct rtentry *rt = NULL;
1602 struct nd_ifinfo *ndi = NULL;
1603 unsigned int genid = 0;
1604 boolean_t is_installed_reachable = FALSE;
1605 struct nd_route_info *rti = NULL;
1606 boolean_t scoped = TRUE;
1607 boolean_t is_rti_rtrlist = FALSE;
1608
1609 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1610
1611 if (nd_router_listp == NULL) {
1612 nd_router_listp = &nd_defrouter_list;
1613 }
1614
1615 if (nd_router_listp != &nd_defrouter_list) {
1616 rti = (struct nd_route_info *)nd_router_listp;
1617 /* XXX For now we treat RTI routes as un-scoped */
1618 scoped = FALSE;
1619 is_rti_rtrlist = TRUE;
1620 }
1621
1622
1623 if (ifp == NULL) {
1624 ifp = nd6_defifp;
1625 if (ifp == NULL) {
1626 nd6log2(info,
1627 "%s:%d: Return early. NULL interface",
1628 __func__, __LINE__);
1629 return;
1630 }
1631 nd6log2(info,
1632 "%s:%d: NULL interface passed. Setting to default interface %s.\n",
1633 __func__, __LINE__, if_name(ifp));
1634 }
1635
1636 /*
1637 * When we are working with RTI router list, the nd6_defifp may be
1638 * NULL. That is the scenario when the network may not have WAN
1639 * v6 connectivity and the only RAs we may be getting are with lifetime
1640 * 0.
1641 */
1642 if (ifp == lo_ifp && !is_rti_rtrlist) {
1643 nd6log2(info,
1644 "%s:%d: Return early. "
1645 "Default router select called for loopback.\n",
1646 __func__, __LINE__);
1647 return;
1648 }
1649
1650 if (ifp->if_ipv6_router_mode == IPV6_ROUTER_MODE_EXCLUSIVE) {
1651 nd6log2(info,
1652 "%s:%d: Return early. "
1653 "Default router select called for interface"
1654 " %s in IPV6_ROUTER_MODE_EXCLUSIVE\n",
1655 __func__, __LINE__, if_name(ifp));
1656 return;
1657 }
1658
1659 /*
1660 * Let's handle easy case (3) first:
1661 * If default router list is empty, there's nothing to be done.
1662 */
1663 if (!TAILQ_FIRST(nd_router_listp)) {
1664 nd6log2(info,
1665 "%s:%d: Return early. "
1666 "Default router is empty.\n", __func__, __LINE__);
1667 return;
1668 }
1669
1670 /*
1671 * Take an early exit if number of routers in nd_ifinfo is
1672 * 0 for the interface.
1673 */
1674 ndi = ND_IFINFO(ifp);
1675 if (!ndi || !ndi->initialized) {
1676 nd6log2(info,
1677 "%s:%d: Return early. "
1678 "Interface %s's nd_ifinfo not initialized.\n",
1679 __func__, __LINE__, if_name(ifp));
1680 return;
1681 }
1682
1683 /*
1684 * RTI router list routes are installed as unscoped.
1685 * Since there can be only one unscoped route, we need to
1686 * go through the entire list and consider all interfaces.
1687 * Further, for now, RTI option is only processed on Ethernet
1688 * type interfaces only.
1689 */
1690 if (ndi->ndefrouters == 0 && !is_rti_rtrlist) {
1691 nd6log2(info,
1692 "%s:%d: Return early. "
1693 "%s does not have any default routers.\n",
1694 __func__, __LINE__, if_name(ifp));
1695 return;
1696 }
1697
1698 /*
1699 * Due to the number of times we drop nd6_mutex, we need to
1700 * serialize this function.
1701 */
1702 while (nd_defrouter_busy) {
1703 nd_defrouter_waiters++;
1704 msleep(nd_defrouter_waitchan, nd6_mutex, (PZERO - 1),
1705 __func__, NULL);
1706 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1707 }
1708 nd_defrouter_busy = TRUE;
1709
1710 /*
1711 * Search for a (probably) reachable router from the list.
1712 * We just pick up the first reachable one (if any), assuming that
1713 * the ordering rule of the list described in defrtrlist_update().
1714 *
1715 * For all intents and purposes of Scoped Routing:
1716 * selected_dr = candidate for primary router
1717 * installed_dr = currently installed primary router
1718 */
1719 genid = nd6_defrouter_genid;
1720 dr = TAILQ_FIRST(nd_router_listp);
1721
1722 while (dr != NULL) {
1723 struct in6_addr rtaddr;
1724 ifnet_ref_t drifp = NULL;
1725 struct nd_defrouter *__single drrele = NULL;
1726 boolean_t nd6_mutex_unlocked = FALSE;
1727
1728 NDDR_LOCK(dr);
1729 drifp = dr->ifp;
1730 if (drifp != ifp && !is_rti_rtrlist) {
1731 NDDR_UNLOCK(dr);
1732 dr = TAILQ_NEXT(dr, dr_entry);
1733 continue;
1734 }
1735
1736 if (dr->stateflags & NDDRF_INELIGIBLE) {
1737 NDDR_UNLOCK(dr);
1738 dr = TAILQ_NEXT(dr, dr_entry);
1739 nd6log(info, "Ignoring dummy entry for default router.");
1740 continue;
1741 }
1742
1743 if (dr->ifp->if_type != IFT_CELLULAR &&
1744 dr->stateflags & NDDRF_LOCAL) {
1745 NDDR_UNLOCK(dr);
1746 nd6log(info, "%s: Ignoring router %s that has locally hosted address.\n",
1747 if_name(dr->ifp),
1748 ip6_sprintf(&dr->rtaddr));
1749 dr = TAILQ_NEXT(dr, dr_entry);
1750 continue;
1751 }
1752
1753 /*
1754 * Optimize for the common case.
1755 * When the interface has only one default router
1756 * there's no point checking for reachability as
1757 * there's nothing else to choose from.
1758 */
1759 if (ndi->ndefrouters == 1 && !is_rti_rtrlist) {
1760 nd6log2(info,
1761 "%s:%d: Fast forward default router selection "
1762 "as interface %s has learned only one default "
1763 "router and there's nothing else to choose from.\n",
1764 __func__, __LINE__, if_name(ifp));
1765 VERIFY(selected_dr == NULL && installed_dr == NULL);
1766 selected_dr = dr;
1767 if (dr->stateflags & NDDRF_INSTALLED) {
1768 installed_dr = dr;
1769 }
1770 NDDR_ADDREF(selected_dr);
1771 NDDR_UNLOCK(dr);
1772 goto install_route;
1773 }
1774
1775 if (dr->stateflags & NDDRF_MAPPED) {
1776 rtaddr = dr->rtaddr_mapped;
1777 } else {
1778 rtaddr = dr->rtaddr;
1779 }
1780
1781 NDDR_ADDREF(dr); /* for this for loop */
1782 NDDR_UNLOCK(dr);
1783
1784 /* Callee returns a locked route upon success */
1785 if (selected_dr == NULL) {
1786 nd6_mutex_unlocked = TRUE;
1787 lck_mtx_unlock(nd6_mutex);
1788 if ((rt = nd6_lookup(&rtaddr, 0, drifp, 0)) != NULL &&
1789 (ln = rt->rt_llinfo) != NULL &&
1790 ND6_IS_LLINFO_PROBREACH(ln)) {
1791 RT_LOCK_ASSERT_HELD(rt);
1792 selected_dr = dr;
1793 NDDR_ADDREF(selected_dr);
1794 }
1795 }
1796
1797 if (rt) {
1798 RT_REMREF_LOCKED(rt);
1799 RT_UNLOCK(rt);
1800 rt = NULL;
1801 }
1802
1803 if (nd6_mutex_unlocked) {
1804 lck_mtx_lock(nd6_mutex);
1805 }
1806
1807 /*
1808 * Handle case (b)
1809 * When there are more than one routers on the same link, the one with
1810 * the highest router preference will be installed.
1811 * Since the list is in decreasing order of preference:
1812 * 1) If selected_dr is not NULL, only use dr if it is static and has
1813 * equal preference and selected_dr is not static.
1814 * 2) Else if selected_dr is NULL, and dr is static make selected_dr = dr
1815 */
1816 NDDR_LOCK(dr);
1817 if (((selected_dr && (rtpref(dr) >= rtpref(selected_dr)) &&
1818 !(selected_dr->stateflags & NDDRF_STATIC)) ||
1819 (selected_dr == NULL)) &&
1820 (dr->stateflags & NDDRF_STATIC)) {
1821 if (selected_dr) {
1822 /* Release it later on */
1823 VERIFY(drrele == NULL);
1824 drrele = selected_dr;
1825 }
1826 selected_dr = dr;
1827 NDDR_ADDREF(selected_dr);
1828 }
1829
1830 /* Record the currently installed router */
1831 if (dr->stateflags & NDDRF_INSTALLED) {
1832 if (installed_dr == NULL) {
1833 installed_dr = dr;
1834 NDDR_ADDREF(installed_dr);
1835 if (dr->stateflags & NDDRF_MAPPED) {
1836 rtaddr = installed_dr->rtaddr_mapped;
1837 } else {
1838 rtaddr = installed_dr->rtaddr;
1839 }
1840 NDDR_UNLOCK(dr);
1841 lck_mtx_unlock(nd6_mutex);
1842 /* Callee returns a locked route upon success */
1843 if ((rt = nd6_lookup(&rtaddr, 0, installed_dr->ifp, 0)) != NULL) {
1844 RT_LOCK_ASSERT_HELD(rt);
1845 if ((ln = rt->rt_llinfo) != NULL &&
1846 ND6_IS_LLINFO_PROBREACH(ln)) {
1847 is_installed_reachable = TRUE;
1848 }
1849
1850 RT_REMREF_LOCKED(rt);
1851 RT_UNLOCK(rt);
1852 rt = NULL;
1853 }
1854 lck_mtx_lock(nd6_mutex);
1855 } else {
1856 /* this should not happen; warn for diagnosis */
1857 nd6log0(error, "%s: more than one "
1858 "default router is installed for interface: %s\n",
1859 __func__, if_name(installed_dr->ifp));
1860 NDDR_UNLOCK(dr);
1861 }
1862 } else {
1863 NDDR_UNLOCK(dr);
1864 }
1865
1866 NDDR_REMREF(dr); /* for this for loop */
1867 if (drrele != NULL) {
1868 NDDR_REMREF(drrele);
1869 }
1870
1871 /*
1872 * Check if the list changed when we gave up
1873 * the nd6_mutex lock
1874 */
1875 if (genid != nd6_defrouter_genid) {
1876 if (selected_dr) {
1877 NDDR_REMREF(selected_dr);
1878 selected_dr = NULL;
1879 }
1880
1881 if (installed_dr) {
1882 NDDR_REMREF(installed_dr);
1883 installed_dr = NULL;
1884 }
1885
1886 if (ndi->ndefrouters == 0 && !is_rti_rtrlist) {
1887 nd6log2(info,
1888 "%s:%d: Interface %s no longer "
1889 "has any default routers. Abort.\n",
1890 __func__, __LINE__, if_name(ifp));
1891 goto out;
1892 }
1893 nd6log2(info,
1894 "%s:%d: Iterate default router list again "
1895 "for interface %s, as the list seems to have "
1896 "changed during release-reaquire of global "
1897 "nd6_mutex lock.\n",
1898 __func__, __LINE__, if_name(ifp));
1899
1900 is_installed_reachable = FALSE;
1901 genid = nd6_defrouter_genid;
1902 dr = TAILQ_FIRST(nd_router_listp);
1903 } else {
1904 dr = TAILQ_NEXT(dr, dr_entry);
1905 }
1906 }
1907
1908 /*
1909 * If none of the default routers was found to be reachable,
1910 * round-robin the list regardless of preference.
1911 * Please note selected_dr equal to NULL implies that even
1912 * installed default router is not reachable
1913 */
1914 if (selected_dr == NULL) {
1915 if (installed_dr) {
1916 for (dr = TAILQ_NEXT(installed_dr, dr_entry); dr;
1917 dr = TAILQ_NEXT(dr, dr_entry)) {
1918 if (installed_dr->ifp != dr->ifp && !is_rti_rtrlist) {
1919 continue;
1920 }
1921 if (dr->stateflags & NDDRF_INELIGIBLE) {
1922 continue;
1923 }
1924 selected_dr = dr;
1925 break;
1926 }
1927 }
1928
1929 /*
1930 * If none was installed or the installed one if the last
1931 * one on the list, select the first one from the list
1932 */
1933 if ((installed_dr == NULL) || (selected_dr == NULL)) {
1934 for (dr = TAILQ_FIRST(nd_router_listp); dr;
1935 dr = TAILQ_NEXT(dr, dr_entry)) {
1936 if (dr->stateflags & NDDRF_INELIGIBLE) {
1937 continue;
1938 }
1939 if (dr->ifp == ifp || is_rti_rtrlist) {
1940 selected_dr = dr;
1941 break;
1942 }
1943 }
1944 }
1945
1946 if ((selected_dr == NULL) && (installed_dr == NULL)) {
1947 nd6log2(info,
1948 "%s:%d: Between release and re-acquire of global "
1949 "nd6_mutex lock, the list seems to have changed "
1950 "and it does not have any default routers for "
1951 "interface %s.\n",
1952 __func__, __LINE__, if_name(ifp));
1953 goto out;
1954 }
1955
1956 if (selected_dr != installed_dr) {
1957 NDDR_ADDREF(selected_dr);
1958 }
1959 } else if (installed_dr != NULL) {
1960 if (installed_dr != selected_dr) {
1961 /*
1962 * This means that selected default router is reachable
1963 * while installed one may or may not be.
1964 * Static router should always be considered as reachable
1965 * for router selection process.
1966 */
1967 if ((installed_dr->stateflags & NDDRF_STATIC) &&
1968 rtpref(installed_dr) >= rtpref(selected_dr)) {
1969 NDDR_REMREF(selected_dr);
1970 selected_dr = installed_dr;
1971 } else if (is_installed_reachable) {
1972 if (rtpref(selected_dr) <= rtpref(installed_dr)) {
1973 NDDR_REMREF(selected_dr);
1974 selected_dr = installed_dr;
1975 }
1976 }
1977 } else {
1978 NDDR_REMREF(selected_dr);
1979 }
1980 }
1981
1982 install_route:
1983 /*
1984 * If the selected router is different than the installed one,
1985 * remove the installed router and install the selected one.
1986 * Note that the selected router is never NULL here.
1987 * Else check if the route entry scope has to be changed.
1988 */
1989 lck_mtx_unlock(nd6_mutex);
1990 if (installed_dr != selected_dr) {
1991 if (rti) {
1992 nd6log(info,
1993 "%s:%d: Found a better router for interface "
1994 "%s. Installing new default route: %s/%p\n",
1995 __func__, __LINE__, if_name(ifp),
1996 ip6_sprintf(&rti->nd_rti_prefix), &rti->nd_rti_prefix);
1997 } else {
1998 nd6log(info,
1999 "%s:%d: Found a better router for interface "
2000 "%s. Installing new default route. NO RTI\n",
2001 __func__, __LINE__, if_name(ifp));
2002 }
2003 if (installed_dr != NULL) {
2004 defrouter_delreq(installed_dr, rti);
2005 }
2006 /*
2007 * Install scoped route if the interface is not
2008 * the default nd6 interface.
2009 */
2010 defrouter_addreq(selected_dr, rti,
2011 scoped && (selected_dr->ifp != nd6_defifp));
2012 } else if (((installed_dr->stateflags & NDDRF_IFSCOPE) &&
2013 (installed_dr->ifp == nd6_defifp)) ||
2014 (scoped && !(installed_dr->stateflags & NDDRF_IFSCOPE) &&
2015 (installed_dr->ifp != nd6_defifp))) {
2016 nd6log(info,
2017 "%s:%d: Need to reinstall default route for interface "
2018 "%s as its scope has changed.\n",
2019 __func__, __LINE__, if_name(ifp));
2020 defrouter_delreq(installed_dr, rti);
2021 defrouter_addreq(installed_dr, rti,
2022 scoped && (installed_dr->ifp != nd6_defifp));
2023 } else {
2024 nd6log2(info,
2025 "%s:%d: No need to change the default "
2026 "route for interface %s.\n",
2027 __func__, __LINE__, if_name(ifp));
2028 }
2029 lck_mtx_lock(nd6_mutex);
2030 out:
2031 if (selected_dr && (selected_dr != installed_dr)) {
2032 NDDR_REMREF(selected_dr);
2033 }
2034 if (installed_dr) {
2035 NDDR_REMREF(installed_dr);
2036 }
2037 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2038 VERIFY(nd_defrouter_busy);
2039 nd_defrouter_busy = FALSE;
2040 if (nd_defrouter_waiters > 0) {
2041 nd_defrouter_waiters = 0;
2042 wakeup(nd_defrouter_waitchan);
2043 }
2044 }
2045
2046 static struct nd_defrouter *
defrtrlist_update_common(struct nd_defrouter * new,struct nd_drhead * nd_router_listp,boolean_t scoped)2047 defrtrlist_update_common(struct nd_defrouter *new, struct nd_drhead *nd_router_listp, boolean_t scoped)
2048 {
2049 struct nd_defrouter *dr, *n;
2050 struct ifnet *ifp = new->ifp;
2051 struct nd_ifinfo *ndi = NULL;
2052 struct timeval caltime;
2053
2054 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2055
2056 if (nd_router_listp == NULL) {
2057 nd_router_listp = &nd_defrouter_list;
2058 }
2059
2060 /*
2061 * If we are not operating on default router list,
2062 * it implies we are operating on RTI's router list.
2063 * XXX For now we manage RTI routes un-scoped.
2064 */
2065 if (nd_router_listp != &nd_defrouter_list) {
2066 scoped = FALSE;
2067 }
2068
2069 if ((dr = defrouter_lookup(nd_router_listp, &new->rtaddr, ifp)) != NULL) {
2070 /* entry exists */
2071 /*
2072 * 1. If previous entry was not dummy and new is,
2073 * delete it and return NULL.
2074 * 2. If previous entry was dummy and the new one
2075 * is also dummy, simply return dr.
2076 * 3. If previous was dummy but new one is not,
2077 * make sure we perform default router selection again.
2078 */
2079 /* If the router was not added as a dummy and there's
2080 * been a change (lifetime advertised was 0, communicated
2081 * as NDDRF_INELIGIBLE flag), remove the entry.
2082 */
2083 if ((new->stateflags & NDDRF_INELIGIBLE) != 0 &&
2084 (dr->stateflags & NDDRF_INELIGIBLE) == 0) {
2085 TAILQ_REMOVE(nd_router_listp, dr, dr_entry);
2086 defrtrlist_del(dr, nd_router_listp);
2087 NDDR_REMREF(dr); /* remove list reference */
2088 NDDR_REMREF(dr);
2089 dr = NULL;
2090 return NULL;
2091 } else {
2092 int oldpref = rtpref(dr);
2093 struct nd_defrouter *__single p = NULL;
2094 boolean_t dummy_change = FALSE;
2095 /*
2096 * If new one is not dummy but the old one was,
2097 * reset the stateflag.
2098 */
2099 if ((new->stateflags & NDDRF_INELIGIBLE) == 0 &&
2100 (dr->stateflags & NDDRF_INELIGIBLE) != 0) {
2101 dummy_change = TRUE;
2102 dr->stateflags &= ~NDDRF_INELIGIBLE;
2103 }
2104
2105 /* override */
2106 dr->flags = new->flags; /* xxx flag check */
2107 dr->rtlifetime = new->rtlifetime;
2108 dr->expire = new->expire;
2109
2110 /*
2111 * If the preference does not change, there's no need
2112 * to sort the entries. If Scoped Routing is enabled,
2113 * put the primary/non-scoped router at the top of the
2114 * list of routers in the same preference band, unless
2115 * it's already at that position.
2116 */
2117 /* same preference and scoped; just return */
2118 if (rtpref(new) == oldpref && scoped && dummy_change == FALSE) {
2119 return dr;
2120 }
2121
2122 n = TAILQ_FIRST(nd_router_listp);
2123 while (n != NULL) {
2124 /* preference changed; sort it */
2125 if (rtpref(new) != oldpref) {
2126 break;
2127 }
2128
2129 /* not at the top of band; sort it */
2130 if (n != dr && rtpref(n) == oldpref &&
2131 (!p || rtpref(p) > rtpref(n))) {
2132 break;
2133 }
2134
2135 p = n;
2136 n = TAILQ_NEXT(n, dr_entry);
2137 }
2138
2139 /* nothing has changed, just return */
2140 if (n == NULL && (scoped ||
2141 !(dr->stateflags & NDDRF_IFSCOPE)) && dummy_change == FALSE) {
2142 return dr;
2143 }
2144
2145 /*
2146 * preferred router may be changed, so relocate
2147 * this router.
2148 * XXX: calling TAILQ_REMOVE directly is bad manners.
2149 * However, since defrtrlist_del() has many side
2150 * effects, we intentionally do so here.
2151 * defrouter_select() below will handle routing
2152 * changes later.
2153 */
2154 TAILQ_REMOVE(nd_router_listp, dr, dr_entry);
2155 new->stateflags = dr->stateflags;
2156
2157 n = dr;
2158 goto insert;
2159 }
2160 }
2161
2162 VERIFY(dr == NULL);
2163 n = nddr_alloc(Z_WAITOK);
2164
2165 ndi = ND_IFINFO(ifp);
2166 VERIFY((NULL != ndi) && (TRUE == ndi->initialized));
2167 lck_mtx_lock(&ndi->lock);
2168
2169 if (ip6_maxifdefrouters >= 0 &&
2170 ndi->ndefrouters >= ip6_maxifdefrouters) {
2171 lck_mtx_unlock(&ndi->lock);
2172 nddr_free(n);
2173 nd6log0(error, "%s: ignoring router addition as we have hit the "
2174 "max limit of %d for max default routers.\n", __func__,
2175 ip6_maxifdefrouters);
2176 return NULL;
2177 }
2178
2179 NDDR_ADDREF(n); /* for the nd_defrouter list */
2180 NDDR_ADDREF(n); /* for the caller */
2181
2182 ++nd6_defrouter_genid;
2183 ndi->ndefrouters++;
2184 VERIFY(ndi->ndefrouters != 0);
2185 lck_mtx_unlock(&ndi->lock);
2186
2187 nd6log2(info, "%s: allocating defrouter %s\n", if_name(ifp),
2188 ip6_sprintf(&new->rtaddr));
2189
2190 getmicrotime(&caltime);
2191 NDDR_LOCK(n);
2192 memcpy(&n->rtaddr, &new->rtaddr, sizeof(n->rtaddr));
2193 n->flags = new->flags;
2194 n->stateflags = new->stateflags;
2195 n->rtlifetime = new->rtlifetime;
2196 n->expire = new->expire;
2197 n->base_calendartime = caltime.tv_sec;
2198 n->base_uptime = net_uptime();
2199 n->ifp = new->ifp;
2200 n->err = new->err;
2201 n->is_reachable = TRUE;
2202 NDDR_UNLOCK(n);
2203 insert:
2204 /* get nd6_service() to be scheduled as soon as it's convenient */
2205 ++nd6_sched_timeout_want;
2206
2207 /*
2208 * Insert the new router in the Default Router List;
2209 * The Default Router List should be in the descending order
2210 * of router-preferece. When Scoped Routing is disabled, routers
2211 * with the same preference are sorted in the arriving time order;
2212 * otherwise, the first entry in the list of routers having the same
2213 * preference is the primary default router, when the interface used
2214 * by the entry is the default interface.
2215 */
2216
2217 /* insert at the end of the group */
2218 for (dr = TAILQ_FIRST(nd_router_listp); dr;
2219 dr = TAILQ_NEXT(dr, dr_entry)) {
2220 if (rtpref(n) > rtpref(dr) ||
2221 (!scoped && rtpref(n) == rtpref(dr))) {
2222 break;
2223 }
2224 }
2225 if (dr) {
2226 TAILQ_INSERT_BEFORE(dr, n, dr_entry);
2227 } else {
2228 TAILQ_INSERT_TAIL(nd_router_listp, n, dr_entry);
2229 }
2230
2231 defrouter_select(ifp, nd_router_listp);
2232
2233 return n;
2234 }
2235
2236 struct nd_defrouter *
defrtrlist_update(struct nd_defrouter * new,struct nd_drhead * nd_router_list)2237 defrtrlist_update(struct nd_defrouter *new, struct nd_drhead *nd_router_list)
2238 {
2239 struct nd_defrouter *dr;
2240
2241 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2242 dr = defrtrlist_update_common(new, nd_router_list,
2243 (nd6_defifp != NULL && new->ifp != nd6_defifp));
2244
2245 return dr;
2246 }
2247
2248 struct nd_pfxrouter *
pfxrtr_lookup(struct nd_prefix * pr,struct nd_defrouter * dr)2249 pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr)
2250 {
2251 struct nd_pfxrouter *search;
2252
2253 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2254 NDPR_LOCK_ASSERT_HELD(pr);
2255
2256 for (search = pr->ndpr_advrtrs.lh_first; search;
2257 search = search->pfr_next) {
2258 if (search->router == dr) {
2259 break;
2260 }
2261 }
2262
2263 return search;
2264 }
2265
2266 static void
pfxrtr_add(struct nd_prefix * pr,struct nd_defrouter * dr)2267 pfxrtr_add(struct nd_prefix *pr, struct nd_defrouter *dr)
2268 {
2269 struct nd_pfxrouter *__single new;
2270
2271 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2272 NDPR_LOCK_ASSERT_NOTHELD(pr);
2273
2274 new = zalloc_flags(ndprtr_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
2275 new->router = dr;
2276
2277 NDPR_LOCK(pr);
2278 LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry);
2279 pr->ndpr_genid++;
2280 NDPR_UNLOCK(pr);
2281 // callers of pfxrtr_add already in busy state
2282 pfxlist_onlink_check(true);
2283 }
2284
2285 static void
pfxrtr_del(struct nd_pfxrouter * pfr,struct nd_prefix * pr)2286 pfxrtr_del(struct nd_pfxrouter *pfr, struct nd_prefix *pr)
2287 {
2288 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2289 NDPR_LOCK_ASSERT_HELD(pr);
2290 pr->ndpr_genid++;
2291 LIST_REMOVE(pfr, pfr_entry);
2292 zfree(ndprtr_zone, pfr);
2293 }
2294
2295 /*
2296 * The routine has been modified to atomically refresh expiry
2297 * time for nd6 prefix as the part of lookup.
2298 * There's a corner case where a system going
2299 * in sleep gets rid of manual addresses configured in the system
2300 * and then schedules the prefix for deletion.
2301 * However before the prefix gets deleted, if system comes out
2302 * from sleep and configures same address before prefix deletion
2303 * , the later prefix deletion will remove the prefix route and
2304 * the system will not be able to communicate with other IPv6
2305 * neighbor nodes in the same subnet.
2306 */
2307 struct nd_prefix *
nd6_prefix_lookup(struct nd_prefix * pr,int nd6_prefix_expiry)2308 nd6_prefix_lookup(struct nd_prefix *pr, int nd6_prefix_expiry)
2309 {
2310 struct nd_prefix *__single search;
2311
2312 lck_mtx_lock(nd6_mutex);
2313 for (search = nd_prefix.lh_first; search; search = search->ndpr_next) {
2314 NDPR_LOCK(search);
2315 if (pr->ndpr_ifp == search->ndpr_ifp &&
2316 pr->ndpr_plen == search->ndpr_plen &&
2317 in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr, pr->ndpr_prefix.sin6_scope_id,
2318 &search->ndpr_prefix.sin6_addr, search->ndpr_prefix.sin6_scope_id, pr->ndpr_plen)) {
2319 if (nd6_prefix_expiry != ND6_PREFIX_EXPIRY_UNSPEC) {
2320 search->ndpr_expire = nd6_prefix_expiry;
2321 }
2322 NDPR_ADDREF(search);
2323 NDPR_UNLOCK(search);
2324 break;
2325 }
2326 NDPR_UNLOCK(search);
2327 }
2328 lck_mtx_unlock(nd6_mutex);
2329
2330 return search;
2331 }
2332
2333 int
nd6_prelist_add(struct nd_prefix * pr,struct nd_defrouter * dr,struct nd_prefix ** newp,boolean_t force_scoped)2334 nd6_prelist_add(struct nd_prefix *pr, struct nd_defrouter *dr,
2335 struct nd_prefix **newp, boolean_t force_scoped)
2336 {
2337 struct nd_prefix *__single new = NULL;
2338 ifnet_ref_t ifp = pr->ndpr_ifp;
2339 struct nd_ifinfo *__single ndi = NULL;
2340 int i, error;
2341
2342 if (ip6_maxifprefixes >= 0) {
2343 ndi = ND_IFINFO(ifp);
2344 VERIFY((NULL != ndi) && (TRUE == ndi->initialized));
2345 lck_mtx_lock(&ndi->lock);
2346 if (ndi->nprefixes >= ip6_maxifprefixes) {
2347 lck_mtx_unlock(&ndi->lock);
2348 return ENOMEM;
2349 }
2350 lck_mtx_unlock(&ndi->lock);
2351 }
2352
2353 new = ndpr_alloc(M_WAITOK);
2354 if (new == NULL) {
2355 return ENOMEM;
2356 }
2357
2358 NDPR_LOCK(new);
2359 NDPR_LOCK(pr);
2360 new->ndpr_ifp = pr->ndpr_ifp;
2361 new->ndpr_prefix = pr->ndpr_prefix;
2362 new->ndpr_plen = pr->ndpr_plen;
2363 new->ndpr_vltime = pr->ndpr_vltime;
2364 new->ndpr_pltime = pr->ndpr_pltime;
2365 new->ndpr_flags = pr->ndpr_flags;
2366 if (pr->ndpr_stateflags & NDPRF_STATIC) {
2367 new->ndpr_stateflags |= NDPRF_STATIC;
2368 }
2369 NDPR_UNLOCK(pr);
2370 if ((error = in6_init_prefix_ltimes(new)) != 0) {
2371 NDPR_UNLOCK(new);
2372 ndpr_free(new);
2373 return error;
2374 }
2375 new->ndpr_lastupdate = net_uptime();
2376 if (newp != NULL) {
2377 *newp = new;
2378 NDPR_ADDREF(new); /* for caller */
2379 }
2380 /* initialization */
2381 LIST_INIT(&new->ndpr_advrtrs);
2382 in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen);
2383 /* make prefix in the canonical form */
2384 for (i = 0; i < 4; i++) {
2385 new->ndpr_prefix.sin6_addr.s6_addr32[i] &=
2386 new->ndpr_mask.s6_addr32[i];
2387 }
2388
2389 NDPR_UNLOCK(new);
2390
2391 /* get nd6_service() to be scheduled as soon as it's convenient */
2392 ++nd6_sched_timeout_want;
2393
2394 lck_mtx_lock(nd6_mutex);
2395 nd_prefix_busy_wait();
2396 /* link ndpr_entry to nd_prefix list */
2397 LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry);
2398 new->ndpr_debug |= IFD_ATTACHED;
2399 NDPR_ADDREF(new); /* for nd_prefix list */
2400
2401 lck_mtx_lock(&ndi->lock);
2402 ndi->nprefixes++;
2403 VERIFY(ndi->nprefixes != 0);
2404 lck_mtx_unlock(&ndi->lock);
2405
2406 /* ND_OPT_PI_FLAG_ONLINK processing */
2407 if (new->ndpr_raf_onlink) {
2408 int e;
2409
2410 if ((e = nd6_prefix_onlink_common(new, force_scoped,
2411 new->ndpr_ifp->if_index)) != 0) {
2412 nd6log0(error, "nd6_prelist_add: failed to make "
2413 "the prefix %s/%d on-link %s on %s (errno=%d)\n",
2414 ip6_sprintf(&new->ndpr_prefix.sin6_addr),
2415 new->ndpr_plen, force_scoped ? "scoped" :
2416 "non-scoped", if_name(ifp), e);
2417 /* proceed anyway. XXX: is it correct? */
2418 }
2419 }
2420
2421 if (dr) {
2422 pfxrtr_add(new, dr);
2423 }
2424
2425 nd_prefix_busy_signal();
2426 lck_mtx_unlock(nd6_mutex);
2427
2428 return 0;
2429 }
2430
2431 /*
2432 * Caller must have held an extra reference on nd_prefix.
2433 */
2434 void
prelist_remove(struct nd_prefix * pr)2435 prelist_remove(struct nd_prefix *pr)
2436 {
2437 struct nd_pfxrouter *__single pfr = NULL, *__single next = NULL;
2438 ifnet_ref_t ifp = pr->ndpr_ifp;
2439 struct nd_ifinfo *__single ndi = NULL;
2440 struct nd_prefix *__single tmp_pr = NULL;
2441 boolean_t pr_scoped;
2442 int err;
2443
2444 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2445 NDPR_LOCK_ASSERT_HELD(pr);
2446
2447 if (pr->ndpr_stateflags & NDPRF_DEFUNCT) {
2448 return;
2449 }
2450
2451 pr_scoped = (pr->ndpr_stateflags & NDPRF_IFSCOPE) != 0;
2452 /*
2453 * If there are no more addresses, defunct the prefix. This is needed
2454 * because we don't want multiple threads calling prelist_remove() for
2455 * the same prefix and this might happen because we unlock nd6_mutex
2456 * down below.
2457 */
2458 if (pr->ndpr_addrcnt == 0) {
2459 pr->ndpr_stateflags |= NDPRF_DEFUNCT;
2460 }
2461
2462 /* make sure to invalidate the prefix until it is really freed. */
2463 pr->ndpr_vltime = 0;
2464 pr->ndpr_pltime = 0;
2465
2466 /*
2467 * Though these flags are now meaningless, we'd rather keep the value
2468 * of pr->ndpr_raf_onlink and pr->ndpr_raf_auto not to confuse users
2469 * when executing "ndp -p".
2470 */
2471 if (pr->ndpr_stateflags & NDPRF_ONLINK) {
2472 int error = 0;
2473 NDPR_ADDREF(pr);
2474 NDPR_UNLOCK(pr);
2475 nd_prefix_busy_signal();
2476 lck_mtx_unlock(nd6_mutex);
2477 if ((error = nd6_prefix_offlink(pr)) != 0) {
2478 nd6log0(error, "prelist_remove: failed to make "
2479 "%s/%d offlink on %s, errno=%d\n",
2480 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
2481 pr->ndpr_plen, if_name(ifp), error);
2482 /* what should we do? */
2483 }
2484 lck_mtx_lock(nd6_mutex);
2485 nd_prefix_busy_wait();
2486 NDPR_LOCK(pr);
2487 if (NDPR_REMREF(pr) == NULL) {
2488 // We entered in the busy state and should return in the busy state
2489 return;
2490 }
2491 }
2492
2493 /*
2494 * Check if there is a scoped version of this PR, if so
2495 * make it unscoped.
2496 */
2497 if (!pr_scoped && IN6_IS_ADDR_UNIQUE_LOCAL(&pr->ndpr_prefix.sin6_addr)) {
2498 tmp_pr = nd6_prefix_equal_lookup(pr, FALSE);
2499 if (tmp_pr != NULL) {
2500 NDPR_ADDREF(pr);
2501 NDPR_UNLOCK(pr);
2502
2503 nd_prefix_busy_signal();
2504 lck_mtx_unlock(nd6_mutex);
2505 err = nd6_prefix_offlink(tmp_pr);
2506 lck_mtx_lock(nd6_mutex);
2507 nd_prefix_busy_wait();
2508 if (err != 0) {
2509 nd6log0(error,
2510 "%s: failed to make %s/%d offlink on %s, "
2511 "errno=%d\n", __func__,
2512 ip6_sprintf(&tmp_pr->ndpr_prefix.sin6_addr),
2513 tmp_pr->ndpr_plen, if_name(tmp_pr->ndpr_ifp), err);
2514 }
2515
2516 err = nd6_prefix_onlink_scoped(tmp_pr, IFSCOPE_NONE);
2517 if (err != 0) {
2518 nd6log0(error,
2519 "%s: failed to make %s/%d onlink on %s, errno=%d\n",
2520 __func__, ip6_sprintf(&tmp_pr->ndpr_prefix.sin6_addr),
2521 tmp_pr->ndpr_plen, if_name(tmp_pr->ndpr_ifp), err);
2522 }
2523
2524 if (err != 0) {
2525 nd6log0(error,
2526 "%s: error unscoping %s/%d from %s\n",
2527 __func__, ip6_sprintf(&tmp_pr->ndpr_prefix.sin6_addr),
2528 tmp_pr->ndpr_plen, if_name(tmp_pr->ndpr_ifp));
2529 } else {
2530 nd6log2(info,
2531 "%s: %s/%d unscoped, previously on %s\n",
2532 __func__, ip6_sprintf(&tmp_pr->ndpr_prefix.sin6_addr),
2533 tmp_pr->ndpr_plen, if_name(tmp_pr->ndpr_ifp));
2534 }
2535
2536 NDPR_REMREF(tmp_pr);
2537
2538 NDPR_LOCK(pr);
2539 if (NDPR_REMREF(pr) == NULL) {
2540 return;
2541 }
2542 }
2543 }
2544
2545 if (pr->ndpr_addrcnt > 0) {
2546 /*
2547 * The state might have changed if we called
2548 * nd6_prefix_offlink().
2549 */
2550 pr->ndpr_stateflags &= ~NDPRF_DEFUNCT;
2551 return; /* notice here? */
2552 }
2553
2554 /* unlink ndpr_entry from nd_prefix list */
2555 LIST_REMOVE(pr, ndpr_entry);
2556 pr->ndpr_debug &= ~IFD_ATTACHED;
2557
2558 /* free list of routers that adversed the prefix */
2559 for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
2560 next = pfr->pfr_next;
2561 pfxrtr_del(pfr, pr);
2562 }
2563
2564 ndi = ND_IFINFO(ifp);
2565 VERIFY((NULL != ndi) && (TRUE == ndi->initialized));
2566 lck_mtx_lock(&ndi->lock);
2567 VERIFY(ndi->nprefixes > 0);
2568 ndi->nprefixes--;
2569 lck_mtx_unlock(&ndi->lock);
2570
2571 /* This must not be the last reference to the nd_prefix */
2572 if (NDPR_REMREF(pr) == NULL) {
2573 panic("%s: unexpected (missing) refcnt ndpr=%p", __func__, pr);
2574 /* NOTREACHED */
2575 }
2576
2577 /*
2578 * Don't call pfxlist_onlink_check() here because we are
2579 * holding the NDPR lock and this could cause a deadlock when
2580 * there are multiple threads executing pfxlist_onlink_check().
2581 */
2582 }
2583
2584 int
prelist_update(struct nd_prefix * new,struct nd_defrouter * dr,struct mbuf * m,int mcast)2585 prelist_update(
2586 struct nd_prefix *new,
2587 struct nd_defrouter *dr, /* may be NULL */
2588 struct mbuf *m,
2589 int mcast)
2590 {
2591 struct in6_ifaddr *__single ia6 = NULL, *__single ia6_match = NULL;
2592 struct ifaddr *__single ifa;
2593 ifnet_ref_t ifp = new->ndpr_ifp;
2594 struct nd_prefix *__single pr;
2595 int error = 0;
2596 int newprefix = 0;
2597 int auth;
2598 uint64_t timenow = net_uptime();
2599
2600 /* no need to lock "new" here, as it is local to the caller */
2601 NDPR_LOCK_ASSERT_NOTHELD(new);
2602
2603 auth = 0;
2604 if (m) {
2605 /*
2606 * Authenticity for NA consists authentication for
2607 * both IP header and IP datagrams, doesn't it ?
2608 */
2609 #if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
2610 auth = (m->m_flags & M_AUTHIPHDR) && (m->m_flags & M_AUTHIPDGM);
2611 #endif
2612 }
2613
2614 if ((pr = nd6_prefix_lookup(new, ND6_PREFIX_EXPIRY_UNSPEC)) != NULL) {
2615 /*
2616 * nd6_prefix_lookup() ensures that pr and new have the same
2617 * prefix on a same interface.
2618 */
2619
2620 /*
2621 * Update prefix information. Note that the on-link (L) bit
2622 * and the autonomous (A) bit should NOT be changed from 1
2623 * to 0.
2624 */
2625 lck_mtx_lock(nd6_mutex);
2626 NDPR_LOCK(pr);
2627 if (new->ndpr_raf_onlink == 1) {
2628 pr->ndpr_raf_onlink = 1;
2629 }
2630 if (new->ndpr_raf_auto == 1) {
2631 pr->ndpr_raf_auto = 1;
2632 }
2633 if (new->ndpr_raf_onlink) {
2634 pr->ndpr_vltime = new->ndpr_vltime;
2635 pr->ndpr_pltime = new->ndpr_pltime;
2636 (void) in6_init_prefix_ltimes(pr); /* XXX error case? */
2637 pr->ndpr_lastupdate = net_uptime();
2638 }
2639
2640 NDPR_ADDREF(pr);
2641 if (new->ndpr_raf_onlink &&
2642 (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
2643 int e;
2644
2645 NDPR_UNLOCK(pr);
2646 if ((e = nd6_prefix_onlink(pr)) != 0) {
2647 nd6log0(error,
2648 "prelist_update: failed to make "
2649 "the prefix %s/%d on-link on %s "
2650 "(errno=%d)\n",
2651 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
2652 pr->ndpr_plen, if_name(pr->ndpr_ifp), e);
2653 /* proceed anyway. XXX: is it correct? */
2654 }
2655 NDPR_LOCK(pr);
2656 }
2657
2658 if (dr && pfxrtr_lookup(pr, dr) == NULL) {
2659 NDPR_UNLOCK(pr);
2660 nd_prefix_busy_wait();
2661 pfxrtr_add(pr, dr);
2662 nd_prefix_busy_signal();
2663 } else {
2664 NDPR_UNLOCK(pr);
2665 }
2666 NDPR_REMREF(pr);
2667 lck_mtx_unlock(nd6_mutex);
2668 } else {
2669 newprefix = 1;
2670
2671 if (new->ndpr_vltime == 0) {
2672 goto end;
2673 }
2674 if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0) {
2675 goto end;
2676 }
2677
2678 bzero(&new->ndpr_addr, sizeof(struct in6_addr));
2679
2680 error = nd6_prelist_add(new, dr, &pr, FALSE);
2681 if (error != 0 || pr == NULL) {
2682 nd6log(info, "prelist_update: "
2683 "nd6_prelist_add failed for %s/%d on %s "
2684 "errno=%d, returnpr=0x%llx\n",
2685 ip6_sprintf(&new->ndpr_prefix.sin6_addr),
2686 new->ndpr_plen, if_name(new->ndpr_ifp),
2687 error, (uint64_t)VM_KERNEL_ADDRPERM(pr));
2688 goto end; /* we should just give up in this case. */
2689 }
2690 }
2691
2692 /*
2693 * Address autoconfiguration based on Section 5.5.3 of RFC 4862.
2694 * Note that pr must be non NULL at this point.
2695 */
2696
2697 /* 5.5.3 (a). Ignore the prefix without the A bit set. */
2698 if (!new->ndpr_raf_auto) {
2699 goto end;
2700 }
2701
2702 /*
2703 * 5.5.3 (b). the link-local prefix should have been ignored in
2704 * nd6_ra_input.
2705 */
2706
2707 /* 5.5.3 (c). Consistency check on lifetimes: pltime <= vltime. */
2708 if (new->ndpr_pltime > new->ndpr_vltime) {
2709 error = EINVAL; /* XXX: won't be used */
2710 goto end;
2711 }
2712
2713 /*
2714 * 5.5.3 (d). If the prefix advertised is not equal to the prefix of
2715 * an address configured by stateless autoconfiguration already in the
2716 * list of addresses associated with the interface, and the Valid
2717 * Lifetime is not 0, form an address. We first check if we have
2718 * a matching prefix.
2719 */
2720 ifnet_lock_shared(ifp);
2721 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2722 struct in6_ifaddr *__single ifa6 = NULL;
2723 u_int32_t remaininglifetime = 0;
2724 struct in6_addrlifetime lt6_tmp = {};
2725
2726 IFA_LOCK(ifa);
2727 if (ifa->ifa_addr->sa_family != AF_INET6) {
2728 IFA_UNLOCK(ifa);
2729 continue;
2730 }
2731 ifa6 = ifatoia6(ifa);
2732
2733 /*
2734 * We only consider autoconfigured addresses as per RFC 4862.
2735 */
2736 if (!(ifa6->ia6_flags & IN6_IFF_AUTOCONF)) {
2737 IFA_UNLOCK(ifa);
2738 continue;
2739 }
2740 /*
2741 * Spec is not clear here, but I believe we should concentrate
2742 * on unicast (i.e. not anycast) addresses.
2743 * XXX: other ia6_flags? detached or duplicated?
2744 */
2745 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0) {
2746 IFA_UNLOCK(ifa);
2747 continue;
2748 }
2749 /*
2750 * Ignore the address if it is not associated with a prefix
2751 * or is associated with a prefix that is different from this
2752 * one. (pr is never NULL here)
2753 */
2754 if (ifa6->ia6_ndpr != pr) {
2755 IFA_UNLOCK(ifa);
2756 continue;
2757 }
2758
2759 if (ia6_match == NULL) { /* remember the first one */
2760 ia6_match = ifa6;
2761 ifa_addref(ifa); /* for ia6_match */
2762 }
2763
2764 /*
2765 * An already autoconfigured address matched. Now that we
2766 * are sure there is at least one matched address, we can
2767 * proceed to 5.5.3. (e): update the lifetimes according to the
2768 * "two hours" rule and the privacy extension.
2769 */
2770 /* retrieve time as uptime (last arg is 0) */
2771 in6ifa_getlifetime(ifa6, <6_tmp, 0);
2772
2773 if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME) {
2774 remaininglifetime = ND6_INFINITE_LIFETIME;
2775 } else if (timenow - ifa6->ia6_updatetime > lt6_tmp.ia6t_vltime) {
2776 /*
2777 * The case of "invalid" address. We should usually
2778 * not see this case.
2779 */
2780 remaininglifetime = 0;
2781 } else {
2782 remaininglifetime = lt6_tmp.ia6t_vltime -
2783 (uint32_t)(timenow - ifa6->ia6_updatetime);
2784 }
2785 /* when not updating, keep the current stored lifetime. */
2786 lt6_tmp.ia6t_vltime = remaininglifetime;
2787
2788 if (TWOHOUR < new->ndpr_vltime ||
2789 remaininglifetime < new->ndpr_vltime) {
2790 lt6_tmp.ia6t_vltime = new->ndpr_vltime;
2791 } else if (remaininglifetime <= TWOHOUR) {
2792 if (auth) {
2793 lt6_tmp.ia6t_vltime = new->ndpr_vltime;
2794 }
2795 } else {
2796 /*
2797 * new->ndpr_vltime <= TWOHOUR &&
2798 * TWOHOUR < remaininglifetime
2799 */
2800 lt6_tmp.ia6t_vltime = TWOHOUR;
2801 }
2802
2803 /* The 2 hour rule is not imposed for preferred lifetime. */
2804 lt6_tmp.ia6t_pltime = new->ndpr_pltime;
2805
2806 /* Special handling for lifetimes of temporary addresses. */
2807 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
2808 u_int32_t maxvltime, maxpltime;
2809
2810 /* Constrain lifetimes to system limits. */
2811 if (lt6_tmp.ia6t_vltime > ip6_temp_valid_lifetime) {
2812 lt6_tmp.ia6t_vltime = ip6_temp_valid_lifetime;
2813 }
2814 if (lt6_tmp.ia6t_pltime > ip6_temp_preferred_lifetime) {
2815 lt6_tmp.ia6t_pltime =
2816 ip6_temp_preferred_lifetime -
2817 ip6_desync_factor;
2818 }
2819
2820 /*
2821 * According to RFC 4941, section 3.3 (1), we only
2822 * update the lifetimes when they are in the maximum
2823 * intervals.
2824 */
2825 if (ip6_temp_valid_lifetime >
2826 (u_int32_t)((timenow - ifa6->ia6_createtime) +
2827 ip6_desync_factor)) {
2828 maxvltime = ip6_temp_valid_lifetime -
2829 (uint32_t)((timenow - ifa6->ia6_createtime) +
2830 ip6_desync_factor);
2831 } else {
2832 maxvltime = 0;
2833 }
2834 if (ip6_temp_preferred_lifetime >
2835 (u_int32_t)((timenow - ifa6->ia6_createtime) +
2836 ip6_desync_factor)) {
2837 maxpltime = ip6_temp_preferred_lifetime -
2838 (uint32_t)((timenow - ifa6->ia6_createtime) +
2839 ip6_desync_factor);
2840 } else {
2841 maxpltime = 0;
2842 }
2843
2844 if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME ||
2845 lt6_tmp.ia6t_vltime > maxvltime) {
2846 lt6_tmp.ia6t_vltime = maxvltime;
2847 }
2848
2849 if (lt6_tmp.ia6t_pltime == ND6_INFINITE_LIFETIME ||
2850 lt6_tmp.ia6t_pltime > maxpltime) {
2851 lt6_tmp.ia6t_pltime = maxpltime;
2852 }
2853 }
2854
2855 in6_init_address_ltimes(<6_tmp);
2856 in6ifa_setlifetime(ifa6, <6_tmp);
2857 ifa6->ia6_updatetime = timenow;
2858 IFA_UNLOCK(ifa);
2859 }
2860 ifnet_lock_done(ifp);
2861 if (ia6_match == NULL && new->ndpr_vltime) {
2862 /*
2863 * 5.5.3 (d) (continued)
2864 * No address matched and the valid lifetime is non-zero.
2865 * Create a new address.
2866 */
2867 if ((ia6 = in6_pfx_newpersistaddr(new, mcast, &error, FALSE, 0))
2868 != NULL) {
2869 /*
2870 * note that we should use pr (not new) for reference.
2871 */
2872 IFA_LOCK(&ia6->ia_ifa);
2873 NDPR_LOCK(pr);
2874 ia6->ia6_ndpr = pr;
2875 NDPR_ADDREF(pr); /* for addr reference */
2876 pr->ndpr_addrcnt++;
2877 VERIFY(pr->ndpr_addrcnt != 0);
2878 NDPR_UNLOCK(pr);
2879 IFA_UNLOCK(&ia6->ia_ifa);
2880
2881 /*
2882 * RFC 4941 3.3 (2).
2883 * When a new public address is created as described
2884 * in RFC 4862, also create a new temporary address.
2885 *
2886 * RFC 4941 3.5.
2887 * When an interface connects to a new link, a new
2888 * randomized interface identifier should be generated
2889 * immediately together with a new set of temporary
2890 * addresses. Thus, we specify 1 as the 2nd arg of
2891 * in6_tmpifadd().
2892 */
2893 if (ip6_use_tempaddr &&
2894 (!IN6_IS_ADDR_UNIQUE_LOCAL(&new->ndpr_prefix.sin6_addr)
2895 || ip6_ula_use_tempaddr)) {
2896 int e;
2897 if ((e = in6_tmpifadd(ia6, 1)) != 0) {
2898 nd6log(info, "prelist_update: "
2899 "failed to create a temporary "
2900 "address, errno=%d\n",
2901 e);
2902 }
2903 }
2904 ifa_remref(&ia6->ia_ifa);
2905 ia6 = NULL;
2906
2907 /*
2908 * If the interface is marked for CLAT46 configuration
2909 * try and configure the reserved IPv6 address for
2910 * stateless translation.
2911 */
2912 if (IS_INTF_CLAT46(ifp)) {
2913 if ((ia6 = in6_pfx_newpersistaddr(new, mcast,
2914 &error, TRUE, CLAT46_COLLISION_COUNT_OFFSET))
2915 != NULL) {
2916 IFA_LOCK(&ia6->ia_ifa);
2917 NDPR_LOCK(pr);
2918 ia6->ia6_ndpr = pr;
2919 NDPR_ADDREF(pr); /* for addr reference */
2920 pr->ndpr_addrcnt++;
2921 VERIFY(pr->ndpr_addrcnt != 0);
2922 pr->ndpr_stateflags |= NDPRF_CLAT46;
2923 NDPR_UNLOCK(pr);
2924 IFA_UNLOCK(&ia6->ia_ifa);
2925 ifa_remref(&ia6->ia_ifa);
2926 ia6 = NULL;
2927 } else if (error != EEXIST) {
2928 uuid_t tmp_uuid = {};
2929 /*
2930 * Only report the error if it is not
2931 * EEXIST.
2932 */
2933 ip6stat.ip6s_clat464_v6addr_conffail++;
2934 in6_clat46_event_enqueue_nwk_wq_entry(
2935 IN6_CLAT46_EVENT_V6_ADDR_CONFFAIL,
2936 0,
2937 tmp_uuid);
2938 nd6log0(error, "Could not configure CLAT46 address on interface %s.\n", ifp->if_xname);
2939 }
2940 /*
2941 * Reset the error as we do not want to
2942 * treat failure of CLAT46 address configuration
2943 * as complete failure in prelist update path.
2944 */
2945 error = 0;
2946 }
2947
2948 /*
2949 * A newly added address might affect the status
2950 * of other addresses, so we check and update it.
2951 * XXX: what if address duplication happens?
2952 */
2953 lck_mtx_lock(nd6_mutex);
2954 pfxlist_onlink_check(false);
2955 lck_mtx_unlock(nd6_mutex);
2956 }
2957 }
2958 end:
2959 if (pr != NULL) {
2960 NDPR_REMREF(pr);
2961 }
2962 if (ia6_match != NULL) {
2963 ifa_remref(&ia6_match->ia_ifa);
2964 }
2965 return error;
2966 }
2967
2968 /*
2969 * Neighbor Discover Default Router structure reference counting routines.
2970 */
2971 static struct nd_defrouter *
nddr_alloc(zalloc_flags_t how)2972 nddr_alloc(zalloc_flags_t how)
2973 {
2974 struct nd_defrouter *__single dr;
2975
2976 dr = zalloc_flags(nddr_zone, how | Z_ZERO);
2977 if (dr) {
2978 lck_mtx_init(&dr->nddr_lock, &ifa_mtx_grp, &ifa_mtx_attr);
2979 lck_mtx_init(&dr->nddr_ref_lock, &ifa_mtx_grp, &ifa_mtx_attr);
2980 dr->nddr_debug |= IFD_ALLOC;
2981 if (nddr_debug != 0) {
2982 dr->nddr_debug |= IFD_DEBUG;
2983 dr->nddr_trace = nddr_trace;
2984 }
2985 }
2986 return dr;
2987 }
2988
2989 static void
nddr_free(struct nd_defrouter * dr)2990 nddr_free(struct nd_defrouter *dr)
2991 {
2992 if (dr->nddr_debug & IFD_ATTACHED) {
2993 panic("%s: attached nddr %p is being freed", __func__, dr);
2994 /* NOTREACHED */
2995 } else if (!(dr->nddr_debug & IFD_ALLOC)) {
2996 panic("%s: nddr %p cannot be freed", __func__, dr);
2997 /* NOTREACHED */
2998 }
2999 dr->nddr_debug &= ~IFD_ALLOC;
3000 lck_mtx_destroy(&dr->nddr_lock, &ifa_mtx_grp);
3001 lck_mtx_destroy(&dr->nddr_ref_lock, &ifa_mtx_grp);
3002 zfree(nddr_zone, dr);
3003 }
3004
3005 static void
nddr_trace(struct nd_defrouter * dr,int refhold)3006 nddr_trace(struct nd_defrouter *dr, int refhold)
3007 {
3008 struct nd_defrouter_dbg *__single dr_dbg = (struct nd_defrouter_dbg *)dr;
3009 ctrace_t *tr;
3010 uint32_t idx;
3011 uint16_t *cnt;
3012
3013 if (!(dr->nddr_debug & IFD_DEBUG)) {
3014 panic("%s: nddr %p has no debug structure", __func__, dr);
3015 /* NOTREACHED */
3016 }
3017 if (refhold) {
3018 cnt = &dr_dbg->nddr_refhold_cnt;
3019 tr = dr_dbg->nddr_refhold;
3020 } else {
3021 cnt = &dr_dbg->nddr_refrele_cnt;
3022 tr = dr_dbg->nddr_refrele;
3023 }
3024
3025 idx = os_atomic_inc_orig(cnt, relaxed) % NDDR_TRACE_HIST_SIZE;
3026 ctrace_record(&tr[idx]);
3027 }
3028
3029 void
nddr_addref(struct nd_defrouter * nddr)3030 nddr_addref(struct nd_defrouter *nddr)
3031 {
3032 NDDR_REF_LOCK_SPIN(nddr);
3033 if (++nddr->nddr_refcount == 0) {
3034 panic("%s: nddr %p wraparound refcnt", __func__, nddr);
3035 /* NOTREACHED */
3036 } else if (nddr->nddr_trace != NULL) {
3037 (*nddr->nddr_trace)(nddr, TRUE);
3038 }
3039 NDDR_REF_UNLOCK(nddr);
3040 }
3041
3042 struct nd_defrouter *
nddr_remref(struct nd_defrouter * nddr)3043 nddr_remref(struct nd_defrouter *nddr)
3044 {
3045 NDDR_REF_LOCK_SPIN(nddr);
3046 if (nddr->nddr_refcount == 0) {
3047 panic("%s: nddr %p negative refcnt", __func__, nddr);
3048 /* NOTREACHED */
3049 } else if (nddr->nddr_trace != NULL) {
3050 (*nddr->nddr_trace)(nddr, FALSE);
3051 }
3052
3053 if (--nddr->nddr_refcount == 0) {
3054 NDDR_REF_UNLOCK(nddr);
3055 nddr_free(nddr);
3056 nddr = NULL;
3057 } else {
3058 NDDR_REF_UNLOCK(nddr);
3059 }
3060 return nddr;
3061 }
3062
3063 uint64_t
nddr_getexpire(struct nd_defrouter * dr)3064 nddr_getexpire(struct nd_defrouter *dr)
3065 {
3066 struct timeval caltime;
3067 uint64_t expiry;
3068
3069 if (dr->expire != 0) {
3070 /* account for system time change */
3071 getmicrotime(&caltime);
3072
3073 dr->base_calendartime +=
3074 NET_CALCULATE_CLOCKSKEW(caltime,
3075 dr->base_calendartime, net_uptime(), dr->base_uptime);
3076
3077 expiry = dr->base_calendartime +
3078 dr->expire - dr->base_uptime;
3079 } else {
3080 expiry = 0;
3081 }
3082 return expiry;
3083 }
3084
3085 /*
3086 * Neighbor Discover Prefix structure reference counting routines.
3087 */
3088 static struct nd_prefix *
ndpr_alloc(int how)3089 ndpr_alloc(int how)
3090 {
3091 struct nd_prefix *__single pr;
3092
3093 pr = zalloc_flags(ndpr_zone, how | Z_ZERO);
3094 if (pr != NULL) {
3095 lck_mtx_init(&pr->ndpr_lock, &ifa_mtx_grp, &ifa_mtx_attr);
3096 lck_mtx_init(&pr->ndpr_ref_lock, &ifa_mtx_grp, &ifa_mtx_attr);
3097 RB_INIT(&pr->ndpr_prproxy_sols);
3098 pr->ndpr_debug |= IFD_ALLOC;
3099 if (ndpr_debug != 0) {
3100 pr->ndpr_debug |= IFD_DEBUG;
3101 pr->ndpr_trace = ndpr_trace;
3102 }
3103 }
3104 return pr;
3105 }
3106
3107 static void
ndpr_free(struct nd_prefix * pr)3108 ndpr_free(struct nd_prefix *pr)
3109 {
3110 if (pr->ndpr_debug & IFD_ATTACHED) {
3111 panic("%s: attached ndpr %p is being freed", __func__, pr);
3112 /* NOTREACHED */
3113 } else if (!(pr->ndpr_debug & IFD_ALLOC)) {
3114 panic("%s: ndpr %p cannot be freed", __func__, pr);
3115 /* NOTREACHED */
3116 } else if (pr->ndpr_rt != NULL) {
3117 panic("%s: ndpr %p route %p not freed", __func__, pr,
3118 pr->ndpr_rt);
3119 /* NOTREACHED */
3120 } else if (pr->ndpr_prproxy_sols_cnt != 0) {
3121 panic("%s: ndpr %p non-zero solicitors count (%d)",
3122 __func__, pr, pr->ndpr_prproxy_sols_cnt);
3123 /* NOTREACHED */
3124 } else if (!RB_EMPTY(&pr->ndpr_prproxy_sols)) {
3125 panic("%s: ndpr %p non-empty solicitors tree", __func__, pr);
3126 /* NOTREACHED */
3127 }
3128 pr->ndpr_debug &= ~IFD_ALLOC;
3129 lck_mtx_destroy(&pr->ndpr_lock, &ifa_mtx_grp);
3130 lck_mtx_destroy(&pr->ndpr_ref_lock, &ifa_mtx_grp);
3131 zfree(ndpr_zone, pr);
3132 }
3133
3134 static void
ndpr_trace(struct nd_prefix * pr,int refhold)3135 ndpr_trace(struct nd_prefix *pr, int refhold)
3136 {
3137 struct nd_prefix_dbg *__single pr_dbg = (struct nd_prefix_dbg *)pr;
3138 ctrace_t *tr;
3139 u_int32_t idx;
3140 u_int16_t *cnt;
3141
3142 if (!(pr->ndpr_debug & IFD_DEBUG)) {
3143 panic("%s: ndpr %p has no debug structure", __func__, pr);
3144 /* NOTREACHED */
3145 }
3146 if (refhold) {
3147 cnt = &pr_dbg->ndpr_refhold_cnt;
3148 tr = pr_dbg->ndpr_refhold;
3149 } else {
3150 cnt = &pr_dbg->ndpr_refrele_cnt;
3151 tr = pr_dbg->ndpr_refrele;
3152 }
3153
3154 idx = os_atomic_inc_orig(cnt, relaxed) % NDPR_TRACE_HIST_SIZE;
3155 ctrace_record(&tr[idx]);
3156 }
3157
3158 void
ndpr_addref(struct nd_prefix * ndpr)3159 ndpr_addref(struct nd_prefix *ndpr)
3160 {
3161 NDPR_REF_LOCK_SPIN(ndpr);
3162 if (++ndpr->ndpr_refcount == 0) {
3163 panic("%s: ndpr %p wraparound refcnt", __func__, ndpr);
3164 /* NOTREACHED */
3165 } else if (ndpr->ndpr_trace != NULL) {
3166 (*ndpr->ndpr_trace)(ndpr, TRUE);
3167 }
3168 NDPR_REF_UNLOCK(ndpr);
3169 }
3170
3171 struct nd_prefix *
ndpr_remref(struct nd_prefix * ndpr)3172 ndpr_remref(struct nd_prefix *ndpr)
3173 {
3174 NDPR_REF_LOCK_SPIN(ndpr);
3175 if (ndpr->ndpr_refcount == 0) {
3176 panic("%s: ndpr %p negative refcnt", __func__, ndpr);
3177 /* NOTREACHED */
3178 } else if (ndpr->ndpr_trace != NULL) {
3179 (*ndpr->ndpr_trace)(ndpr, FALSE);
3180 }
3181
3182 if (--ndpr->ndpr_refcount == 0) {
3183 if (ndpr->ndpr_addrcnt != 0) {
3184 panic("%s: freeing ndpr %p with outstanding address "
3185 "reference (%d)", __func__, ndpr,
3186 ndpr->ndpr_addrcnt);
3187 /* NOTREACHED */
3188 }
3189 NDPR_REF_UNLOCK(ndpr);
3190 ndpr_free(ndpr);
3191 ndpr = NULL;
3192 } else {
3193 NDPR_REF_UNLOCK(ndpr);
3194 }
3195 return ndpr;
3196 }
3197
3198 uint64_t
ndpr_getexpire(struct nd_prefix * pr)3199 ndpr_getexpire(struct nd_prefix *pr)
3200 {
3201 struct timeval caltime;
3202 uint64_t expiry;
3203
3204 if (pr->ndpr_expire != 0 && pr->ndpr_vltime != ND6_INFINITE_LIFETIME) {
3205 /* account for system time change */
3206 getmicrotime(&caltime);
3207
3208 pr->ndpr_base_calendartime +=
3209 NET_CALCULATE_CLOCKSKEW(caltime,
3210 pr->ndpr_base_calendartime, net_uptime(),
3211 pr->ndpr_base_uptime);
3212
3213 expiry = pr->ndpr_base_calendartime +
3214 pr->ndpr_expire - pr->ndpr_base_uptime;
3215 } else {
3216 expiry = 0;
3217 }
3218 return expiry;
3219 }
3220
3221 /*
3222 * A supplement function used in the on-link detection below;
3223 * detect if a given prefix has a (probably) reachable advertising router.
3224 * XXX: lengthy function name...
3225 */
3226 static struct nd_pfxrouter *
find_pfxlist_reachable_router(struct nd_prefix * pr)3227 find_pfxlist_reachable_router(struct nd_prefix *pr)
3228 {
3229 struct nd_pfxrouter *__single pfxrtr = NULL;
3230 ifnet_ref_t ifp = NULL;
3231
3232 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
3233 NDPR_LOCK_ASSERT_HELD(pr);
3234
3235 pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs);
3236 while (pfxrtr) {
3237 /* XXX This should be same as prefixes interface. */
3238 ifp = pfxrtr->router->ifp;
3239
3240 /*
3241 * As long as there's a router advertisting this prefix
3242 * on cellular (for that matter any interface that is point
3243 * to point really), we treat the router as reachable.
3244 */
3245 if (ifp != NULL && ifp->if_type == IFT_CELLULAR) {
3246 break;
3247 }
3248
3249 if (pfxrtr->router->is_reachable) {
3250 break;
3251 }
3252 pfxrtr = LIST_NEXT(pfxrtr, pfr_entry);
3253 }
3254 return pfxrtr;
3255 }
3256
3257 /*
3258 * Check if each prefix in the prefix list has at least one available router
3259 * that advertised the prefix (a router is "available" if its neighbor cache
3260 * entry is reachable or probably reachable).
3261 * If the check fails, the prefix may be off-link, because, for example,
3262 * we have moved from the network but the lifetime of the prefix has not
3263 * expired yet. So we should not use the prefix if there is another prefix
3264 * that has an available router.
3265 * But, if there is no prefix that has an available router, we still regards
3266 * all the prefixes as on-link. This is because we can't tell if all the
3267 * routers are simply dead or if we really moved from the network and there
3268 * is no router around us.
3269 */
3270 void
pfxlist_onlink_check(bool already_locked)3271 pfxlist_onlink_check(bool already_locked)
3272 {
3273 struct nd_prefix *__single pr, *__single prclear;
3274 struct in6_ifaddr *__single ifa;
3275 struct nd_defrouter *__single dr;
3276 struct nd_pfxrouter *__single pfxrtr = NULL;
3277 int err, i, found = 0;
3278 u_int16_t addresses_count;
3279 struct ifaddr **__single __counted_by(addresses_count) ifap = NULL;
3280 struct nd_prefix *__single ndpr;
3281 u_int64_t timenow = net_uptime();
3282
3283 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
3284
3285 if (!already_locked) {
3286 nd_prefix_busy_wait();
3287 } else {
3288 VERIFY(nd_prefix_busy);
3289 }
3290
3291 /*
3292 * Check if there is a prefix that has a reachable advertising
3293 * router.
3294 */
3295 pr = nd_prefix.lh_first;
3296 while (pr) {
3297 NDPR_LOCK(pr);
3298 if (pr->ndpr_raf_onlink && find_pfxlist_reachable_router(pr) &&
3299 (pr->ndpr_debug & IFD_ATTACHED)) {
3300 NDPR_UNLOCK(pr);
3301 break;
3302 }
3303 NDPR_UNLOCK(pr);
3304 pr = pr->ndpr_next;
3305 }
3306 /*
3307 * If we have no such prefix, check whether we still have a router
3308 * that does not advertise any prefixes.
3309 */
3310 if (pr == NULL) {
3311 for (dr = TAILQ_FIRST(&nd_defrouter_list); dr;
3312 dr = TAILQ_NEXT(dr, dr_entry)) {
3313 struct nd_prefix *__single pr0;
3314
3315 for (pr0 = nd_prefix.lh_first; pr0;
3316 pr0 = pr0->ndpr_next) {
3317 NDPR_LOCK(pr0);
3318 if ((pfxrtr = pfxrtr_lookup(pr0, dr)) != NULL) {
3319 NDPR_UNLOCK(pr0);
3320 break;
3321 }
3322 NDPR_UNLOCK(pr0);
3323 }
3324 if (pfxrtr != NULL) {
3325 break;
3326 }
3327 }
3328 }
3329 if (pr != NULL || (TAILQ_FIRST(&nd_defrouter_list) && pfxrtr == NULL)) {
3330 /*
3331 * There is at least one prefix that has a reachable router,
3332 * or at least a router which probably does not advertise
3333 * any prefixes. The latter would be the case when we move
3334 * to a new link where we have a router that does not provide
3335 * prefixes and we configure an address by hand.
3336 * Detach prefixes which have no reachable advertising
3337 * router, and attach other prefixes.
3338 */
3339 pr = nd_prefix.lh_first;
3340 while (pr) {
3341 NDPR_LOCK(pr);
3342 /*
3343 * We aren't interested prefixes already processed,
3344 * nor in prefixes without the L bit
3345 * set nor in static prefixes
3346 */
3347 if (pr->ndpr_raf_onlink == 0 ||
3348 pr->ndpr_stateflags & NDPRF_STATIC) {
3349 NDPR_UNLOCK(pr);
3350 pr = pr->ndpr_next;
3351 continue;
3352 }
3353 if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
3354 find_pfxlist_reachable_router(pr) == NULL &&
3355 (pr->ndpr_debug & IFD_ATTACHED)) {
3356 pr->ndpr_stateflags |= NDPRF_DETACHED;
3357 }
3358 if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
3359 find_pfxlist_reachable_router(pr) != NULL &&
3360 (pr->ndpr_debug & IFD_ATTACHED)) {
3361 pr->ndpr_stateflags &= ~NDPRF_DETACHED;
3362 }
3363 NDPR_UNLOCK(pr);
3364 pr = pr->ndpr_next;
3365 }
3366 } else {
3367 /* there is no prefix that has a reachable router */
3368 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
3369 NDPR_LOCK(pr);
3370 if (pr->ndpr_raf_onlink == 0 ||
3371 pr->ndpr_stateflags & NDPRF_STATIC) {
3372 NDPR_UNLOCK(pr);
3373 continue;
3374 }
3375 if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0) {
3376 pr->ndpr_stateflags &= ~NDPRF_DETACHED;
3377 }
3378 NDPR_UNLOCK(pr);
3379 }
3380 }
3381 /*
3382 * Instead of removing interface route for detached prefix,
3383 * keep the route and treat unreachability similar to the processing
3384 * of an RA that has just deprecated the prefix.
3385 * Keep around the detached flag just to be able to be able
3386 * to differentiate the scenario from explicit RA deprecation
3387 * of prefix.
3388 * Keep the logic to install the interface route for a (just) attached
3389 * prefix. Note that all attempt of reinstallation does not
3390 * necessarily success, when a same prefix is shared among multiple
3391 * interfaces. Such cases will be handled in nd6_prefix_onlink,
3392 * so we don't have to care about them.
3393 */
3394 pr = nd_prefix.lh_first;
3395 while (pr) {
3396 int error;
3397
3398 NDPR_LOCK(pr);
3399 if (pr->ndpr_raf_onlink == 0 ||
3400 pr->ndpr_stateflags & NDPRF_STATIC ||
3401 pr->ndpr_stateflags & NDPRF_PROCESSED_ONLINK ||
3402 pr->ndpr_stateflags & NDPRF_DEFUNCT) {
3403 NDPR_UNLOCK(pr);
3404 pr = pr->ndpr_next;
3405 continue;
3406 }
3407 pr->ndpr_stateflags |= NDPRF_PROCESSED_ONLINK;
3408 NDPR_ADDREF(pr);
3409 if (pr->ndpr_stateflags & NDPRF_DETACHED) {
3410 /*
3411 * When a prefix is detached, make it deprecated by setting pltime
3412 * to 0, and let it expire according to its advertised vltime.
3413 * If its original vltime is infinite or longer than 2hr,
3414 * set it to 2hr.
3415 */
3416 pr->ndpr_pltime = 0;
3417 uint32_t pr_remaining_lifetime;
3418 uint32_t original_lifetime = (uint32_t)(timenow - pr->ndpr_base_uptime);
3419 if (pr->ndpr_vltime > original_lifetime) {
3420 pr_remaining_lifetime = pr->ndpr_vltime - original_lifetime;
3421 } else {
3422 pr_remaining_lifetime = 0;
3423 }
3424 if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME ||
3425 pr_remaining_lifetime >= TWOHOUR) {
3426 pr->ndpr_vltime = TWOHOUR;
3427 } else {
3428 pr->ndpr_vltime = pr_remaining_lifetime;
3429 }
3430 in6_init_prefix_ltimes(pr);
3431 NDPR_UNLOCK(pr);
3432 } else if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
3433 (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 &&
3434 pr->ndpr_raf_onlink) {
3435 NDPR_UNLOCK(pr);
3436 if ((error = nd6_prefix_onlink(pr)) != 0) {
3437 nd6log0(error,
3438 "pfxlist_onlink_check: failed to "
3439 "make %s/%d offlink, errno=%d\n",
3440 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3441 pr->ndpr_plen, error);
3442 }
3443 NDPR_REMREF(pr);
3444 pr = nd_prefix.lh_first;
3445 continue;
3446 } else {
3447 NDPR_UNLOCK(pr);
3448 }
3449 NDPR_REMREF(pr);
3450 pr = pr->ndpr_next;
3451 }
3452 LIST_FOREACH(prclear, &nd_prefix, ndpr_entry) {
3453 NDPR_LOCK(prclear);
3454 prclear->ndpr_stateflags &= ~NDPRF_PROCESSED_ONLINK;
3455 NDPR_UNLOCK(prclear);
3456 }
3457
3458 if (!already_locked) {
3459 nd_prefix_busy_signal();
3460 }
3461
3462 /*
3463 * Changes on the prefix status might affect address status as well.
3464 * Make sure that all addresses derived from an attached prefix are
3465 * attached, and that all addresses derived from a detached prefix are
3466 * detached. Note, however, that a manually configured address should
3467 * always be attached.
3468 * The precise detection logic is same as the one for prefixes.
3469 *
3470 * ifnet_get_address_list_family_internal() may fail due to memory
3471 * pressure, but we will eventually be called again when we receive
3472 * another NA, RA, or when the link status changes.
3473 */
3474 err = ifnet_get_address_list_family_internal(NULL, &ifap, &addresses_count,
3475 AF_INET6, 0, M_NOWAIT, 0);
3476 if (err != 0 || ifap == NULL) {
3477 nd6log0(error, "%s: ifnet_get_address_list_family_internal "
3478 "failed. err=%d", __func__, err);
3479 return;
3480 }
3481 for (i = 0; ifap[i]; i++) {
3482 ifa = ifatoia6(ifap[i]);
3483 IFA_LOCK(&ifa->ia_ifa);
3484 if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0 ||
3485 (ifap[i]->ifa_debug & IFD_ATTACHED) == 0) {
3486 IFA_UNLOCK(&ifa->ia_ifa);
3487 continue;
3488 }
3489 if ((ndpr = ifa->ia6_ndpr) == NULL) {
3490 /*
3491 * This can happen when we first configure the address
3492 * (i.e. the address exists, but the prefix does not).
3493 * XXX: complicated relationships...
3494 */
3495 IFA_UNLOCK(&ifa->ia_ifa);
3496 continue;
3497 }
3498 IFA_UNLOCK(&ifa->ia_ifa);
3499
3500 NDPR_LOCK(ndpr);
3501 if (find_pfxlist_reachable_router(ndpr)) {
3502 NDPR_UNLOCK(ndpr);
3503 found = 1;
3504 break;
3505 }
3506 NDPR_UNLOCK(ndpr);
3507 }
3508 if (found) {
3509 for (i = 0; ifap[i]; i++) {
3510 struct in6_addrlifetime lt6_tmp = {};
3511
3512 ifa = ifatoia6(ifap[i]);
3513 IFA_LOCK(&ifa->ia_ifa);
3514 if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0 ||
3515 (ifap[i]->ifa_debug & IFD_ATTACHED) == 0) {
3516 IFA_UNLOCK(&ifa->ia_ifa);
3517 continue;
3518 }
3519 if ((ndpr = ifa->ia6_ndpr) == NULL) {
3520 /* XXX: see above. */
3521 IFA_UNLOCK(&ifa->ia_ifa);
3522 continue;
3523 }
3524 IFA_UNLOCK(&ifa->ia_ifa);
3525 NDPR_LOCK(ndpr);
3526 if (find_pfxlist_reachable_router(ndpr) == NULL) {
3527 /*
3528 * When the prefix of an addr is detached, make the address
3529 * deprecated by setting pltime to 0, and let it expire according
3530 * to its advertised vltime. If its original vltime is infinite
3531 * or longer than 2hr, set it to 2hr.
3532 */
3533 NDPR_UNLOCK(ndpr);
3534 IFA_LOCK(&ifa->ia_ifa);
3535 in6ifa_getlifetime(ifa, <6_tmp, 0);
3536 /* We want to immediately deprecate the address */
3537 lt6_tmp.ia6t_pltime = 0;
3538 /* Do not extend its valid lifetime */
3539 uint32_t remaining_lifetime;
3540 uint32_t original_lifetime = (uint32_t)(timenow - ifa->ia6_updatetime);
3541 if (lt6_tmp.ia6t_vltime > original_lifetime) {
3542 remaining_lifetime = lt6_tmp.ia6t_vltime - original_lifetime;
3543 } else {
3544 remaining_lifetime = 0;
3545 }
3546 if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME || remaining_lifetime >= TWOHOUR) {
3547 lt6_tmp.ia6t_vltime = TWOHOUR;
3548 } else {
3549 lt6_tmp.ia6t_vltime = remaining_lifetime;
3550 }
3551
3552 in6_init_address_ltimes(<6_tmp);
3553 in6ifa_setlifetime(ifa, <6_tmp);
3554 ifa->ia6_updatetime = timenow;
3555
3556 /*
3557 * The next nd6 service timer expiry will take
3558 * care of marking the addresses as deprecated
3559 * and issuing the notifications as well.
3560 */
3561 IFA_UNLOCK(&ifa->ia_ifa);
3562 } else {
3563 NDPR_UNLOCK(ndpr);
3564 }
3565 }
3566 }
3567 ifnet_address_list_free_counted_by(ifap, addresses_count);
3568 }
3569
3570 static struct nd_prefix *
nd6_prefix_equal_lookup(struct nd_prefix * pr,boolean_t primary_only)3571 nd6_prefix_equal_lookup(struct nd_prefix *pr, boolean_t primary_only)
3572 {
3573 struct nd_prefix *__single opr;
3574
3575 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
3576
3577 for (opr = nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
3578 if (opr == pr) {
3579 continue;
3580 }
3581
3582 NDPR_LOCK(opr);
3583 if ((opr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
3584 NDPR_UNLOCK(opr);
3585 continue;
3586 }
3587 if (opr->ndpr_plen == pr->ndpr_plen &&
3588 in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr, pr->ndpr_prefix.sin6_scope_id,
3589 &opr->ndpr_prefix.sin6_addr, opr->ndpr_prefix.sin6_scope_id, pr->ndpr_plen) &&
3590 (!primary_only ||
3591 !(opr->ndpr_stateflags & NDPRF_IFSCOPE))) {
3592 NDPR_ADDREF(opr);
3593 NDPR_UNLOCK(opr);
3594 return opr;
3595 }
3596 NDPR_UNLOCK(opr);
3597 }
3598 return NULL;
3599 }
3600
3601 /*
3602 * Synchronize the interface routes of similar prefixes on different
3603 * interfaces; the one using the default interface would be (re)installed
3604 * as a primary/non-scoped entry, and the rest as scoped entri(es).
3605 */
3606 static void
nd6_prefix_sync(struct ifnet * ifp)3607 nd6_prefix_sync(struct ifnet *ifp)
3608 {
3609 struct nd_prefix *__single pr, *__single opr;
3610 int err = 0;
3611 uint64_t timenow;
3612
3613 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
3614
3615 if (ifp == NULL) {
3616 return;
3617 }
3618
3619
3620 net_update_uptime();
3621 timenow = net_uptime();
3622
3623 LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
3624 NDPR_LOCK(pr);
3625 if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
3626 NDPR_UNLOCK(pr);
3627 continue;
3628 }
3629 if (pr->ndpr_expire != 0 && pr->ndpr_expire < timenow) {
3630 NDPR_UNLOCK(pr);
3631 continue;
3632 }
3633 if (pr->ndpr_ifp == ifp &&
3634 (pr->ndpr_stateflags & NDPRF_IFSCOPE) &&
3635 !IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) {
3636 NDPR_UNLOCK(pr);
3637 break;
3638 }
3639 NDPR_UNLOCK(pr);
3640 }
3641
3642 if (pr == NULL) {
3643 return;
3644 }
3645
3646 /* Remove conflicting entries */
3647 opr = nd6_prefix_equal_lookup(pr, TRUE);
3648 if (opr != NULL) {
3649 lck_mtx_unlock(nd6_mutex);
3650 err = nd6_prefix_offlink(opr);
3651 lck_mtx_lock(nd6_mutex);
3652 if (err != 0) {
3653 nd6log0(error,
3654 "%s: failed to make %s/%d offlink on %s, "
3655 "errno=%d\n", __func__,
3656 ip6_sprintf(&opr->ndpr_prefix.sin6_addr),
3657 opr->ndpr_plen, if_name(opr->ndpr_ifp), err);
3658 }
3659 } else {
3660 nd6log0(error,
3661 "%s: scoped %s/%d on %s has no matching unscoped prefix\n",
3662 __func__, ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3663 pr->ndpr_plen, if_name(pr->ndpr_ifp));
3664 }
3665
3666 lck_mtx_unlock(nd6_mutex);
3667 err = nd6_prefix_offlink(pr);
3668 lck_mtx_lock(nd6_mutex);
3669 if (err != 0) {
3670 nd6log0(error,
3671 "%s: failed to make %s/%d offlink on %s, errno=%d\n",
3672 __func__, ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3673 pr->ndpr_plen, if_name(pr->ndpr_ifp), err);
3674 }
3675
3676 /* Add the entries back */
3677 if (opr != NULL) {
3678 err = nd6_prefix_onlink_scoped(opr, opr->ndpr_ifp->if_index);
3679 if (err != 0) {
3680 nd6log0(error,
3681 "%s: failed to make %s/%d scoped onlink on %s, "
3682 "errno=%d\n", __func__,
3683 ip6_sprintf(&opr->ndpr_prefix.sin6_addr),
3684 opr->ndpr_plen, if_name(opr->ndpr_ifp), err);
3685 }
3686 }
3687
3688 err = nd6_prefix_onlink_scoped(pr, IFSCOPE_NONE);
3689 if (err != 0) {
3690 nd6log0(error,
3691 "%s: failed to make %s/%d onlink on %s, errno=%d\n",
3692 __func__, ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3693 pr->ndpr_plen, if_name(pr->ndpr_ifp), err);
3694 }
3695
3696 if (err != 0) {
3697 nd6log0(error,
3698 "%s: error promoting %s/%d to %s from %s\n",
3699 __func__, ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3700 pr->ndpr_plen, if_name(pr->ndpr_ifp),
3701 (opr != NULL) ? if_name(opr->ndpr_ifp) : "NONE");
3702 } else {
3703 nd6log2(info,
3704 "%s: %s/%d promoted, previously on %s\n",
3705 if_name(pr->ndpr_ifp),
3706 ip6_sprintf(&pr->ndpr_prefix.sin6_addr), pr->ndpr_plen,
3707 (opr != NULL) ? if_name(opr->ndpr_ifp) : "NONE");
3708 }
3709
3710 if (opr != NULL) {
3711 NDPR_REMREF(opr);
3712 }
3713 }
3714
3715 static int
nd6_prefix_onlink_common(struct nd_prefix * pr,boolean_t force_scoped,unsigned int ifscope)3716 nd6_prefix_onlink_common(struct nd_prefix *pr, boolean_t force_scoped,
3717 unsigned int ifscope)
3718 {
3719 struct ifaddr *__single ifa;
3720 ifnet_ref_t ifp = pr->ndpr_ifp;
3721 struct sockaddr_in6 mask6, prefix;
3722 struct nd_prefix *__single opr;
3723 u_int32_t rtflags;
3724 int error = 0, prproxy = 0;
3725 rtentry_ref_t rt = NULL;
3726 u_char prefix_len = 0;
3727
3728 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_OWNED);
3729
3730 /* sanity check */
3731 NDPR_LOCK(pr);
3732 if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
3733 nd6log0(error,
3734 "%s: %s/%d on %s scoped=%d is already on-link\n",
3735 __func__, ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3736 pr->ndpr_plen, if_name(pr->ndpr_ifp),
3737 (pr->ndpr_stateflags & NDPRF_IFSCOPE) ? 1 : 0);
3738 NDPR_UNLOCK(pr);
3739 return EEXIST;
3740 }
3741 NDPR_UNLOCK(pr);
3742
3743 /*
3744 * Add the interface route associated with the prefix. Before
3745 * installing the route, check if there's the same prefix on another
3746 * interface, and the prefix has already installed the interface route.
3747 */
3748 opr = nd6_prefix_equal_lookup(pr, FALSE);
3749 if (opr != NULL) {
3750 NDPR_REMREF(opr);
3751 }
3752
3753 if (!force_scoped) {
3754 /*
3755 * If a primary/non-scoped interface route already exists,
3756 * install the new one as a scoped entry. If the existing
3757 * interface route is scoped, install new as non-scoped.
3758 */
3759 ifscope = (opr != NULL) ? ifp->if_index : IFSCOPE_NONE;
3760 opr = nd6_prefix_equal_lookup(pr, TRUE);
3761 if (opr != NULL) {
3762 NDPR_REMREF(opr);
3763 } else if (ifscope != IFSCOPE_NONE) {
3764 ifscope = IFSCOPE_NONE;
3765 }
3766 }
3767
3768 /*
3769 * We prefer link-local addresses as the associated interface address.
3770 */
3771 /* search for a link-local addr */
3772 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
3773 IN6_IFF_NOTREADY | IN6_IFF_ANYCAST);
3774 if (ifa == NULL) {
3775 struct in6_ifaddr *__single ia6;
3776 ifnet_lock_shared(ifp);
3777 IFP_TO_IA6(ifp, ia6);
3778 ifnet_lock_done(ifp);
3779 if (ia6 != NULL) {
3780 ifa = &ia6->ia_ifa;
3781 }
3782 /* should we care about ia6_flags? */
3783 }
3784 NDPR_LOCK(pr);
3785 if (ifa == NULL) {
3786 /*
3787 * This can still happen, when, for example, we receive an RA
3788 * containing a prefix with the L bit set and the A bit clear,
3789 * after removing all IPv6 addresses on the receiving
3790 * interface. This should, of course, be rare though.
3791 */
3792 nd6log(info,
3793 "nd6_prefix_onlink: failed to find any ifaddr"
3794 " to add route for a prefix(%s/%d) on %s\n",
3795 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3796 pr->ndpr_plen, if_name(ifp));
3797 NDPR_UNLOCK(pr);
3798 return 0;
3799 }
3800
3801 /*
3802 * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
3803 * ifa->ifa_rtrequest = nd6_rtrequest;
3804 */
3805 SOCKADDR_ZERO(&mask6, sizeof(mask6));
3806 mask6.sin6_len = sizeof(mask6);
3807 mask6.sin6_addr = pr->ndpr_mask;
3808 prefix = pr->ndpr_prefix;
3809 prefix_len = pr->ndpr_plen;
3810 if ((rt = pr->ndpr_rt) != NULL) {
3811 pr->ndpr_rt = NULL;
3812 }
3813 NDPR_ADDREF(pr); /* keep reference for this routine */
3814 NDPR_UNLOCK(pr);
3815
3816 IFA_LOCK_SPIN(ifa);
3817 rtflags = ifa->ifa_flags | RTF_CLONING | RTF_UP;
3818 IFA_UNLOCK(ifa);
3819 if (nd6_need_cache(ifp)) {
3820 /* explicitly set in case ifa_flags does not set the flag. */
3821 rtflags |= RTF_CLONING;
3822 } else {
3823 /*
3824 * explicitly clear the cloning bit in case ifa_flags sets it.
3825 */
3826 rtflags &= ~RTF_CLONING;
3827 }
3828
3829 lck_mtx_unlock(nd6_mutex);
3830
3831 /*
3832 * check if it conflicts with a indirect prefix route added by RIO
3833 * if so, remove the rti entry.
3834 */
3835 if (ifscope == IFSCOPE_NONE) {
3836 rtentry_ref_t temp_route = NULL;
3837 LCK_MTX_ASSERT(rnh_lock, LCK_MTX_ASSERT_NOTOWNED);
3838 lck_mtx_lock(rnh_lock);
3839 temp_route = rt_lookup(TRUE, SA(&prefix), SA(&mask6), rt_tables[AF_INET6], IFSCOPE_NONE);
3840 lck_mtx_unlock(rnh_lock);
3841
3842 if (temp_route != NULL && temp_route->rt_flags & RTF_GATEWAY && temp_route->rt_ifp != NULL) {
3843 struct nd_route_info rti = {};
3844 bzero(&rti, sizeof(rti));
3845 rti.nd_rti_prefixlen = prefix_len;
3846 rti.nd_rti_prefix = prefix.sin6_addr;
3847 lck_mtx_lock(nd6_mutex);
3848 nd6_rti_delreq(&rti);
3849 lck_mtx_unlock(nd6_mutex);
3850 }
3851 if (temp_route != NULL) {
3852 rtfree(temp_route);
3853 }
3854 }
3855
3856 if (rt != NULL) {
3857 rtfree(rt);
3858 rt = NULL;
3859 }
3860
3861 error = rtrequest_scoped(RTM_ADD, SA(&prefix), ifa->ifa_addr, SA(&mask6),
3862 rtflags, &rt, ifscope);
3863
3864 /*
3865 * Serialize the setting of NDPRF_PRPROXY.
3866 */
3867 lck_mtx_lock(&proxy6_lock);
3868
3869 if (rt != NULL) {
3870 RT_LOCK(rt);
3871 nd6_rtmsg(RTM_ADD, rt);
3872 RT_UNLOCK(rt);
3873 NDPR_LOCK(pr);
3874 } else {
3875 NDPR_LOCK(pr);
3876 nd6log0(error, "nd6_prefix_onlink: failed to add route for a"
3877 " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%x,"
3878 " scoped=%d, errno = %d\n",
3879 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3880 pr->ndpr_plen, if_name(ifp),
3881 ip6_sprintf(&SIN6(ifa->ifa_addr)->sin6_addr),
3882 ip6_sprintf(&mask6.sin6_addr), rtflags,
3883 (ifscope != IFSCOPE_NONE), error);
3884 }
3885 NDPR_LOCK_ASSERT_HELD(pr);
3886
3887 pr->ndpr_stateflags &= ~(NDPRF_IFSCOPE | NDPRF_PRPROXY);
3888
3889 /*
3890 * TODO: If the prefix route exists, we should really find it and
3891 * refer the prefix to it; otherwise ndpr_rt is NULL.
3892 */
3893 if (!(pr->ndpr_stateflags & NDPRF_DEFUNCT) &&
3894 (rt != NULL || error == EEXIST)) {
3895 struct nd_ifinfo *__single ndi = NULL;
3896
3897 VERIFY(pr->ndpr_prproxy_sols_cnt == 0);
3898 VERIFY(RB_EMPTY(&pr->ndpr_prproxy_sols));
3899
3900 ndi = ND_IFINFO(ifp);
3901 VERIFY((NULL != ndi) && (TRUE == ndi->initialized));
3902 lck_mtx_lock(&ndi->lock);
3903
3904 pr->ndpr_rt = rt; /* keep reference from rtrequest */
3905 pr->ndpr_stateflags |= NDPRF_ONLINK;
3906 if (ifscope != IFSCOPE_NONE) {
3907 pr->ndpr_stateflags |= NDPRF_IFSCOPE;
3908 } else if ((rtflags & RTF_CLONING) &&
3909 (ndi->flags & ND6_IFF_PROXY_PREFIXES) &&
3910 !IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) {
3911 /*
3912 * At present, in order for the prefix to be eligible
3913 * as a proxying/proxied prefix, we require that the
3914 * prefix route entry be marked as a cloning route with
3915 * RTF_PROXY; i.e. nd6_need_cache() needs to return
3916 * true for the interface type, hence the test for
3917 * RTF_CLONING above.
3918 */
3919 pr->ndpr_stateflags |= NDPRF_PRPROXY;
3920 }
3921
3922 lck_mtx_unlock(&ndi->lock);
3923 } else if (rt != NULL && pr->ndpr_stateflags & NDPRF_DEFUNCT) {
3924 rtfree(rt);
3925 }
3926
3927 prproxy = (pr->ndpr_stateflags & NDPRF_PRPROXY);
3928 VERIFY(!prproxy || !(pr->ndpr_stateflags & NDPRF_IFSCOPE));
3929 NDPR_UNLOCK(pr);
3930
3931 ifa_remref(ifa);
3932
3933 /*
3934 * If this is an upstream prefix, find the downstream ones (if any)
3935 * and re-configure their prefix routes accordingly. Otherwise,
3936 * this could be potentially be a downstream prefix, and so find the
3937 * upstream prefix, if any.
3938 */
3939 nd6_prproxy_prelist_update(pr, prproxy ? pr : NULL);
3940
3941 NDPR_REMREF(pr); /* release reference for this routine */
3942 lck_mtx_unlock(&proxy6_lock);
3943
3944 lck_mtx_lock(nd6_mutex);
3945
3946 return error;
3947 }
3948
3949 int
nd6_prefix_onlink(struct nd_prefix * pr)3950 nd6_prefix_onlink(struct nd_prefix *pr)
3951 {
3952 return nd6_prefix_onlink_common(pr, FALSE, IFSCOPE_NONE);
3953 }
3954
3955 int
nd6_prefix_onlink_scoped(struct nd_prefix * pr,unsigned int ifscope)3956 nd6_prefix_onlink_scoped(struct nd_prefix *pr, unsigned int ifscope)
3957 {
3958 return nd6_prefix_onlink_common(pr, TRUE, ifscope);
3959 }
3960
3961 int
nd6_prefix_offlink(struct nd_prefix * pr)3962 nd6_prefix_offlink(struct nd_prefix *pr)
3963 {
3964 int error = 0, prproxy;
3965 ifnet_ref_t ifp = pr->ndpr_ifp;
3966 struct sockaddr_in6 sa6, mask6, prefix;
3967 rtentry_ref_t rt = NULL, ndpr_rt = NULL;
3968 unsigned int ifscope;
3969 u_char prefix_len = 0;
3970
3971 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
3972
3973 /* sanity check */
3974 NDPR_LOCK(pr);
3975 if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
3976 nd6log0(error,
3977 "nd6_prefix_offlink: %s/%d on %s scoped=%d is already "
3978 "off-link\n", ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3979 pr->ndpr_plen, if_name(pr->ndpr_ifp),
3980 (pr->ndpr_stateflags & NDPRF_IFSCOPE) ? 1 : 0);
3981 NDPR_UNLOCK(pr);
3982 return EEXIST;
3983 }
3984
3985 SOCKADDR_ZERO(&sa6, sizeof(sa6));
3986 sa6.sin6_family = AF_INET6;
3987 sa6.sin6_len = sizeof(sa6);
3988 bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr,
3989 sizeof(struct in6_addr));
3990 SOCKADDR_ZERO(&mask6, sizeof(mask6));
3991 mask6.sin6_family = AF_INET6;
3992 mask6.sin6_len = sizeof(sa6);
3993 bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr));
3994 prefix = pr->ndpr_prefix;
3995 prefix_len = pr->ndpr_plen;
3996 if ((ndpr_rt = pr->ndpr_rt) != NULL) {
3997 pr->ndpr_rt = NULL;
3998 }
3999 NDPR_ADDREF(pr); /* keep reference for this routine */
4000 NDPR_UNLOCK(pr);
4001
4002 ifscope = (pr->ndpr_stateflags & NDPRF_IFSCOPE) ?
4003 ifp->if_index : IFSCOPE_NONE;
4004
4005 error = rtrequest_scoped(RTM_DELETE, SA(&sa6), NULL, SA(&mask6),
4006 0, &rt, ifscope);
4007
4008 if (rt != NULL) {
4009 /* report the route deletion to the routing socket. */
4010 RT_LOCK(rt);
4011 nd6_rtmsg(RTM_DELETE, rt);
4012 RT_UNLOCK(rt);
4013 rtfree(rt);
4014 } else {
4015 nd6log0(error,
4016 "nd6_prefix_offlink: failed to delete route: "
4017 "%s/%d on %s, scoped %d, (errno = %d)\n",
4018 ip6_sprintf(&sa6.sin6_addr), prefix_len, if_name(ifp),
4019 (ifscope != IFSCOPE_NONE), error);
4020 }
4021
4022 struct nd_route_info rti = {};
4023 bzero(&rti, sizeof(rti));
4024 rti.nd_rti_prefixlen = prefix_len;
4025 rti.nd_rti_prefix = prefix.sin6_addr;
4026
4027 lck_mtx_lock(nd6_mutex);
4028 nd6_rti_select(&rti, ifp);
4029 lck_mtx_unlock(nd6_mutex);
4030
4031 if (ndpr_rt != NULL) {
4032 rtfree(ndpr_rt);
4033 }
4034
4035 lck_mtx_lock(&proxy6_lock);
4036
4037 NDPR_LOCK(pr);
4038 prproxy = (pr->ndpr_stateflags & NDPRF_PRPROXY);
4039 VERIFY(!prproxy || !(pr->ndpr_stateflags & NDPRF_IFSCOPE));
4040 pr->ndpr_stateflags &= ~(NDPRF_ONLINK | NDPRF_IFSCOPE | NDPRF_PRPROXY);
4041 if (pr->ndpr_prproxy_sols_cnt > 0) {
4042 VERIFY(prproxy);
4043 nd6_prproxy_sols_reap(pr);
4044 VERIFY(pr->ndpr_prproxy_sols_cnt == 0);
4045 VERIFY(RB_EMPTY(&pr->ndpr_prproxy_sols));
4046 }
4047 NDPR_UNLOCK(pr);
4048
4049 /*
4050 * If this was an upstream prefix, find the downstream ones and do
4051 * some cleanups. If this was a downstream prefix, the prefix route
4052 * has been removed from the routing table above, but there may be
4053 * other tasks to perform.
4054 */
4055 nd6_prproxy_prelist_update(pr, prproxy ? pr : NULL);
4056
4057 NDPR_REMREF(pr); /* release reference for this routine */
4058 lck_mtx_unlock(&proxy6_lock);
4059
4060 return error;
4061 }
4062
4063 struct in6_ifaddr *
in6_pfx_newpersistaddr(struct nd_prefix * pr,int mcast,int * errorp,boolean_t is_clat46,uint8_t collision_count)4064 in6_pfx_newpersistaddr(struct nd_prefix *pr, int mcast, int *errorp,
4065 boolean_t is_clat46, uint8_t collision_count)
4066 {
4067 struct in6_ifaddr *__single ia6 = NULL;
4068 ifnet_ref_t ifp = NULL;
4069 struct nd_ifinfo *__single ndi = NULL;
4070 struct in6_addr mask;
4071 struct in6_aliasreq ifra;
4072 int error, ifaupdate, iidlen, notcga;
4073
4074 VERIFY(pr != NULL);
4075 VERIFY(errorp != NULL);
4076
4077 NDPR_LOCK(pr);
4078 ifp = pr->ndpr_ifp;
4079 ia6 = NULL;
4080 error = 0;
4081
4082 /*
4083 * Prefix Length check:
4084 * If the sum of the prefix length and interface identifier
4085 * length does not equal 128 bits, the Prefix Information
4086 * option MUST be ignored. The length of the interface
4087 * identifier is defined in a separate link-type specific
4088 * document.
4089 */
4090 iidlen = in6_if2idlen(ifp);
4091 if (iidlen < 0) {
4092 error = EADDRNOTAVAIL;
4093 /* this should not happen, so we always log it. */
4094 log(LOG_ERR, "%s: IID length undefined (%s)\n",
4095 __func__, if_name(ifp));
4096 goto unlock1;
4097 } else if (iidlen != 64) {
4098 error = EADDRNOTAVAIL;
4099 /*
4100 * stateless autoconfiguration not yet well-defined for IID
4101 * lengths other than 64 octets. Just give up for now.
4102 */
4103 nd6log(info, "%s: IID length not 64 octets (%s)\n",
4104 __func__, if_name(ifp));
4105 goto unlock1;
4106 }
4107
4108 if (iidlen + pr->ndpr_plen != 128) {
4109 error = EADDRNOTAVAIL;
4110 nd6log(info,
4111 "%s: invalid prefix length %d for %s, ignored\n",
4112 __func__, pr->ndpr_plen, if_name(ifp));
4113 goto unlock1;
4114 }
4115
4116 bzero(&ifra, sizeof(ifra));
4117 strlcpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
4118 ifra.ifra_addr.sin6_family = AF_INET6;
4119 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
4120
4121 /* prefix */
4122 bcopy(&pr->ndpr_prefix.sin6_addr, &ifra.ifra_addr.sin6_addr,
4123 sizeof(ifra.ifra_addr.sin6_addr));
4124 in6_len2mask(&mask, pr->ndpr_plen);
4125 ifra.ifra_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
4126 ifra.ifra_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
4127 ifra.ifra_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
4128 ifra.ifra_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
4129
4130 ndi = ND_IFINFO(ifp);
4131 VERIFY(ndi->initialized);
4132 lck_mtx_lock(&ndi->lock);
4133
4134 notcga = nd6_send_opstate == ND6_SEND_OPMODE_DISABLED ||
4135 (ndi->flags & ND6_IFF_INSECURE) != 0;
4136
4137 lck_mtx_unlock(&ndi->lock);
4138 NDPR_UNLOCK(pr);
4139
4140 if (notcga && !is_clat46) {
4141 ia6 = in6ifa_ifpforlinklocal(ifp, 0);
4142 if (ia6 == NULL) {
4143 error = EADDRNOTAVAIL;
4144 nd6log(info, "%s: no link-local address (%s)\n",
4145 __func__, if_name(ifp));
4146 goto done;
4147 }
4148
4149 IFA_LOCK(&ia6->ia_ifa);
4150 ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
4151 (ia6->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
4152 ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
4153 (ia6->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
4154 ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
4155 (ia6->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
4156 ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
4157 (ia6->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
4158 IFA_UNLOCK(&ia6->ia_ifa);
4159 ifa_remref(&ia6->ia_ifa);
4160 ia6 = NULL;
4161 } else {
4162 struct in6_cga_prepare local_cga_prepare;
4163 struct in6_cga_prepare *__single prepare_p;
4164
4165
4166 in6_cga_node_lock();
4167
4168 if (ndi->cga_initialized) {
4169 bcopy(&(ndi->local_cga_modifier),
4170 &(local_cga_prepare.cga_modifier),
4171 sizeof(local_cga_prepare.cga_modifier));
4172 prepare_p = &local_cga_prepare;
4173 } else {
4174 prepare_p = NULL;
4175 }
4176 error = in6_cga_generate(prepare_p, collision_count,
4177 &ifra.ifra_addr.sin6_addr, ifp);
4178 in6_cga_node_unlock();
4179 if (error == 0) {
4180 ifra.ifra_flags |= IN6_IFF_SECURED;
4181 if (is_clat46) {
4182 ifra.ifra_flags |= IN6_IFF_CLAT46;
4183 }
4184 } else {
4185 if (!is_clat46) {
4186 nd6log0(error, "%s: no CGA available (%s) err=%d\n",
4187 __func__, if_name(ifp), error);
4188 } else {
4189 nd6log0(error, "%s: no CLAT46 available (%s) err=%d\n",
4190 __func__, if_name(ifp), error);
4191 }
4192 goto done;
4193 }
4194 }
4195
4196 VERIFY(ia6 == NULL);
4197
4198 /* new prefix mask. */
4199 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
4200 ifra.ifra_prefixmask.sin6_family = AF_INET6;
4201 bcopy(&mask, &ifra.ifra_prefixmask.sin6_addr,
4202 sizeof(ifra.ifra_prefixmask.sin6_addr));
4203
4204 /* lifetimes. */
4205 ifra.ifra_lifetime.ia6t_vltime = pr->ndpr_vltime;
4206 ifra.ifra_lifetime.ia6t_pltime = pr->ndpr_pltime;
4207
4208 /* address flags */
4209 ifra.ifra_flags |= IN6_IFF_AUTOCONF; /* obey autoconf */
4210
4211 /*
4212 * Make sure that we do not have this address already. This should
4213 * usually not happen, but we can still see this case, e.g., if we
4214 * have manually configured the exact address to be configured.
4215 */
4216 if ((ia6 = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr))
4217 != NULL) {
4218 error = EEXIST;
4219 ifa_remref(&ia6->ia_ifa);
4220 ia6 = NULL;
4221
4222 /* this should be rare enough to make an explicit log */
4223 log(LOG_INFO, "%s: %s is already configured!\n",
4224 __func__, ip6_sprintf(&ifra.ifra_addr.sin6_addr));
4225 goto done;
4226 }
4227
4228 /*
4229 * Allocate ifaddr structure, link into chain, etc.
4230 * If we are going to create a new address upon receiving a multicasted
4231 * RA, we need to impose a random delay before starting DAD.
4232 * [RFC 4862, Section 5.4.2]
4233 */
4234 ifaupdate = IN6_IFAUPDATE_NOWAIT;
4235 if (mcast) {
4236 ifaupdate |= IN6_IFAUPDATE_DADDELAY;
4237 }
4238 error = in6_update_ifa(ifp, &ifra, ifaupdate, &ia6);
4239 if (error != 0) {
4240 nd6log0(error,
4241 "%s: failed to make ifaddr %s on %s (errno=%d)\n",
4242 __func__, ip6_sprintf(&ifra.ifra_addr.sin6_addr),
4243 if_name(ifp), error);
4244 error = EADDRNOTAVAIL;
4245 goto done;
4246 } else {
4247 /* remember the collision count */
4248 ia6->ia6_cga_collision_count = collision_count;
4249 }
4250
4251 VERIFY(ia6 != NULL);
4252 in6_post_msg(ifp, KEV_INET6_NEW_RTADV_ADDR, ia6, NULL, 0);
4253 goto done;
4254
4255 unlock1:
4256 NDPR_UNLOCK(pr);
4257
4258 done:
4259 *errorp = error;
4260 return ia6;
4261 }
4262
4263 #define IA6_NONCONST(ifa) __DECONST(struct in6_ifaddr *, (ifa))
4264
4265 int
in6_tmpifadd(const struct in6_ifaddr * ia0,int forcegen)4266 in6_tmpifadd(const struct in6_ifaddr *ia0, int forcegen)
4267 {
4268 ifnet_ref_t ifp = ia0->ia_ifa.ifa_ifp;
4269 struct in6_ifaddr *__single ia, *__single newia;
4270 struct in6_aliasreq ifra;
4271 int i, error, ifaupdate;
4272 int trylimit = 3; /* XXX: adhoc value */
4273 u_int32_t randid[2];
4274 uint32_t vltime0, pltime0;
4275 uint64_t timenow = net_uptime();
4276 struct in6_addr addr;
4277 struct nd_prefix *__single ndpr;
4278
4279 bzero(&ifra, sizeof(ifra));
4280 strlcpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
4281 IFA_LOCK(&IA6_NONCONST(ia0)->ia_ifa);
4282 ifra.ifra_addr = ia0->ia_addr;
4283 /* copy prefix mask */
4284 ifra.ifra_prefixmask = ia0->ia_prefixmask;
4285 /* clear the old IFID */
4286 for (i = 0; i < 4; i++) {
4287 ifra.ifra_addr.sin6_addr.s6_addr32[i]
4288 &= ifra.ifra_prefixmask.sin6_addr.s6_addr32[i];
4289 }
4290 addr = ia0->ia_addr.sin6_addr;
4291 IFA_UNLOCK(&IA6_NONCONST(ia0)->ia_ifa);
4292
4293 again:
4294 in6_iid_mktmp(ifp, (u_int8_t *)randid,
4295 (const u_int8_t *)&addr.s6_addr[8], forcegen);
4296
4297 ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
4298 (randid[0] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[2]));
4299 ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
4300 (randid[1] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[3]));
4301
4302 /*
4303 * in6_iid_mktmp() quite likely provided a unique interface ID.
4304 * However, we may still have a chance to see collision, because
4305 * there may be a time lag between generation of the ID and generation
4306 * of the address. So, we'll do one more sanity check.
4307 */
4308 if ((ia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr)) != NULL) {
4309 ifa_remref(&ia->ia_ifa);
4310 if (trylimit-- == 0) {
4311 nd6log(info, "in6_tmpifadd: failed to find "
4312 "a unique random IFID\n");
4313 return EEXIST;
4314 }
4315 forcegen = 1;
4316 goto again;
4317 }
4318
4319 /*
4320 * The Valid Lifetime is the lower of the Valid Lifetime of the
4321 * public address or TEMP_VALID_LIFETIME.
4322 * The Preferred Lifetime is the lower of the Preferred Lifetime
4323 * of the public address or TEMP_PREFERRED_LIFETIME -
4324 * DESYNC_FACTOR.
4325 */
4326 IFA_LOCK(&IA6_NONCONST(ia0)->ia_ifa);
4327 if (ia0->ia6_lifetime.ia6ti_vltime != ND6_INFINITE_LIFETIME) {
4328 vltime0 = IFA6_IS_INVALID(ia0, timenow) ? 0 :
4329 (ia0->ia6_lifetime.ia6ti_vltime -
4330 (uint32_t)(timenow - ia0->ia6_updatetime));
4331 if (vltime0 > ip6_temp_valid_lifetime) {
4332 vltime0 = ip6_temp_valid_lifetime;
4333 }
4334 } else {
4335 vltime0 = ip6_temp_valid_lifetime;
4336 }
4337 if (ia0->ia6_lifetime.ia6ti_pltime != ND6_INFINITE_LIFETIME) {
4338 pltime0 = IFA6_IS_DEPRECATED(ia0, timenow) ? 0 :
4339 (ia0->ia6_lifetime.ia6ti_pltime -
4340 (uint32_t)(timenow - ia0->ia6_updatetime));
4341 if (pltime0 > ip6_temp_preferred_lifetime - ip6_desync_factor) {
4342 pltime0 = ip6_temp_preferred_lifetime -
4343 ip6_desync_factor;
4344 }
4345 } else {
4346 pltime0 = ip6_temp_preferred_lifetime - ip6_desync_factor;
4347 }
4348 ifra.ifra_lifetime.ia6t_vltime = vltime0;
4349 ifra.ifra_lifetime.ia6t_pltime = pltime0;
4350 IFA_UNLOCK(&IA6_NONCONST(ia0)->ia_ifa);
4351 /*
4352 * A temporary address is created only if this calculated Preferred
4353 * Lifetime is greater than REGEN_ADVANCE time units.
4354 */
4355 if (ifra.ifra_lifetime.ia6t_pltime <= ip6_temp_regen_advance) {
4356 return 0;
4357 }
4358
4359 /* XXX: scope zone ID? */
4360
4361 ifra.ifra_flags |= (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY);
4362
4363 /* allocate ifaddr structure, link into chain, etc. */
4364 ifaupdate = IN6_IFAUPDATE_NOWAIT | IN6_IFAUPDATE_DADDELAY;
4365 error = in6_update_ifa(ifp, &ifra, ifaupdate, &newia);
4366 if (error != 0) {
4367 nd6log0(error, "%s: failed to add address. err=%d\n",
4368 __func__, error);
4369 return error;
4370 }
4371 VERIFY(newia != NULL);
4372
4373 IFA_LOCK(&IA6_NONCONST(ia0)->ia_ifa);
4374 ndpr = ia0->ia6_ndpr;
4375 if (ndpr == NULL) {
4376 /*
4377 * We lost the race with another thread that has purged
4378 * ia0 address; in this case, purge the tmp addr as well.
4379 */
4380 nd6log0(error, "in6_tmpifadd: no public address\n");
4381 VERIFY(!(ia0->ia6_flags & IN6_IFF_AUTOCONF));
4382 IFA_UNLOCK(&IA6_NONCONST(ia0)->ia_ifa);
4383 in6_purgeaddr(&newia->ia_ifa);
4384 ifa_remref(&newia->ia_ifa);
4385 return EADDRNOTAVAIL;
4386 }
4387 NDPR_ADDREF(ndpr); /* for us */
4388 IFA_UNLOCK(&IA6_NONCONST(ia0)->ia_ifa);
4389 IFA_LOCK(&newia->ia_ifa);
4390 if (newia->ia6_ndpr != NULL) {
4391 NDPR_LOCK(newia->ia6_ndpr);
4392 VERIFY(newia->ia6_ndpr->ndpr_addrcnt != 0);
4393 newia->ia6_ndpr->ndpr_addrcnt--;
4394 NDPR_UNLOCK(newia->ia6_ndpr);
4395 NDPR_REMREF(newia->ia6_ndpr); /* release addr reference */
4396 }
4397 newia->ia6_ndpr = ndpr;
4398 NDPR_LOCK(newia->ia6_ndpr);
4399 newia->ia6_ndpr->ndpr_addrcnt++;
4400 VERIFY(newia->ia6_ndpr->ndpr_addrcnt != 0);
4401 NDPR_ADDREF(newia->ia6_ndpr); /* for addr reference */
4402 NDPR_UNLOCK(newia->ia6_ndpr);
4403 IFA_UNLOCK(&newia->ia_ifa);
4404 /*
4405 * A newly added address might affect the status of other addresses.
4406 * XXX: when the temporary address is generated with a new public
4407 * address, the onlink check is redundant. However, it would be safe
4408 * to do the check explicitly everywhere a new address is generated,
4409 * and, in fact, we surely need the check when we create a new
4410 * temporary address due to deprecation of an old temporary address.
4411 */
4412 lck_mtx_lock(nd6_mutex);
4413 pfxlist_onlink_check(false);
4414 lck_mtx_unlock(nd6_mutex);
4415 ifa_remref(&newia->ia_ifa);
4416
4417 /* remove our reference */
4418 NDPR_REMREF(ndpr);
4419
4420 return 0;
4421 }
4422 #undef IA6_NONCONST
4423
4424 int
in6_init_prefix_ltimes(struct nd_prefix * ndpr)4425 in6_init_prefix_ltimes(struct nd_prefix *ndpr)
4426 {
4427 struct timeval caltime;
4428 u_int64_t timenow = net_uptime();
4429
4430 NDPR_LOCK_ASSERT_HELD(ndpr);
4431
4432 getmicrotime(&caltime);
4433 ndpr->ndpr_base_calendartime = caltime.tv_sec;
4434 ndpr->ndpr_base_uptime = timenow;
4435
4436 /* check if preferred lifetime > valid lifetime. RFC 4862 5.5.3 (c) */
4437 if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) {
4438 nd6log(info, "in6_init_prefix_ltimes: preferred lifetime"
4439 "(%d) is greater than valid lifetime(%d)\n",
4440 (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime);
4441 return EINVAL;
4442 }
4443 if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME) {
4444 ndpr->ndpr_preferred = 0;
4445 } else {
4446 ndpr->ndpr_preferred = timenow + ndpr->ndpr_pltime;
4447 }
4448 if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME) {
4449 ndpr->ndpr_expire = 0;
4450 } else {
4451 ndpr->ndpr_expire = timenow + ndpr->ndpr_vltime;
4452 }
4453
4454 return 0;
4455 }
4456
4457 static void
in6_init_address_ltimes(struct in6_addrlifetime * lt6)4458 in6_init_address_ltimes(struct in6_addrlifetime *lt6)
4459 {
4460 uint64_t timenow = net_uptime();
4461
4462 /* Valid lifetime must not be updated unless explicitly specified. */
4463 /* init ia6t_expire */
4464 if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME) {
4465 lt6->ia6t_expire = 0;
4466 } else {
4467 lt6->ia6t_expire = timenow;
4468 lt6->ia6t_expire += lt6->ia6t_vltime;
4469 }
4470
4471 /* init ia6t_preferred */
4472 if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME) {
4473 lt6->ia6t_preferred = 0;
4474 } else {
4475 lt6->ia6t_preferred = timenow;
4476 lt6->ia6t_preferred += lt6->ia6t_pltime;
4477 }
4478 }
4479
4480 /*
4481 * Delete all the routing table entries that use the specified gateway.
4482 * XXX: this function causes search through all entries of routing table, so
4483 * it shouldn't be called when acting as a router.
4484 *
4485 * This should really be working on entries that have a specific
4486 * parent route.
4487 */
4488 void
rt6_flush(struct in6_addr * gateway,struct ifnet * ifp)4489 rt6_flush(
4490 struct in6_addr *gateway,
4491 struct ifnet *ifp)
4492 {
4493 radix_node_head_ref_t rnh = rt_tables[AF_INET6];
4494
4495 /* We'll care only link-local addresses */
4496 if (!IN6_IS_ADDR_LINKLOCAL(gateway)) {
4497 return;
4498 }
4499 lck_mtx_lock(rnh_lock);
4500 /* XXX: hack for KAME's link-local address kludge */
4501 if (in6_embedded_scope) {
4502 gateway->s6_addr16[1] = htons(ifp->if_index);
4503 }
4504
4505 rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
4506 lck_mtx_unlock(rnh_lock);
4507 }
4508
4509 static int
rt6_deleteroute(struct radix_node * rn,void * arg)4510 rt6_deleteroute(
4511 struct radix_node *rn,
4512 void *arg)
4513 {
4514 rtentry_ref_t rt = (struct rtentry *)rn;
4515 struct in6_addr *__single gate = (struct in6_addr *)arg;
4516
4517 LCK_MTX_ASSERT(rnh_lock, LCK_MTX_ASSERT_OWNED);
4518
4519 RT_LOCK(rt);
4520 if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6) {
4521 RT_UNLOCK(rt);
4522 return 0;
4523 }
4524
4525 if (!IN6_ARE_ADDR_EQUAL(gate, &SIN6(rt->rt_gateway)->sin6_addr)) {
4526 RT_UNLOCK(rt);
4527 return 0;
4528 }
4529 /*
4530 * Do not delete a static route.
4531 * XXX: this seems to be a bit ad-hoc. Should we consider the
4532 * 'cloned' bit instead?
4533 */
4534 if ((rt->rt_flags & RTF_STATIC) != 0) {
4535 RT_UNLOCK(rt);
4536 return 0;
4537 }
4538 /*
4539 * We delete only host route. This means, in particular, we don't
4540 * delete default route.
4541 */
4542 if ((rt->rt_flags & RTF_HOST) == 0) {
4543 RT_UNLOCK(rt);
4544 return 0;
4545 }
4546
4547 /*
4548 * Safe to drop rt_lock and use rt_key, rt_gateway, since holding
4549 * rnh_lock here prevents another thread from calling rt_setgate()
4550 * on this route.
4551 */
4552 RT_UNLOCK(rt);
4553 return rtrequest_locked(RTM_DELETE, rt_key(rt), rt->rt_gateway,
4554 rt_mask(rt), rt->rt_flags, 0);
4555 }
4556
4557 int
nd6_setdefaultiface(int ifindex)4558 nd6_setdefaultiface(
4559 int ifindex)
4560 {
4561 int error = 0;
4562 ifnet_t def_ifp = NULL;
4563
4564 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
4565
4566 ifnet_head_lock_shared();
4567 if (!IF_INDEX_IN_RANGE(ifindex)) {
4568 ifnet_head_done();
4569 return EINVAL;
4570 }
4571 def_ifp = ifindex2ifnet[ifindex];
4572 ifnet_head_done();
4573
4574 lck_mtx_lock(nd6_mutex);
4575 if (nd6_defifindex != ifindex) {
4576 ifnet_ref_t odef_ifp = nd6_defifp;
4577
4578 nd6_defifindex = ifindex;
4579 if (nd6_defifindex > 0) {
4580 nd6_defifp = def_ifp;
4581 } else {
4582 nd6_defifp = NULL;
4583 }
4584
4585 if (nd6_defifp != NULL) {
4586 nd6log(info, "%s: is now the default "
4587 "interface (was %s)\n", if_name(nd6_defifp),
4588 odef_ifp != NULL ? if_name(odef_ifp) : "NONE");
4589 } else {
4590 nd6log(info, "No default interface set\n");
4591 }
4592
4593 /*
4594 * If the Default Router List is empty, install a route
4595 * to the specified interface as default or remove the default
4596 * route when the default interface becomes canceled.
4597 * The check for the queue is actually redundant, but
4598 * we do this here to avoid re-install the default route
4599 * if the list is NOT empty.
4600 */
4601 if (odef_ifp != NULL) {
4602 defrouter_select(odef_ifp, NULL);
4603 }
4604
4605 if (nd6_defifp != NULL) {
4606 defrouter_select(nd6_defifp, NULL);
4607 nd6_prefix_sync(nd6_defifp);
4608 }
4609
4610 /*
4611 * XXX For now we managed RTI routes as un-scoped.
4612 * Therefore we ignore the change in nd6_defifindex
4613 * for RTI routes for now.
4614 */
4615 /*
4616 * Our current implementation assumes one-to-one mapping between
4617 * interfaces and links, so it would be natural to use the
4618 * default interface as the default link.
4619 */
4620 scope6_setdefault(nd6_defifp);
4621 }
4622 lck_mtx_unlock(nd6_mutex);
4623 return error;
4624 }
4625