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