]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/nd6_rtr.c
xnu-1699.32.7.tar.gz
[apple/xnu.git] / bsd / netinet6 / nd6_rtr.c
CommitLineData
2d21ac55 1/*
6d2010ae 2 * Copyright (c) 2003-2011 Apple Inc. All rights reserved.
2d21ac55
A
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
55e303ae 29/* $FreeBSD: src/sys/netinet6/nd6_rtr.c,v 1.11 2002/04/19 04:46:23 suz Exp $ */
9bccf70c 30/* $KAME: nd6_rtr.c,v 1.111 2001/04/27 01:37:15 jinmei Exp $ */
1c79356b
A
31
32/*
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the project nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
9bccf70c 61
1c79356b
A
62#include <sys/param.h>
63#include <sys/systm.h>
64#include <sys/malloc.h>
65#include <sys/mbuf.h>
66#include <sys/socket.h>
67#include <sys/sockio.h>
68#include <sys/time.h>
69#include <sys/kernel.h>
70#include <sys/errno.h>
1c79356b 71#include <sys/syslog.h>
9bccf70c 72#include <sys/queue.h>
6d2010ae
A
73#include <sys/mcache.h>
74
91447636 75#include <kern/lock.h>
6d2010ae
A
76#include <kern/zalloc.h>
77#include <machine/machine_routines.h>
1c79356b
A
78
79#include <net/if.h>
80#include <net/if_types.h>
81#include <net/if_dl.h>
82#include <net/route.h>
83#include <net/radix.h>
84
85#include <netinet/in.h>
86#include <netinet6/in6_var.h>
9bccf70c 87#include <netinet6/in6_ifattach.h>
1c79356b
A
88#include <netinet/ip6.h>
89#include <netinet6/ip6_var.h>
90#include <netinet6/nd6.h>
91#include <netinet/icmp6.h>
9bccf70c 92#include <netinet6/scope6_var.h>
1c79356b
A
93
94#include <net/net_osdep.h>
95
96#define SDL(s) ((struct sockaddr_dl *)s)
97
6d2010ae
A
98static struct nd_defrouter *defrtrlist_update_common(struct nd_defrouter *,
99 boolean_t);
91447636 100static struct nd_defrouter *defrtrlist_update(struct nd_defrouter *);
6d2010ae
A
101
102static struct in6_ifaddr *in6_ifadd(struct nd_prefix *, int);
103static void defrtrlist_sync(struct ifnet *);
104
105static void defrouter_select_common(struct ifnet *, int);
106
91447636
A
107static struct nd_pfxrouter *pfxrtr_lookup(struct nd_prefix *,
108 struct nd_defrouter *);
109static void pfxrtr_add(struct nd_prefix *, struct nd_defrouter *);
110static void pfxrtr_del(struct nd_pfxrouter *);
111static struct nd_pfxrouter *find_pfxlist_reachable_router(struct nd_prefix *);
91447636 112static void nd6_rtmsg(int, struct rtentry *);
1c79356b 113
6d2010ae
A
114static int nd6_prefix_onlink_common(struct nd_prefix *, boolean_t,
115 unsigned int);
116static struct nd_prefix *nd6_prefix_equal_lookup(struct nd_prefix *, boolean_t);
117static void nd6_prefix_sync(struct ifnet *);
118
119static void in6_init_address_ltimes(struct nd_prefix *,
120 struct in6_addrlifetime *, boolean_t);
1c79356b 121
91447636 122static int rt6_deleteroute(struct radix_node *, void *);
1c79356b 123
6d2010ae
A
124static struct nd_defrouter *nddr_alloc(int);
125static void nddr_free(struct nd_defrouter *);
126static void nddr_trace(struct nd_defrouter *, int);
127
128static struct nd_prefix *ndpr_alloc(int);
129static void ndpr_free(struct nd_prefix *);
130static void ndpr_trace(struct nd_prefix *, int);
131
1c79356b
A
132extern int nd6_recalc_reachtm_interval;
133
9bccf70c 134static struct ifnet *nd6_defifp;
1c79356b 135int nd6_defifindex;
6d2010ae
A
136static unsigned int nd6_defrouter_genid;
137
138int ip6_use_tempaddr = 1; /* use temp addr by default for testing now */
1c79356b 139
6d2010ae 140int nd6_accept_6to4 = 1;
1c79356b 141
9bccf70c
A
142int ip6_desync_factor;
143u_int32_t ip6_temp_preferred_lifetime = DEF_TEMP_PREFERRED_LIFETIME;
144u_int32_t ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME;
145/*
146 * shorter lifetimes for debugging purposes.
6d2010ae
A
147u_int32_t ip6_temp_preferred_lifetime = 800;
148static u_int32_t ip6_temp_valid_lifetime = 1800;
9bccf70c
A
149*/
150int ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
1c79356b 151
91447636
A
152extern lck_mtx_t *nd6_mutex;
153
6d2010ae
A
154/* Serialization variables for single thread access to nd_prefix */
155static boolean_t nd_prefix_busy;
156static void *nd_prefix_waitchan = &nd_prefix_busy;
157static int nd_prefix_waiters = 0;
158
159/* Serialization variables for single thread access to nd_defrouter */
160static boolean_t nd_defrouter_busy;
161static void *nd_defrouter_waitchan = &nd_defrouter_busy;
162static int nd_defrouter_waiters = 0;
163
164/* RTPREF_MEDIUM has to be 0! */
165#define RTPREF_HIGH 1
166#define RTPREF_MEDIUM 0
167#define RTPREF_LOW (-1)
168#define RTPREF_RESERVED (-2)
169#define RTPREF_INVALID (-3) /* internal */
170
171#define NDPR_TRACE_HIST_SIZE 32 /* size of trace history */
172
173/* For gdb */
174__private_extern__ unsigned int ndpr_trace_hist_size = NDPR_TRACE_HIST_SIZE;
175
176struct nd_prefix_dbg {
177 struct nd_prefix ndpr_pr; /* nd_prefix */
178 u_int16_t ndpr_refhold_cnt; /* # of ref */
179 u_int16_t ndpr_refrele_cnt; /* # of rele */
180 /*
181 * Circular lists of ndpr_addref and ndpr_remref callers.
182 */
183 ctrace_t ndpr_refhold[NDPR_TRACE_HIST_SIZE];
184 ctrace_t ndpr_refrele[NDPR_TRACE_HIST_SIZE];
185};
186
187static unsigned int ndpr_debug; /* debug flags */
188static unsigned int ndpr_size; /* size of zone element */
189static struct zone *ndpr_zone; /* zone for nd_prefix */
190
191#define NDPR_ZONE_MAX 64 /* maximum elements in zone */
192#define NDPR_ZONE_NAME "nd6_prefix" /* zone name */
193
194#define NDDR_TRACE_HIST_SIZE 32 /* size of trace history */
195
196/* For gdb */
197__private_extern__ unsigned int nddr_trace_hist_size = NDDR_TRACE_HIST_SIZE;
198
199struct nd_defrouter_dbg {
200 struct nd_defrouter nddr_dr; /* nd_defrouter */
201 uint16_t nddr_refhold_cnt; /* # of ref */
202 uint16_t nddr_refrele_cnt; /* # of rele */
203 /*
204 * Circular lists of ndpr_addref and ndpr_remref callers.
205 */
206 ctrace_t nddr_refhold[NDDR_TRACE_HIST_SIZE];
207 ctrace_t nddr_refrele[NDDR_TRACE_HIST_SIZE];
208};
209
210static unsigned int nddr_debug; /* debug flags */
211static unsigned int nddr_size; /* size of zone element */
212static struct zone *nddr_zone; /* zone for nd_defrouter */
213
214#define NDDR_ZONE_MAX 64 /* maximum elements in zone */
215#define NDDR_ZONE_NAME "nd6_defrouter" /* zone name */
216
217static unsigned int ndprtr_size; /* size of zone element */
218static struct zone *ndprtr_zone; /* zone for nd_pfxrouter */
219
220#define NDPRTR_ZONE_MAX 64 /* maximum elements in zone */
221#define NDPRTR_ZONE_NAME "nd6_pfxrouter" /* zone name */
222
223void
224nd6_rtr_init(void)
225{
226 PE_parse_boot_argn("ifa_debug", &ndpr_debug, sizeof (ndpr_debug));
227 PE_parse_boot_argn("ifa_debug", &nddr_debug, sizeof (nddr_debug));
228
229 ndpr_size = (ndpr_debug == 0) ? sizeof (struct nd_prefix) :
230 sizeof (struct nd_prefix_dbg);
231 ndpr_zone = zinit(ndpr_size, NDPR_ZONE_MAX * ndpr_size, 0,
232 NDPR_ZONE_NAME);
233 if (ndpr_zone == NULL) {
234 panic("%s: failed allocating %s", __func__, NDPR_ZONE_NAME);
235 /* NOTREACHED */
236 }
237 zone_change(ndpr_zone, Z_EXPAND, TRUE);
238 zone_change(ndpr_zone, Z_CALLERACCT, FALSE);
239
240 nddr_size = (nddr_debug == 0) ? sizeof (struct nd_defrouter) :
241 sizeof (struct nd_defrouter_dbg);
242 nddr_zone = zinit(nddr_size, NDDR_ZONE_MAX * nddr_size, 0,
243 NDDR_ZONE_NAME);
244 if (nddr_zone == NULL) {
245 panic("%s: failed allocating %s", __func__, NDDR_ZONE_NAME);
246 /* NOTREACHED */
247 }
248 zone_change(nddr_zone, Z_EXPAND, TRUE);
249 zone_change(nddr_zone, Z_CALLERACCT, FALSE);
250
251 ndprtr_size = sizeof (struct nd_pfxrouter);
252 ndprtr_zone = zinit(ndprtr_size, NDPRTR_ZONE_MAX * ndprtr_size, 0,
253 NDPRTR_ZONE_NAME);
254 if (ndprtr_zone == NULL) {
255 panic("%s: failed allocating %s", __func__, NDPRTR_ZONE_NAME);
256 /* NOTREACHED */
257 }
258 zone_change(ndprtr_zone, Z_EXPAND, TRUE);
259 zone_change(ndprtr_zone, Z_CALLERACCT, FALSE);
260}
261
1c79356b
A
262/*
263 * Receive Router Solicitation Message - just for routers.
264 * Router solicitation/advertisement is mostly managed by userland program
265 * (rtadvd) so here we have no function like nd6_ra_output().
266 *
267 * Based on RFC 2461
268 */
269void
91447636
A
270nd6_rs_input(
271 struct mbuf *m,
272 int off,
273 int icmp6len)
1c79356b
A
274{
275 struct ifnet *ifp = m->m_pkthdr.rcvif;
276 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
277 struct nd_router_solicit *nd_rs;
278 struct in6_addr saddr6 = ip6->ip6_src;
1c79356b
A
279 char *lladdr = NULL;
280 int lladdrlen = 0;
1c79356b
A
281 union nd_opts ndopts;
282
283 /* If I'm not a router, ignore it. */
55e303ae 284 if (ip6_accept_rtadv != 0 || (ifp->if_eflags & IFEF_ACCEPT_RTADVD) || ip6_forwarding != 1)
1c79356b
A
285 goto freeit;
286
287 /* Sanity checks */
288 if (ip6->ip6_hlim != 255) {
9bccf70c
A
289 nd6log((LOG_ERR,
290 "nd6_rs_input: invalid hlim (%d) from %s to %s on %s\n",
291 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
292 ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
293 goto bad;
1c79356b
A
294 }
295
296 /*
6d2010ae
A
297 * Don't update the neighbor cache, if src = :: or a non-neighbor.
298 * The former case indicates that the src has no IP address assigned
299 * yet. See nd6_ns_input() for the latter case.
300 */
301 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src))
1c79356b 302 goto freeit;
6d2010ae
A
303 else {
304 struct sockaddr_in6 src_sa6;
305
306 bzero(&src_sa6, sizeof(src_sa6));
307 src_sa6.sin6_family = AF_INET6;
308 src_sa6.sin6_len = sizeof(src_sa6);
309 src_sa6.sin6_addr = ip6->ip6_src;
310 if (!nd6_is_addr_neighbor(&src_sa6, ifp, 0)) {
311 nd6log((LOG_INFO, "nd6_rs_input: "
312 "RS packet from non-neighbor\n"));
313 goto freeit;
314 }
315 }
1c79356b
A
316
317#ifndef PULLDOWN_TEST
91447636 318 IP6_EXTHDR_CHECK(m, off, icmp6len, return);
1c79356b
A
319 nd_rs = (struct nd_router_solicit *)((caddr_t)ip6 + off);
320#else
321 IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len);
322 if (nd_rs == NULL) {
323 icmp6stat.icp6s_tooshort++;
324 return;
325 }
326#endif
327
328 icmp6len -= sizeof(*nd_rs);
329 nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
330 if (nd6_options(&ndopts) < 0) {
9bccf70c
A
331 nd6log((LOG_INFO,
332 "nd6_rs_input: invalid ND option, ignored\n"));
333 /* nd6_options have incremented stats */
1c79356b
A
334 goto freeit;
335 }
336
337 if (ndopts.nd_opts_src_lladdr) {
338 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
339 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
340 }
341
342 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
9bccf70c 343 nd6log((LOG_INFO,
1c79356b
A
344 "nd6_rs_input: lladdrlen mismatch for %s "
345 "(if %d, RS packet %d)\n",
9bccf70c
A
346 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2));
347 goto bad;
1c79356b
A
348 }
349
350 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
351
352 freeit:
353 m_freem(m);
9bccf70c
A
354 return;
355
356 bad:
357 icmp6stat.icp6s_badrs++;
358 m_freem(m);
1c79356b
A
359}
360
361/*
362 * Receive Router Advertisement Message.
363 *
364 * Based on RFC 2461
365 * TODO: on-link bit on prefix information
366 * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
367 */
368void
91447636
A
369nd6_ra_input(
370 struct mbuf *m,
371 int off,
372 int icmp6len)
1c79356b
A
373{
374 struct ifnet *ifp = m->m_pkthdr.rcvif;
b0d623f7 375 struct nd_ifinfo *ndi = NULL;
1c79356b
A
376 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
377 struct nd_router_advert *nd_ra;
378 struct in6_addr saddr6 = ip6->ip6_src;
6d2010ae 379 int mcast = 0;
1c79356b 380 union nd_opts ndopts;
6d2010ae 381 struct nd_defrouter *dr = NULL;
91447636
A
382 struct timeval timenow;
383
384 getmicrotime(&timenow);
1c79356b 385
55e303ae 386 if (ip6_accept_rtadv == 0 && ((ifp->if_eflags & IFEF_ACCEPT_RTADVD) == 0))
1c79356b
A
387 goto freeit;
388
389 if (ip6->ip6_hlim != 255) {
9bccf70c
A
390 nd6log((LOG_ERR,
391 "nd6_ra_input: invalid hlim (%d) from %s to %s on %s\n",
392 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
393 ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
394 goto bad;
1c79356b
A
395 }
396
397 if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
9bccf70c 398 nd6log((LOG_ERR,
1c79356b 399 "nd6_ra_input: src %s is not link-local\n",
9bccf70c
A
400 ip6_sprintf(&saddr6)));
401 goto bad;
1c79356b
A
402 }
403
404#ifndef PULLDOWN_TEST
91447636 405 IP6_EXTHDR_CHECK(m, off, icmp6len, return);
1c79356b
A
406 nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off);
407#else
408 IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
409 if (nd_ra == NULL) {
410 icmp6stat.icp6s_tooshort++;
411 return;
412 }
413#endif
414
415 icmp6len -= sizeof(*nd_ra);
416 nd6_option_init(nd_ra + 1, icmp6len, &ndopts);
417 if (nd6_options(&ndopts) < 0) {
9bccf70c
A
418 nd6log((LOG_INFO,
419 "nd6_ra_input: invalid ND option, ignored\n"));
420 /* nd6_options have incremented stats */
1c79356b
A
421 goto freeit;
422 }
423
424 {
425 struct nd_defrouter dr0;
426 u_int32_t advreachable = nd_ra->nd_ra_reachable;
1c79356b 427
6d2010ae
A
428 /* remember if this is a multicasted advertisement */
429 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
430 mcast = 1;
431
b0d623f7
A
432 lck_rw_lock_shared(nd_if_rwlock);
433 if (ifp->if_index >= nd_ifinfo_indexlim) {
434 lck_rw_done(nd_if_rwlock);
435 goto freeit;
436 }
437 ndi = &nd_ifinfo[ifp->if_index];
6d2010ae 438 bzero(&dr0, sizeof (dr0));
1c79356b
A
439 dr0.rtaddr = saddr6;
440 dr0.flags = nd_ra->nd_ra_flags_reserved;
441 dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
91447636 442 dr0.expire = timenow.tv_sec + dr0.rtlifetime;
1c79356b 443 dr0.ifp = ifp;
1c79356b
A
444 /* unspecified or not? (RFC 2461 6.3.4) */
445 if (advreachable) {
55e303ae 446 advreachable = ntohl(advreachable);
1c79356b
A
447 if (advreachable <= MAX_REACHABLE_TIME &&
448 ndi->basereachable != advreachable) {
449 ndi->basereachable = advreachable;
450 ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable);
451 ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */
452 }
453 }
454 if (nd_ra->nd_ra_retransmit)
455 ndi->retrans = ntohl(nd_ra->nd_ra_retransmit);
456 if (nd_ra->nd_ra_curhoplimit)
457 ndi->chlim = nd_ra->nd_ra_curhoplimit;
b0d623f7
A
458 lck_rw_done(nd_if_rwlock);
459 ndi = NULL;
6d2010ae 460 lck_mtx_lock(nd6_mutex);
1c79356b 461 dr = defrtrlist_update(&dr0);
6d2010ae 462 lck_mtx_unlock(nd6_mutex);
1c79356b
A
463 }
464
465 /*
466 * prefix
467 */
468 if (ndopts.nd_opts_pi) {
469 struct nd_opt_hdr *pt;
9bccf70c 470 struct nd_opt_prefix_info *pi = NULL;
1c79356b
A
471 struct nd_prefix pr;
472
473 for (pt = (struct nd_opt_hdr *)ndopts.nd_opts_pi;
474 pt <= (struct nd_opt_hdr *)ndopts.nd_opts_pi_end;
475 pt = (struct nd_opt_hdr *)((caddr_t)pt +
476 (pt->nd_opt_len << 3))) {
477 if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION)
478 continue;
479 pi = (struct nd_opt_prefix_info *)pt;
480
481 if (pi->nd_opt_pi_len != 4) {
9bccf70c
A
482 nd6log((LOG_INFO,
483 "nd6_ra_input: invalid option "
484 "len %d for prefix information option, "
485 "ignored\n", pi->nd_opt_pi_len));
1c79356b
A
486 continue;
487 }
488
489 if (128 < pi->nd_opt_pi_prefix_len) {
9bccf70c
A
490 nd6log((LOG_INFO,
491 "nd6_ra_input: invalid prefix "
492 "len %d for prefix information option, "
493 "ignored\n", pi->nd_opt_pi_prefix_len));
1c79356b
A
494 continue;
495 }
496
497 if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
498 || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
9bccf70c
A
499 nd6log((LOG_INFO,
500 "nd6_ra_input: invalid prefix "
501 "%s, ignored\n",
502 ip6_sprintf(&pi->nd_opt_pi_prefix)));
1c79356b
A
503 continue;
504 }
505
1c79356b 506 bzero(&pr, sizeof(pr));
6d2010ae
A
507 lck_mtx_init(&pr.ndpr_lock, ifa_mtx_grp, ifa_mtx_attr);
508 NDPR_LOCK(&pr);
1c79356b
A
509 pr.ndpr_prefix.sin6_family = AF_INET6;
510 pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix);
511 pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix;
91447636 512 pr.ndpr_ifp = m->m_pkthdr.rcvif;
1c79356b
A
513
514 pr.ndpr_raf_onlink = (pi->nd_opt_pi_flags_reserved &
515 ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
516 pr.ndpr_raf_auto = (pi->nd_opt_pi_flags_reserved &
517 ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
518 pr.ndpr_plen = pi->nd_opt_pi_prefix_len;
519 pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time);
520 pr.ndpr_pltime =
521 ntohl(pi->nd_opt_pi_preferred_time);
522
6d2010ae
A
523 /*
524 * Exceptions to stateless autoconfiguration processing:
525 * + nd6_accept_6to4 == 0 && address has 6to4 prefix
526 * + ip6_only_allow_rfc4193_prefix != 0 && address not RFC 4193
527 */
528 if (ip6_only_allow_rfc4193_prefix &&
529 !IN6_IS_ADDR_UNIQUE_LOCAL(&pi->nd_opt_pi_prefix)) {
530 nd6log((LOG_INFO,
531 "nd6_ra_input: no SLAAC on prefix %s [not RFC 4193]\n",
532 ip6_sprintf(&pi->nd_opt_pi_prefix)));
533 pr.ndpr_raf_auto = 0;
534 }
535 else if (!nd6_accept_6to4 &&
536 IN6_IS_ADDR_6TO4(&pi->nd_opt_pi_prefix)) {
537 nd6log((LOG_INFO,
538 "nd6_ra_input: no SLAAC on prefix %s [6to4]\n",
539 ip6_sprintf(&pi->nd_opt_pi_prefix)));
540 pr.ndpr_raf_auto = 0;
541 }
1c79356b 542
6d2010ae
A
543 if (in6_init_prefix_ltimes(&pr)) {
544 NDPR_UNLOCK(&pr);
545 lck_mtx_destroy(&pr.ndpr_lock, ifa_mtx_grp);
546 continue; /* prefix lifetime init failed */
547 } else {
548 NDPR_UNLOCK(&pr);
549 }
550 (void)prelist_update(&pr, dr, m, mcast);
551 lck_mtx_destroy(&pr.ndpr_lock, ifa_mtx_grp);
1c79356b
A
552 }
553 }
554
555 /*
556 * MTU
557 */
558 if (ndopts.nd_opts_mtu && ndopts.nd_opts_mtu->nd_opt_mtu_len == 1) {
559 u_int32_t mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
560
561 /* lower bound */
562 if (mtu < IPV6_MMTU) {
9bccf70c 563 nd6log((LOG_INFO, "nd6_ra_input: bogus mtu option "
1c79356b 564 "mtu=%d sent from %s, ignoring\n",
9bccf70c 565 mtu, ip6_sprintf(&ip6->ip6_src)));
1c79356b
A
566 goto skip;
567 }
568
b0d623f7
A
569 lck_rw_lock_shared(nd_if_rwlock);
570 if (ifp->if_index >= nd_ifinfo_indexlim) {
571 lck_rw_done(nd_if_rwlock);
572 goto freeit;
573 }
574 ndi = &nd_ifinfo[ifp->if_index];
1c79356b
A
575 /* upper bound */
576 if (ndi->maxmtu) {
577 if (mtu <= ndi->maxmtu) {
578 int change = (ndi->linkmtu != mtu);
579
580 ndi->linkmtu = mtu;
b0d623f7 581 lck_rw_done(nd_if_rwlock);
1c79356b
A
582 if (change) /* in6_maxmtu may change */
583 in6_setmaxmtu();
584 } else {
9bccf70c 585 nd6log((LOG_INFO, "nd6_ra_input: bogus mtu "
1c79356b
A
586 "mtu=%d sent from %s; "
587 "exceeds maxmtu %d, ignoring\n",
588 mtu, ip6_sprintf(&ip6->ip6_src),
9bccf70c 589 ndi->maxmtu));
b0d623f7 590 lck_rw_done(nd_if_rwlock);
1c79356b
A
591 }
592 } else {
b0d623f7 593 lck_rw_done(nd_if_rwlock);
9bccf70c 594 nd6log((LOG_INFO, "nd6_ra_input: mtu option "
1c79356b
A
595 "mtu=%d sent from %s; maxmtu unknown, "
596 "ignoring\n",
9bccf70c 597 mtu, ip6_sprintf(&ip6->ip6_src)));
1c79356b 598 }
b0d623f7 599 ndi = NULL;
1c79356b
A
600 }
601
602 skip:
603
604 /*
55e303ae 605 * Source link layer address
1c79356b
A
606 */
607 {
608 char *lladdr = NULL;
609 int lladdrlen = 0;
610
611 if (ndopts.nd_opts_src_lladdr) {
612 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
613 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
614 }
615
616 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
9bccf70c 617 nd6log((LOG_INFO,
1c79356b
A
618 "nd6_ra_input: lladdrlen mismatch for %s "
619 "(if %d, RA packet %d)\n",
9bccf70c
A
620 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2));
621 goto bad;
1c79356b
A
622 }
623
624 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0);
625
626 /*
627 * Installing a link-layer address might change the state of the
628 * router's neighbor cache, which might also affect our on-link
629 * detection of adveritsed prefixes.
630 */
6d2010ae
A
631 lck_mtx_lock(nd6_mutex);
632 pfxlist_onlink_check();
633 lck_mtx_unlock(nd6_mutex);
1c79356b
A
634 }
635
9bccf70c
A
636 freeit:
637 m_freem(m);
6d2010ae
A
638 if (dr)
639 NDDR_REMREF(dr);
9bccf70c 640 return;
1c79356b 641
9bccf70c
A
642 bad:
643 icmp6stat.icp6s_badra++;
6d2010ae 644 goto freeit;
1c79356b
A
645}
646
647/*
648 * default router list proccessing sub routines
649 */
9bccf70c
A
650
651/* tell the change to user processes watching the routing socket. */
652static void
653nd6_rtmsg(cmd, rt)
654 int cmd;
655 struct rtentry *rt;
656{
657 struct rt_addrinfo info;
b0d623f7 658 struct ifnet *ifp = rt->rt_ifp;
9bccf70c 659
b0d623f7 660 RT_LOCK_ASSERT_HELD(rt);
91447636 661
9bccf70c 662 bzero((caddr_t)&info, sizeof(info));
6d2010ae 663 /* Lock ifp for if_lladdr */
b0d623f7 664 ifnet_lock_shared(ifp);
9bccf70c
A
665 info.rti_info[RTAX_DST] = rt_key(rt);
666 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
667 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
6d2010ae
A
668 /*
669 * ifa_addr pointers for both should always be valid
670 * in this context; no need to hold locks.
671 */
672 info.rti_info[RTAX_IFP] = ifp->if_lladdr->ifa_addr;
9bccf70c
A
673 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
674
675 rt_missmsg(cmd, &info, rt->rt_flags, 0);
b0d623f7 676 ifnet_lock_done(ifp);
9bccf70c
A
677}
678
1c79356b 679void
6d2010ae 680defrouter_addreq(struct nd_defrouter *new, boolean_t scoped)
1c79356b
A
681{
682 struct sockaddr_in6 def, mask, gate;
9bccf70c 683 struct rtentry *newrt = NULL;
6d2010ae
A
684 unsigned int ifscope;
685 int err;
686
687 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
688
689 if (new->stateflags & NDDRF_INSTALLED)
690 return;
691
692 nd6log2((LOG_INFO, "%s: adding default router %s, scoped=%d, "
693 "static=%d\n", if_name(new->ifp), ip6_sprintf(&new->rtaddr),
694 scoped, (new->stateflags & NDDRF_STATIC) ? 1 : 0));
1c79356b
A
695
696 Bzero(&def, sizeof(def));
697 Bzero(&mask, sizeof(mask));
698 Bzero(&gate, sizeof(gate));
699
700 def.sin6_len = mask.sin6_len = gate.sin6_len
701 = sizeof(struct sockaddr_in6);
702 def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
703 gate.sin6_addr = new->rtaddr;
704
6d2010ae
A
705 ifscope = scoped ? new->ifp->if_index : IFSCOPE_NONE;
706
707 err = rtrequest_scoped(RTM_ADD, (struct sockaddr *)&def,
b0d623f7 708 (struct sockaddr *)&gate, (struct sockaddr *)&mask,
6d2010ae
A
709 RTF_GATEWAY, &newrt, ifscope);
710
9bccf70c 711 if (newrt) {
b0d623f7 712 RT_LOCK(newrt);
9bccf70c 713 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
b0d623f7
A
714 RT_REMREF_LOCKED(newrt);
715 RT_UNLOCK(newrt);
6d2010ae
A
716 new->stateflags |= NDDRF_INSTALLED;
717 if (ifscope != IFSCOPE_NONE)
718 new->stateflags |= NDDRF_IFSCOPE;
719 new->genid = nd6_defrouter_genid;
9bccf70c 720 } else {
6d2010ae
A
721 nd6log((LOG_ERR, "%s: failed to add default router "
722 "%s on %s scoped %d (errno = %d)\n", __func__,
723 ip6_sprintf(&gate.sin6_addr), if_name(new->ifp),
724 (ifscope != IFSCOPE_NONE), err));
1c79356b 725 }
6d2010ae 726 new->err = err;
1c79356b
A
727}
728
729struct nd_defrouter *
91447636
A
730defrouter_lookup(
731 struct in6_addr *addr,
732 struct ifnet *ifp)
1c79356b
A
733{
734 struct nd_defrouter *dr;
735
91447636
A
736 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
737
1c79356b
A
738 for (dr = TAILQ_FIRST(&nd_defrouter); dr;
739 dr = TAILQ_NEXT(dr, dr_entry)) {
6d2010ae
A
740 NDDR_LOCK(dr);
741 if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr)) {
742 NDDR_ADDREF_LOCKED(dr);
743 NDDR_UNLOCK(dr);
1c79356b 744 return(dr);
6d2010ae
A
745 }
746 NDDR_UNLOCK(dr);
1c79356b
A
747 }
748
6d2010ae 749 return (NULL); /* search failed */
1c79356b
A
750}
751
6d2010ae
A
752/*
753 * Remove the default route for a given router.
754 * This is just a subroutine function for defrouter_select(), and should
755 * not be called from anywhere else.
756 */
1c79356b 757void
6d2010ae 758defrouter_delreq(struct nd_defrouter *dr)
1c79356b
A
759{
760 struct sockaddr_in6 def, mask, gate;
9bccf70c 761 struct rtentry *oldrt = NULL;
6d2010ae
A
762 unsigned int ifscope;
763 int err;
764
765 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
766
767 /* ifp would be NULL for the "drany" case */
768 if (dr->ifp != NULL && !(dr->stateflags & NDDRF_INSTALLED))
769 return;
770
771 NDDR_LOCK_ASSERT_HELD(dr);
772
773 nd6log2((LOG_INFO, "%s: removing default router %s, scoped=%d, "
774 "static=%d\n", dr->ifp != NULL ? if_name(dr->ifp) : "ANY",
775 ip6_sprintf(&dr->rtaddr), (dr->stateflags & NDDRF_IFSCOPE) ? 1 : 0,
776 (dr->stateflags & NDDRF_STATIC) ? 1 : 0));
1c79356b
A
777
778 Bzero(&def, sizeof(def));
779 Bzero(&mask, sizeof(mask));
780 Bzero(&gate, sizeof(gate));
781
782 def.sin6_len = mask.sin6_len = gate.sin6_len
783 = sizeof(struct sockaddr_in6);
784 def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
785 gate.sin6_addr = dr->rtaddr;
786
6d2010ae
A
787 if (dr->ifp != NULL) {
788 ifscope = (dr->stateflags & NDDRF_IFSCOPE) ?
789 dr->ifp->if_index : IFSCOPE_NONE;
790 } else {
791 ifscope = IFSCOPE_NONE;
792 }
793 err = rtrequest_scoped(RTM_DELETE,
794 (struct sockaddr *)&def, (struct sockaddr *)&gate,
795 (struct sockaddr *)&mask, RTF_GATEWAY, &oldrt, ifscope);
796
9bccf70c 797 if (oldrt) {
b0d623f7 798 RT_LOCK(oldrt);
9bccf70c 799 nd6_rtmsg(RTM_DELETE, oldrt);
b0d623f7
A
800 RT_UNLOCK(oldrt);
801 rtfree(oldrt);
6d2010ae
A
802 } else if (err != ESRCH) {
803 nd6log((LOG_ERR, "%s: failed to delete default router "
804 "%s on %s scoped %d (errno = %d)\n", __func__,
805 ip6_sprintf(&gate.sin6_addr), dr->ifp != NULL ?
806 if_name(dr->ifp) : "ANY", (ifscope != IFSCOPE_NONE), err));
807 }
808 /* ESRCH means it's no longer in the routing table; ignore it */
809 if (oldrt != NULL || err == ESRCH) {
810 dr->stateflags &= ~NDDRF_INSTALLED;
811 if (ifscope != IFSCOPE_NONE)
812 dr->stateflags &= ~NDDRF_IFSCOPE;
813 }
814 dr->err = 0;
815}
816
817
818/*
819 * remove all default routes from default router list
820 */
821void
822defrouter_reset(void)
823{
824 struct nd_defrouter *dr, drany;
825
826 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
827
828 dr = TAILQ_FIRST(&nd_defrouter);
829 while (dr) {
830 NDDR_LOCK(dr);
831 if (dr->stateflags & NDDRF_INSTALLED) {
832 NDDR_ADDREF_LOCKED(dr);
833 NDDR_UNLOCK(dr);
834 lck_mtx_unlock(nd6_mutex);
835 NDDR_LOCK(dr);
836 defrouter_delreq(dr);
837 NDDR_UNLOCK(dr);
838 lck_mtx_lock(nd6_mutex);
839 NDDR_REMREF(dr);
840 dr = TAILQ_FIRST(&nd_defrouter);
841 } else {
842 NDDR_UNLOCK(dr);
843 dr = TAILQ_NEXT(dr, dr_entry);
844 }
845 }
846
847 /* Nuke primary (non-scoped) default router */
848 if (ip6_doscopedroute) {
849 bzero(&drany, sizeof (drany));
850 lck_mtx_init(&drany.nddr_lock, ifa_mtx_grp, ifa_mtx_attr);
851 lck_mtx_unlock(nd6_mutex);
852 NDDR_LOCK(&drany);
853 defrouter_delreq(&drany);
854 NDDR_UNLOCK(&drany);
855 lck_mtx_destroy(&drany.nddr_lock, ifa_mtx_grp);
856 lck_mtx_lock(nd6_mutex);
857 }
858
859}
860
861int
862defrtrlist_ioctl(u_long cmd, caddr_t data)
863{
864 struct in6_defrouter_32 *r_32 = (struct in6_defrouter_32 *)data;
865 struct in6_defrouter_64 *r_64 = (struct in6_defrouter_64 *)data;
866 struct nd_defrouter dr0;
867 unsigned int ifindex;
868 struct ifnet *dr_ifp;
869 int error = 0, add = 0;
870
871 switch (cmd) {
872 case SIOCDRADD_IN6_32:
873 case SIOCDRADD_IN6_64:
874 ++add;
875 /* FALLTHRU */
876 case SIOCDRDEL_IN6_32:
877 case SIOCDRDEL_IN6_64:
878 bzero(&dr0, sizeof (dr0));
879 if (cmd == SIOCDRADD_IN6_64 || cmd == SIOCDRDEL_IN6_64) {
880 dr0.rtaddr = r_64->rtaddr.sin6_addr;
881 dr0.flags = r_64->flags;
882 ifindex = r_64->if_index;
883 } else {
884 dr0.rtaddr = r_32->rtaddr.sin6_addr;
885 dr0.flags = r_32->flags;
886 ifindex = r_32->if_index;
887 }
888 ifnet_head_lock_shared();
889 /* Don't need to check is ifindex is < 0 since it's unsigned */
890 if (if_index < ifindex ||
891 (dr_ifp = ifindex2ifnet[ifindex]) == NULL) {
892 ifnet_head_done();
893 error = EINVAL;
894 break;
895 }
896 dr0.ifp = dr_ifp;
897 ifnet_head_done();
898
899 if (IN6_IS_SCOPE_EMBED(&dr0.rtaddr)) {
900 uint16_t *scope = &dr0.rtaddr.s6_addr16[1];
901
902 if (*scope == 0) {
903 *scope = htons(dr_ifp->if_index);
904 } else if (*scope != htons(dr_ifp->if_index)) {
905 error = EINVAL;
906 break;
907 }
908 }
909
910 if (add)
911 error = defrtrlist_add_static(&dr0);
912 if (!add || error != 0) {
913 int err = defrtrlist_del_static(&dr0);
914 if (!add)
915 error = err;
916 }
917 break;
918
919 default:
920 error = EOPNOTSUPP; /* check for safety */
921 break;
9bccf70c 922 }
1c79356b 923
6d2010ae 924 return (error);
1c79356b
A
925}
926
927void
6d2010ae 928defrtrlist_del(struct nd_defrouter *dr)
1c79356b
A
929{
930 struct nd_defrouter *deldr = NULL;
931 struct nd_prefix *pr;
b0d623f7 932 struct ifnet *ifp = dr->ifp;
1c79356b 933
6d2010ae
A
934 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
935
1c79356b
A
936 /*
937 * Flush all the routing table entries that use the router
938 * as a next hop.
939 */
b0d623f7
A
940 if (!ip6_forwarding &&
941 (ip6_accept_rtadv || (ifp->if_eflags & IFEF_ACCEPT_RTADVD))) {
1c79356b 942 /* above is a good condition? */
6d2010ae
A
943 NDDR_ADDREF(dr);
944 lck_mtx_unlock(nd6_mutex);
b0d623f7 945 rt6_flush(&dr->rtaddr, ifp);
6d2010ae
A
946 lck_mtx_lock(nd6_mutex);
947 NDDR_REMREF(dr);
1c79356b
A
948 }
949
950 if (dr == TAILQ_FIRST(&nd_defrouter))
951 deldr = dr; /* The router is primary. */
952
953 TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
6d2010ae
A
954 ++nd6_defrouter_genid;
955
956 nd6log2((LOG_INFO, "%s: freeing defrouter %s\n", if_name(dr->ifp),
957 ip6_sprintf(&dr->rtaddr)));
958
959 /*
960 * Delete it from the routing table.
961 */
962 NDDR_ADDREF(dr);
963 lck_mtx_unlock(nd6_mutex);
964 NDDR_LOCK(dr);
965 defrouter_delreq(dr);
966 NDDR_UNLOCK(dr);
967 lck_mtx_lock(nd6_mutex);
968 NDDR_REMREF(dr);
1c79356b
A
969
970 /*
971 * Also delete all the pointers to the router in each prefix lists.
972 */
973 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
974 struct nd_pfxrouter *pfxrtr;
6d2010ae
A
975
976 NDPR_LOCK(pr);
1c79356b
A
977 if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
978 pfxrtr_del(pfxrtr);
6d2010ae 979 NDPR_UNLOCK(pr);
1c79356b 980 }
6d2010ae
A
981
982 pfxlist_onlink_check();
1c79356b
A
983
984 /*
6d2010ae
A
985 * If the router is the primary one, choose a new one. If Scoped
986 * Routing is enabled, always try to pick another eligible router
987 * on this interface.
1c79356b 988 */
6d2010ae
A
989 if ((deldr || ip6_doscopedroute) && !ip6_forwarding &&
990 (ip6_accept_rtadv || (ifp->if_eflags & IFEF_ACCEPT_RTADVD)))
991 defrouter_select(ifp);
1c79356b 992
b0d623f7
A
993 lck_rw_lock_shared(nd_if_rwlock);
994 if (ifp->if_index < nd_ifinfo_indexlim) {
995 struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
6d2010ae 996 atomic_add_32(&ndi->ndefrouters, -1);
b0d623f7
A
997 if (ndi->ndefrouters < 0) {
998 log(LOG_WARNING, "defrtrlist_del: negative "
999 "count on %s\n", if_name(ifp));
1000 }
e2fac8b1 1001 }
b0d623f7 1002 lck_rw_done(nd_if_rwlock);
e2fac8b1 1003
6d2010ae
A
1004 NDDR_REMREF(dr); /* remove list reference */
1005}
1006
1007int
1008defrtrlist_add_static(struct nd_defrouter *new)
1009{
1010 struct nd_defrouter *dr;
1011 int err = 0;
1012
1013 new->rtlifetime = -1;
1014 new->stateflags |= NDDRF_STATIC;
1015
1016 /* we only want the preference level */
1017 new->flags &= ND_RA_FLAG_RTPREF_MASK;
1018
1019 lck_mtx_lock(nd6_mutex);
1020 dr = defrouter_lookup(&new->rtaddr, new->ifp);
1021 if (dr != NULL && !(dr->stateflags & NDDRF_STATIC)) {
1022 err = EINVAL;
1023 } else {
1024 if (dr != NULL)
1025 NDDR_REMREF(dr);
1026 dr = defrtrlist_update(new);
1027 if (dr != NULL)
1028 err = dr->err;
1029 else
1030 err = ENOMEM;
1031 }
1032 if (dr != NULL)
1033 NDDR_REMREF(dr);
1034 lck_mtx_unlock(nd6_mutex);
1035
1036 return (err);
1037}
1038
1039int
1040defrtrlist_del_static(struct nd_defrouter *new)
1041{
1042 struct nd_defrouter *dr;
1043
1044 lck_mtx_lock(nd6_mutex);
1045 dr = defrouter_lookup(&new->rtaddr, new->ifp);
1046 if (dr == NULL || !(dr->stateflags & NDDRF_STATIC)) {
1047 if (dr != NULL)
1048 NDDR_REMREF(dr);
1049 dr = NULL;
1050 } else {
1051 defrtrlist_del(dr);
1052 NDDR_REMREF(dr);
1053 }
1054 lck_mtx_unlock(nd6_mutex);
91447636 1055
6d2010ae
A
1056 return (dr != NULL ? 0 : EINVAL);
1057}
1058
1059/*
1060 * for default router selection
1061 * regards router-preference field as a 2-bit signed integer
1062 */
1063static int
1064rtpref(struct nd_defrouter *dr)
1065{
1066 switch (dr->flags & ND_RA_FLAG_RTPREF_MASK) {
1067 case ND_RA_FLAG_RTPREF_HIGH:
1068 return (RTPREF_HIGH);
1069 case ND_RA_FLAG_RTPREF_MEDIUM:
1070 case ND_RA_FLAG_RTPREF_RSV:
1071 return (RTPREF_MEDIUM);
1072 case ND_RA_FLAG_RTPREF_LOW:
1073 return (RTPREF_LOW);
1074 default:
1075 /*
1076 * This case should never happen. If it did, it would mean a
1077 * serious bug of kernel internal. We thus always bark here.
1078 * Or, can we even panic?
1079 */
1080 log(LOG_ERR, "rtpref: impossible RA flag %x\n", dr->flags);
1081 return (RTPREF_INVALID);
1082 }
1083 /* NOTREACHED */
1c79356b
A
1084}
1085
1086/*
6d2010ae
A
1087 * Default Router Selection according to Section 6.3.6 of RFC 2461 and
1088 * draft-ietf-ipngwg-router-selection:
1089 *
1090 * 1) Routers that are reachable or probably reachable should be preferred.
1091 * If we have more than one (probably) reachable router, prefer ones
1092 * with the highest router preference.
1c79356b
A
1093 * 2) When no routers on the list are known to be reachable or
1094 * probably reachable, routers SHOULD be selected in a round-robin
6d2010ae 1095 * fashion, regardless of router preference values.
1c79356b
A
1096 * 3) If the Default Router List is empty, assume that all
1097 * destinations are on-link.
6d2010ae
A
1098 *
1099 * When Scoped Routing is enabled, the selection logic is amended as follows:
1100 *
1101 * a) When a default interface is specified, the primary/non-scoped default
1102 * router will be set to the reachable router on that link (if any) with
1103 * the highest router preference.
1104 * b) When there are more than one routers on the same link, the one with
1105 * the highest router preference will be installed, either as scoped or
1106 * non-scoped route entry. If they all share the same preference value,
1107 * the one installed will be the static or the first encountered reachable
1108 * router, i.e. static one wins over dynamic.
1109 * c) When no routers on the list are known to be reachable, or probably
1110 * reachable, no round-robin selection will take place when the default
1111 * interface is set.
1112 *
1113 * We assume nd_defrouter is sorted by router preference value.
1114 * Since the code below covers both with and without router preference cases,
1115 * we do not need to classify the cases by ifdef.
1c79356b 1116 */
6d2010ae
A
1117static void
1118defrouter_select_common(struct ifnet *ifp, int ignore)
1c79356b 1119{
6d2010ae
A
1120 struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
1121 struct nd_defrouter *installed_dr0 = NULL;
1c79356b
A
1122 struct rtentry *rt = NULL;
1123 struct llinfo_nd6 *ln = NULL;
6d2010ae
A
1124 int update = 0;
1125 boolean_t found_installedrt = FALSE;
1126
1127 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1c79356b 1128
1c79356b 1129 /*
6d2010ae
A
1130 * This function should be called only when acting as an autoconfigured
1131 * host. Although the remaining part of this function is not effective
1132 * if the node is not an autoconfigured host, we explicitly exclude
1133 * such cases here for safety.
1c79356b 1134 */
6d2010ae
A
1135 if (ip6_forwarding || (!ignore && !ip6_accept_rtadv &&
1136 !(ifp->if_eflags & IFEF_ACCEPT_RTADVD))) {
1137 nd6log((LOG_WARNING,
1138 "defrouter_select: called unexpectedly (forwarding=%d, "
1139 "accept_rtadv=%d)\n", ip6_forwarding, ip6_accept_rtadv));
1140 return;
1141 }
1142
1143 /*
1144 * Let's handle easy case (3) first:
1145 * If default router list is empty, there's nothing to be done.
1146 */
1147 if (!TAILQ_FIRST(&nd_defrouter))
1148 return;
1149
1150 /*
1151 * Due to the number of times we drop nd6_mutex, we need to
1152 * serialize this function.
1153 */
1154 while (nd_defrouter_busy) {
1155 nd_defrouter_waiters++;
1156 msleep(nd_defrouter_waitchan, nd6_mutex, (PZERO-1),
1157 __func__, NULL);
1158 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1159 }
1160 nd_defrouter_busy = TRUE;
91447636 1161
6d2010ae
A
1162 /*
1163 * Search for a (probably) reachable router from the list.
1164 * We just pick up the first reachable one (if any), assuming that
1165 * the ordering rule of the list described in defrtrlist_update().
1166 *
1167 * For all intents and purposes of Scoped Routing:
1168 * selected_dr = candidate for primary router
1169 * installed_dr = currently installed primary router
1170 */
1c79356b
A
1171 for (dr = TAILQ_FIRST(&nd_defrouter); dr;
1172 dr = TAILQ_NEXT(dr, dr_entry)) {
6d2010ae
A
1173 boolean_t reachable;
1174
b0d623f7 1175 /* Callee returns a locked route upon success */
6d2010ae
A
1176 reachable = FALSE;
1177 NDDR_ADDREF(dr); /* for this for loop */
1178 lck_mtx_unlock(nd6_mutex);
b0d623f7
A
1179 if ((rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp, 0)) != NULL) {
1180 RT_LOCK_ASSERT_HELD(rt);
1181 if ((ln = rt->rt_llinfo) != NULL &&
1182 ND6_IS_LLINFO_PROBREACH(ln)) {
6d2010ae
A
1183 reachable = TRUE;
1184 if (selected_dr == NULL &&
1185 (!ip6_doscopedroute ||
1186 dr->ifp == nd6_defifp)) {
1187 selected_dr = dr;
1188 NDDR_ADDREF(selected_dr);
1189 }
b0d623f7
A
1190 }
1191 RT_REMREF_LOCKED(rt);
1192 RT_UNLOCK(rt);
6d2010ae 1193 rt = NULL;
1c79356b 1194 }
6d2010ae 1195 lck_mtx_lock(nd6_mutex);
1c79356b 1196
6d2010ae
A
1197 /* Handle case (b) */
1198 if (ip6_doscopedroute && dr->ifp == nd6_defifp &&
1199 (selected_dr == NULL || rtpref(dr) > rtpref(selected_dr) ||
1200 (rtpref(dr) == rtpref(selected_dr) &&
1201 (dr->stateflags & NDDRF_STATIC) &&
1202 !(selected_dr->stateflags & NDDRF_STATIC)))) {
1203 if (selected_dr)
1204 NDDR_REMREF(selected_dr);
1205 selected_dr = dr;
1206 NDDR_ADDREF(selected_dr);
1207 }
1208
1209 if (!(dr->stateflags & NDDRF_INSTALLED)) {
1c79356b 1210 /*
6d2010ae
A
1211 * If the router hasn't been installed and it is
1212 * reachable, try to install it later on below.
1213 * If it's static, try to install it anyway.
1c79356b 1214 */
6d2010ae
A
1215 if (reachable || (dr->stateflags & NDDRF_STATIC)) {
1216 dr->genid = -1;
1217 ++update;
1218 nd6log2((LOG_INFO, "%s: possible router %s, "
1219 "scoped=%d, static=%d\n", if_name(dr->ifp),
1220 ip6_sprintf(&dr->rtaddr),
1221 (dr->stateflags & NDDRF_IFSCOPE) ? 1 : 0,
1222 (dr->stateflags & NDDRF_STATIC) ? 1 : 0));
1223 }
1224 NDDR_REMREF(dr); /* for this for loop */
1225 continue;
1226 }
1227
1228 /* Record the currently installed primary/non-scoped router */
1229 if (!ip6_doscopedroute || !(dr->stateflags & NDDRF_IFSCOPE)) {
1230 if (installed_dr == NULL) {
1231 installed_dr = dr;
1232 NDDR_ADDREF(installed_dr);
9bccf70c 1233 } else {
6d2010ae
A
1234 /* this should not happen; warn for diagnosis */
1235 log(LOG_ERR, "defrouter_select: more than one "
1236 "%s default router is installed\n",
1237 ip6_doscopedroute ? "non-scoped" : "");
9bccf70c 1238 }
1c79356b 1239 }
6d2010ae 1240 NDDR_REMREF(dr); /* for this for loop */
1c79356b
A
1241 }
1242
6d2010ae
A
1243 /* If none was selected, use the currently installed one */
1244 if (ip6_doscopedroute && selected_dr == NULL && installed_dr != NULL) {
1245 selected_dr = installed_dr;
1246 NDDR_ADDREF(selected_dr);
1247 }
1c79356b 1248
6d2010ae
A
1249 /*
1250 * Install the unreachable one(s) if necesssary.
1251 */
1252 for (dr = TAILQ_FIRST(&nd_defrouter); dr;
1253 dr = TAILQ_NEXT(dr, dr_entry)) {
1254 struct nd_defrouter *_dr;
1c79356b 1255
6d2010ae
A
1256 if (!ip6_doscopedroute)
1257 break;
1258
1259 NDDR_LOCK(dr);
1260
1261 /* If already (or will be) installed, skip */
1262 if ((dr->stateflags & NDDRF_INSTALLED) || dr->genid == -1) {
1263 NDDR_UNLOCK(dr);
1264 continue;
1265 }
1266
1267 /* See if there is already a default router for the link */
1268 for (_dr = TAILQ_FIRST(&nd_defrouter); _dr;
1269 _dr = TAILQ_NEXT(_dr, dr_entry)) {
1270 if (_dr != dr)
1271 NDDR_LOCK(_dr);
1272 if (_dr == dr || _dr->ifp != dr->ifp) {
1273 if (_dr != dr)
1274 NDDR_UNLOCK(_dr);
1275 continue;
1276 }
1277
1278 if ((_dr->stateflags & NDDRF_INSTALLED) ||
1279 _dr->genid == -1) {
1280 if (_dr != dr)
1281 NDDR_UNLOCK(_dr);
1282 break;
1283 }
1284 if (_dr != dr)
1285 NDDR_UNLOCK(_dr);
1286 }
1287
1288 /* If none so far, schedule it to be installed below */
1289 if (_dr == NULL) {
1290 dr->genid = -1;
1291 ++update;
1292 nd6log2((LOG_INFO, "%s: possible router %s, "
1293 "static=%d (unreachable)\n", if_name(dr->ifp),
1294 ip6_sprintf(&dr->rtaddr),
1295 (dr->stateflags & NDDRF_STATIC) ? 1 : 0));
1296 }
1297 NDDR_UNLOCK(dr);
1298 }
1299
1300 dr = selected_dr;
1301 if (dr != NULL) {
1302 nd6log2((LOG_INFO, "%s: considering primary default router %s, "
1303 "static=%d [round 1]\n", if_name(dr->ifp),
1304 ip6_sprintf(&dr->rtaddr),
1305 (dr->stateflags & NDDRF_STATIC) ? 1 : 0));
1306 }
1307
1308 /*
1309 * If none of the default routers was found to be reachable,
1310 * round-robin the list regardless of preference, except when
1311 * Scoped Routing is enabled per case (c).
1312 *
1313 * Otherwise, if we have an installed router, check if the selected
1314 * (reachable) router should really be preferred to the installed one.
1315 * We only prefer the new router when the old one is not reachable
1316 * or when the new one has a really higher preference value.
1317 */
1318 if (!ip6_doscopedroute && selected_dr == NULL) {
1319 if (installed_dr == NULL ||
1320 !TAILQ_NEXT(installed_dr, dr_entry)) {
1321 selected_dr = TAILQ_FIRST(&nd_defrouter);
1322 if (selected_dr)
1323 NDDR_ADDREF(selected_dr);
1324 } else {
1325 selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
1326 if (selected_dr)
1327 NDDR_ADDREF(selected_dr);
1328 }
1329 } else if (selected_dr != NULL && installed_dr != NULL) {
1330 lck_mtx_unlock(nd6_mutex);
1331 rt = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp, 0);
1332 if (rt) {
1333 RT_LOCK_ASSERT_HELD(rt);
1334 if ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
1335 ND6_IS_LLINFO_PROBREACH(ln) &&
1336 (!ip6_doscopedroute ||
1337 installed_dr->ifp == nd6_defifp) &&
1338 rtpref(selected_dr) <= rtpref(installed_dr)) {
1339 NDDR_REMREF(selected_dr);
1340 selected_dr = installed_dr;
1341 NDDR_ADDREF(selected_dr);
1342 }
1343 RT_REMREF_LOCKED(rt);
1344 RT_UNLOCK(rt);
1345 rt = NULL;
1346 found_installedrt = TRUE;
1347 }
1348 lck_mtx_lock(nd6_mutex);
1349 }
1350
1351 if (ip6_doscopedroute) {
1352 /*
1353 * If the installed primary router is not on the current
1354 * IPv6 default interface, demote it to a scoped entry.
1355 */
1356 if (installed_dr != NULL && installed_dr->ifp != nd6_defifp &&
1357 !(installed_dr->stateflags & NDDRF_IFSCOPE)) {
1358 if (selected_dr != NULL &&
1359 selected_dr->ifp != nd6_defifp) {
1360 NDDR_REMREF(selected_dr);
1361 selected_dr = NULL;
1362 }
1363 ++update;
1364 }
1365
1366 /*
1367 * If the selected router is currently scoped, make sure
1368 * we update (it needs to be promoted to primary.)
1369 */
1370 if (selected_dr != NULL &&
1371 (selected_dr->stateflags & NDDRF_IFSCOPE))
1372 ++update;
1373
1374 /*
1375 * If the installed router is no longe reachable, remove
1376 * it and install the selected router instead.
1377 */
1378 if (installed_dr != NULL && selected_dr != NULL &&
1379 installed_dr != selected_dr && found_installedrt == FALSE) {
1380 installed_dr0 = installed_dr; /* skip it below */
1381 /* NB: we previousled referenced installed_dr */
1382 installed_dr = NULL;
1383 selected_dr->genid = -1;
1384 ++update;
1385 }
1386 }
1387
1388 /*
1389 * If Scoped Routing is enabled and there's nothing to update,
1390 * just return. Otherwise, if Scoped Routing is disabled and if
1391 * the selected router is different than the installed one,
1392 * remove the installed router and install the selected one.
1393 */
1394 dr = selected_dr;
1395 VERIFY(dr != NULL || ip6_doscopedroute);
1396 if (!ip6_doscopedroute || !update) {
1397 if (dr == NULL)
1398 goto out;
1399
1400 if (dr != installed_dr) {
1401 nd6log2((LOG_INFO, "%s: no update, selected router %s, "
1402 "installed router %s\n", if_name(dr->ifp),
1403 ip6_sprintf(&dr->rtaddr), installed_dr != NULL ?
1404 ip6_sprintf(&installed_dr->rtaddr) : "NONE"));
1405 } else {
1406 nd6log2((LOG_INFO, "%s: no update, router is %s\n",
1407 if_name(dr->ifp), ip6_sprintf(&dr->rtaddr)));
1408 }
1409 if (!ip6_doscopedroute && installed_dr != dr) {
1410 /*
1411 * No need to ADDREF dr because at this point
1412 * dr points to selected_dr, which already holds
1413 * a reference.
1414 */
1415 lck_mtx_unlock(nd6_mutex);
1416 if (installed_dr) {
1417 NDDR_LOCK(installed_dr);
1418 defrouter_delreq(installed_dr);
1419 NDDR_UNLOCK(installed_dr);
1420 }
1421 NDDR_LOCK(dr);
1422 defrouter_addreq(dr, FALSE);
1423 NDDR_UNLOCK(dr);
1424 lck_mtx_lock(nd6_mutex);
1425 }
1426 goto out;
1427 }
1428
1429 /*
1430 * Scoped Routing is enabled and we need to update. The selected
1431 * router needs to be installed as primary/non-scoped entry. If
1432 * there is any existing entry that is non-scoped, remove it from
1433 * the routing table and reinstall it as scoped entry.
1434 */
1435 if (dr != NULL) {
1436 nd6log2((LOG_INFO, "%s: considering primary default router %s, "
1437 "static=%d [round 2]\n", if_name(dr->ifp),
1438 ip6_sprintf(&dr->rtaddr),
1439 (dr->stateflags & NDDRF_STATIC) ? 1 : 0));
1440 }
1441
1442 /*
1443 * On the following while loops we use two flags:
1444 * dr->genid
1445 * NDDRF_PROCESSED
1446 *
1447 * genid is used to skip entries that are not to be added/removed on the
1448 * second while loop.
1449 * NDDRF_PROCESSED is used to skip entries that were already processed.
1450 * This is necessary because we drop the nd6_mutex and start the while
1451 * loop again.
1452 */
1453 TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
1454 NDDR_LOCK(dr);
1455 VERIFY((dr->stateflags & NDDRF_PROCESSED) == 0);
1456 NDDR_UNLOCK(dr);
1457 }
1458 /* Remove conflicting entries */
1459 dr = TAILQ_FIRST(&nd_defrouter);
1460 while (dr) {
1461 NDDR_LOCK(dr);
1462 if (!(dr->stateflags & NDDRF_INSTALLED) ||
1463 dr->stateflags & NDDRF_PROCESSED) {
1464 NDDR_UNLOCK(dr);
1465 dr = TAILQ_NEXT(dr, dr_entry);
1466 continue;
1467 }
1468 dr->stateflags |= NDDRF_PROCESSED;
1469
1470 /* A NULL selected_dr will remove primary default route */
1471 if ((dr == selected_dr && (dr->stateflags & NDDRF_IFSCOPE)) ||
1472 (dr != selected_dr && !(dr->stateflags & NDDRF_IFSCOPE))) {
1473 NDDR_ADDREF_LOCKED(dr);
1474 NDDR_UNLOCK(dr);
1475 lck_mtx_unlock(nd6_mutex);
1476 NDDR_LOCK(dr);
1477 defrouter_delreq(dr);
1478 NDDR_UNLOCK(dr);
1479 lck_mtx_lock(nd6_mutex);
1480 NDDR_LOCK(dr);
1481 if (dr && dr != installed_dr0)
1482 dr->genid = -1;
1483 NDDR_UNLOCK(dr);
1484 NDDR_REMREF(dr);
1485 /*
1486 * Since we lost nd6_mutex, we have to start over.
1487 */
1488 dr = TAILQ_FIRST(&nd_defrouter);
1489 continue;
1490 }
1491 NDDR_UNLOCK(dr);
1492 dr = TAILQ_NEXT(dr, dr_entry);
1493 }
1494
1495 /* -1 is a special number, make sure we don't use it for genid */
1496 if (++nd6_defrouter_genid == -1)
1497 nd6_defrouter_genid = 1;
1498
1499 TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
1500 NDDR_LOCK(dr);
1501 dr->stateflags &= ~NDDRF_PROCESSED;
1502 NDDR_UNLOCK(dr);
1503 }
1504 /* Add the entries back */
1505 dr = TAILQ_FIRST(&nd_defrouter);
1506 while (dr) {
1507 struct nd_defrouter *_dr;
1508
1509 NDDR_LOCK(dr);
1510 if (dr->stateflags & NDDRF_PROCESSED ||
1511 dr->genid != -1) {
1512 NDDR_UNLOCK(dr);
1513 dr = TAILQ_NEXT(dr, dr_entry);
1514 continue;
1515 }
1516 dr->stateflags |= NDDRF_PROCESSED;
1517
1518 /* Handle case (b) */
1519 for (_dr = TAILQ_FIRST(&nd_defrouter); _dr;
1520 _dr = TAILQ_NEXT(_dr, dr_entry)) {
1521 if (_dr == dr)
1522 continue;
1523 /*
1524 * This is safe because we previously checked if
1525 * _dr == dr.
1526 */
1527 NDDR_LOCK(_dr);
1528 if (_dr->ifp == dr->ifp && rtpref(_dr) >= rtpref(dr) &&
1529 (_dr->stateflags & NDDRF_INSTALLED)) {
1530 NDDR_ADDREF_LOCKED(_dr);
1531 NDDR_UNLOCK(_dr);
1532 break;
1533 }
1534 NDDR_UNLOCK(_dr);
1535 }
1536
1537 /* If same preference and i/f, static entry takes precedence */
1538 if (_dr != NULL && rtpref(_dr) == rtpref(dr) &&
1539 !(_dr->stateflags & NDDRF_STATIC) &&
1540 (dr->stateflags & NDDRF_STATIC)) {
1541 lck_mtx_unlock(nd6_mutex);
1542 NDDR_LOCK(_dr);
1543 defrouter_delreq(_dr);
1544 NDDR_UNLOCK(_dr);
1545 lck_mtx_lock(nd6_mutex);
1546 NDDR_REMREF(_dr);
1547 _dr = NULL;
1548 }
1549
1550 if (_dr == NULL && !(dr->stateflags & NDDRF_INSTALLED)) {
1551 NDDR_ADDREF_LOCKED(dr);
1552 NDDR_UNLOCK(dr);
1553 lck_mtx_unlock(nd6_mutex);
1554 NDDR_LOCK(dr);
1555 defrouter_addreq(dr, (selected_dr == NULL ||
1556 dr->ifp != selected_dr->ifp));
1557 dr->genid = nd6_defrouter_genid;
1558 NDDR_UNLOCK(dr);
1559 lck_mtx_lock(nd6_mutex);
1560 NDDR_REMREF(dr);
1561 /*
1562 * Since we lost nd6_mutex, we have to start over.
1563 */
1564 dr = TAILQ_FIRST(&nd_defrouter);
1565 continue;
1566 }
1567 NDDR_UNLOCK(dr);
1568 dr = TAILQ_NEXT(dr, dr_entry);
1569 }
1570out:
1571 TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
1572 NDDR_LOCK(dr);
1573 dr->stateflags &= ~NDDRF_PROCESSED;
1574 NDDR_UNLOCK(dr);
1575 }
1576 if (selected_dr)
1577 NDDR_REMREF(selected_dr);
1578 if (installed_dr)
1579 NDDR_REMREF(installed_dr);
1580 if (installed_dr0)
1581 NDDR_REMREF(installed_dr0);
1582 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1583 VERIFY(nd_defrouter_busy);
1584 nd_defrouter_busy = FALSE;
1585 if (nd_defrouter_waiters > 0) {
1586 nd_defrouter_waiters = 0;
1587 wakeup(nd_defrouter_waitchan);
1588 }
1589}
1590
1591void
1592defrouter_select(struct ifnet *ifp)
1593{
1594 return (defrouter_select_common(ifp, 0));
1595}
1596
1597static struct nd_defrouter *
1598defrtrlist_update_common(struct nd_defrouter *new, boolean_t scoped)
1599{
1600 struct nd_defrouter *dr, *n;
1601 struct ifnet *ifp = new->ifp;
1602 struct nd_ifinfo *ndi;
1603
1604 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1605
1606 if ((dr = defrouter_lookup(&new->rtaddr, ifp)) != NULL) {
1607 /* entry exists */
1608 if (new->rtlifetime == 0) {
1609 defrtrlist_del(dr);
1610 NDDR_REMREF(dr);
1611 dr = NULL;
1612 } else {
1613 int oldpref = rtpref(dr);
1614
1615 /* override */
1616 dr->flags = new->flags; /* xxx flag check */
1c79356b
A
1617 dr->rtlifetime = new->rtlifetime;
1618 dr->expire = new->expire;
6d2010ae
A
1619
1620 /*
1621 * If the preference does not change, there's no need
1622 * to sort the entries. If Scoped Routing is enabled,
1623 * put the primary/non-scoped router at the top of the
1624 * list of routers in the same preference band, unless
1625 * it's already at that position.
1626 */
1627 if (ip6_doscopedroute) {
1628 struct nd_defrouter *p = NULL;
1629
1630 /* same preference and scoped; just return */
1631 if (rtpref(new) == oldpref && scoped)
1632 return (dr);
1633
1634 n = TAILQ_FIRST(&nd_defrouter);
1635 while (n != NULL) {
1636 /* preference changed; sort it */
1637 if (rtpref(new) != oldpref)
1638 break;
1639
1640 /* not at the top of band; sort it */
1641 if (n != dr && rtpref(n) == oldpref &&
1642 (!p || rtpref(p) > rtpref(n)))
1643 break;
1644
1645 p = n;
1646 n = TAILQ_NEXT(n, dr_entry);
1647 }
1648
1649 /* nothing has changed, just return */
1650 if (n == NULL && (scoped ||
1651 !(dr->stateflags & NDDRF_IFSCOPE)))
1652 return (dr);
1653 } else if (rtpref(new) == oldpref) {
1654 return (dr);
1655 }
1656
1657 /*
1658 * preferred router may be changed, so relocate
1659 * this router.
1660 * XXX: calling TAILQ_REMOVE directly is a bad manner.
1661 * However, since defrtrlist_del() has many side
1662 * effects, we intentionally do so here.
1663 * defrouter_select() below will handle routing
1664 * changes later.
1665 */
1666 TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
1667 new->stateflags = dr->stateflags;
1668 new->stateflags &= ~NDDRF_PROCESSED;
1669
1670 lck_rw_lock_shared(nd_if_rwlock);
1671 VERIFY(ifp->if_index < nd_ifinfo_indexlim);
1672 ndi = &nd_ifinfo[ifp->if_index];
1673 lck_rw_done(nd_if_rwlock);
1674 n = dr;
1675 goto insert;
1c79356b 1676 }
6d2010ae 1677 return (dr);
1c79356b
A
1678 }
1679
6d2010ae
A
1680 VERIFY(dr == NULL);
1681
1c79356b
A
1682 /* entry does not exist */
1683 if (new->rtlifetime == 0) {
1c79356b
A
1684 return(NULL);
1685 }
1686
6d2010ae 1687 n = nddr_alloc(M_WAITOK);
b0d623f7 1688 if (n == NULL) {
b0d623f7
A
1689 return(NULL);
1690 }
1691
1692 lck_rw_lock_shared(nd_if_rwlock);
6d2010ae 1693 ndi = &nd_ifinfo[ifp->if_index];
b0d623f7
A
1694 if (ifp->if_index >= nd_ifinfo_indexlim)
1695 goto freeit;
e2fac8b1
A
1696 if (ip6_maxifdefrouters >= 0 &&
1697 ndi->ndefrouters >= ip6_maxifdefrouters) {
b0d623f7
A
1698freeit:
1699 lck_rw_done(nd_if_rwlock);
6d2010ae 1700 nddr_free(n);
e2fac8b1
A
1701 return (NULL);
1702 }
6d2010ae
A
1703
1704 NDDR_ADDREF(n); /* for the nd_defrouter list */
1705 NDDR_ADDREF(n); /* for the caller */
1706
1707 ++nd6_defrouter_genid;
1708 atomic_add_32(&ndi->ndefrouters, 1);
b0d623f7 1709 lck_rw_done(nd_if_rwlock);
e2fac8b1 1710
6d2010ae
A
1711 nd6log2((LOG_INFO, "%s: allocating defrouter %s\n", if_name(ifp),
1712 ip6_sprintf(&new->rtaddr)));
1713
1714 NDDR_LOCK(n);
1715 memcpy(&n->rtaddr, &new->rtaddr, sizeof(n->rtaddr));
1716 n->flags = new->flags;
1717 n->stateflags = new->stateflags;
1718 n->stateflags &= ~NDDRF_PROCESSED;
1719 n->rtlifetime = new->rtlifetime;
1720 n->expire = new->expire;
1721 n->ifp = new->ifp;
1722 n->genid = new->genid;
1723 n->err = new->err;
1724 NDDR_UNLOCK(n);
1725insert:
1c79356b
A
1726
1727 /*
6d2010ae
A
1728 * Insert the new router in the Default Router List;
1729 * The Default Router List should be in the descending order
1730 * of router-preferece. When Scoped Routing is disabled, routers
1731 * with the same preference are sorted in the arriving time order;
1732 * otherwise, the first entry in the list of routers having the same
1733 * preference is the primary default router, when the interface used
1734 * by the entry is the default interface.
1c79356b 1735 */
b0d623f7 1736
6d2010ae
A
1737 /* insert at the end of the group */
1738 for (dr = TAILQ_FIRST(&nd_defrouter); dr;
1739 dr = TAILQ_NEXT(dr, dr_entry)) {
1740 if (rtpref(n) > rtpref(dr) ||
1741 (ip6_doscopedroute && !scoped && rtpref(n) == rtpref(dr)))
1742 break;
1743 }
1744 if (dr)
1745 TAILQ_INSERT_BEFORE(dr, n, dr_entry);
1746 else
1747 TAILQ_INSERT_TAIL(&nd_defrouter, n, dr_entry);
1748
1749 /* Ignore auto-configuration checks for static route entries */
1750 defrouter_select_common(ifp, (n->stateflags & NDDRF_STATIC));
1751
1752 return (n);
1753}
1754
1755static struct nd_defrouter *
1756defrtrlist_update(struct nd_defrouter *new)
1757{
1758 struct nd_defrouter *dr;
1759
1760 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1761 dr = defrtrlist_update_common(new,
1762 (nd6_defifp != NULL && new->ifp != nd6_defifp));
1763
1764 return (dr);
1765}
1766
1767static void
1768defrtrlist_sync(struct ifnet *ifp)
1769{
1770 struct nd_defrouter *dr, new;
1771
1772 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1773
1774 if (!ip6_doscopedroute) {
1775 defrouter_select(ifp);
1776 return;
1777 }
1778
1779 for (dr = TAILQ_FIRST(&nd_defrouter); dr;
1780 dr = TAILQ_NEXT(dr, dr_entry)) {
1781 NDDR_LOCK(dr);
1782 if (dr->ifp == ifp && (dr->stateflags & NDDRF_INSTALLED))
1783 break;
1784 NDDR_UNLOCK(dr);
1785 }
1786
1787 if (dr == NULL) {
1788 /*
1789 * Set ignore flag; the chosen default interface might
1790 * not be configured to accept RAs.
1791 */
1792 defrouter_select_common(ifp, 1);
1793 } else {
1794 memcpy(&new.rtaddr, &dr->rtaddr, sizeof(new.rtaddr));
1795 new.flags = dr->flags;
1796 new.stateflags = dr->stateflags;
1797 new.stateflags &= ~NDDRF_PROCESSED;
1798 new.rtlifetime = dr->rtlifetime;
1799 new.expire = dr->expire;
1800 new.ifp = dr->ifp;
1801 new.genid = dr->genid;
1802 new.err = dr->err;
1803 NDDR_UNLOCK(dr);
1804 dr = defrtrlist_update_common(&new, FALSE);
1805 if (dr)
1806 NDDR_REMREF(dr);
1807 }
1c79356b
A
1808}
1809
9bccf70c 1810static struct nd_pfxrouter *
6d2010ae 1811pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr)
1c79356b
A
1812{
1813 struct nd_pfxrouter *search;
6d2010ae 1814
91447636 1815 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
6d2010ae
A
1816 NDPR_LOCK_ASSERT_HELD(pr);
1817
1818 for (search = pr->ndpr_advrtrs.lh_first; search;
1819 search = search->pfr_next) {
1c79356b
A
1820 if (search->router == dr)
1821 break;
1822 }
1823
1824 return(search);
1825}
1826
1827static void
6d2010ae 1828pfxrtr_add(struct nd_prefix *pr, struct nd_defrouter *dr)
1c79356b
A
1829{
1830 struct nd_pfxrouter *new;
1831
91447636 1832 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
6d2010ae 1833 NDPR_LOCK_ASSERT_NOTHELD(pr);
91447636 1834
6d2010ae 1835 new = zalloc(ndprtr_zone);
1c79356b
A
1836 if (new == NULL)
1837 return;
1838 bzero(new, sizeof(*new));
1839 new->router = dr;
1840
6d2010ae 1841 NDPR_LOCK(pr);
1c79356b 1842 LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry);
6d2010ae
A
1843 NDPR_UNLOCK(pr);
1844
1845 pfxlist_onlink_check();
1c79356b
A
1846}
1847
1848static void
91447636
A
1849pfxrtr_del(
1850 struct nd_pfxrouter *pfr)
1c79356b 1851{
91447636 1852 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
1c79356b 1853 LIST_REMOVE(pfr, pfr_entry);
6d2010ae 1854 zfree(ndprtr_zone, pfr);
1c79356b
A
1855}
1856
1857struct nd_prefix *
6d2010ae 1858nd6_prefix_lookup(struct nd_prefix *pr)
1c79356b
A
1859{
1860 struct nd_prefix *search;
1861
91447636 1862 lck_mtx_lock(nd6_mutex);
1c79356b 1863 for (search = nd_prefix.lh_first; search; search = search->ndpr_next) {
6d2010ae 1864 NDPR_LOCK(search);
1c79356b
A
1865 if (pr->ndpr_ifp == search->ndpr_ifp &&
1866 pr->ndpr_plen == search->ndpr_plen &&
1867 in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
6d2010ae
A
1868 &search->ndpr_prefix.sin6_addr, pr->ndpr_plen)) {
1869 NDPR_ADDREF_LOCKED(search);
1870 NDPR_UNLOCK(search);
1c79356b
A
1871 break;
1872 }
6d2010ae 1873 NDPR_UNLOCK(search);
1c79356b 1874 }
91447636 1875 lck_mtx_unlock(nd6_mutex);
1c79356b
A
1876
1877 return(search);
1878}
1879
e2fac8b1
A
1880static void
1881purge_detached(struct ifnet *ifp)
1882{
1883 struct nd_prefix *pr, *pr_next;
1884 struct in6_ifaddr *ia;
1885 struct ifaddr *ifa, *ifa_next;
b0d623f7 1886
e2fac8b1
A
1887 lck_mtx_lock(nd6_mutex);
1888
6d2010ae
A
1889 pr = nd_prefix.lh_first;
1890repeat:
1891 while (pr) {
e2fac8b1 1892 pr_next = pr->ndpr_next;
6d2010ae 1893 NDPR_LOCK(pr);
e2fac8b1
A
1894 if (pr->ndpr_ifp != ifp ||
1895 IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) ||
1896 ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
6d2010ae
A
1897 !LIST_EMPTY(&pr->ndpr_advrtrs))) {
1898 NDPR_UNLOCK(pr);
1899 pr = pr_next;
e2fac8b1 1900 continue;
6d2010ae
A
1901 }
1902 NDPR_UNLOCK(pr);
b0d623f7 1903 ifnet_lock_shared(ifp);
e2fac8b1
A
1904 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa_next) {
1905 ifa_next = ifa->ifa_list.tqe_next;
6d2010ae
A
1906 IFA_LOCK(ifa);
1907 if (ifa->ifa_addr->sa_family != AF_INET6) {
1908 IFA_UNLOCK(ifa);
e2fac8b1 1909 continue;
6d2010ae 1910 }
e2fac8b1
A
1911 ia = (struct in6_ifaddr *)ifa;
1912 if ((ia->ia6_flags & IN6_IFF_AUTOCONF) ==
1913 IN6_IFF_AUTOCONF && ia->ia6_ndpr == pr) {
6d2010ae
A
1914 IFA_ADDREF_LOCKED(ifa); /* for us */
1915 IFA_UNLOCK(ifa);
b0d623f7
A
1916 /*
1917 * Purging the address requires writer access
1918 * to the address list, so drop the ifnet lock
1919 * now and repeat from beginning.
1920 */
1921 ifnet_lock_done(ifp);
6d2010ae
A
1922 lck_mtx_unlock(nd6_mutex);
1923 in6_purgeaddr(ifa);
1924 lck_mtx_lock(nd6_mutex);
1925 IFA_REMREF(ifa); /* drop ours */
1926 pr = nd_prefix.lh_first;
b0d623f7 1927 goto repeat;
e2fac8b1 1928 }
6d2010ae 1929 IFA_UNLOCK(ifa);
e2fac8b1 1930 }
b0d623f7 1931 ifnet_lock_done(ifp);
6d2010ae
A
1932 NDPR_LOCK(pr);
1933 if (pr->ndpr_addrcnt == 0) {
1934 NDPR_ADDREF_LOCKED(pr);
1935 prelist_remove(pr);
1936 NDPR_UNLOCK(pr);
1937 NDPR_REMREF(pr);
1938 } else {
1939 NDPR_UNLOCK(pr);
1940 }
1941 pr = pr_next;
e2fac8b1
A
1942 }
1943
1944 lck_mtx_unlock(nd6_mutex);
1945}
1946
9bccf70c 1947int
6d2010ae
A
1948nd6_prelist_add(struct nd_prefix *pr, struct nd_defrouter *dr,
1949 struct nd_prefix **newp, boolean_t force_scoped)
1c79356b 1950{
9bccf70c 1951 struct nd_prefix *new = NULL;
b0d623f7
A
1952 struct ifnet *ifp = pr->ndpr_ifp;
1953 struct nd_ifinfo *ndi = NULL;
6d2010ae
A
1954 int i, error;
1955 struct timeval timenow;
1956
1957 getmicrotime(&timenow);
e2fac8b1
A
1958
1959 if (ip6_maxifprefixes >= 0) {
b0d623f7
A
1960 lck_rw_lock_shared(nd_if_rwlock);
1961 if (ifp->if_index >= nd_ifinfo_indexlim) {
1962 lck_rw_done(nd_if_rwlock);
1963 return (EINVAL);
1964 }
1965 ndi = &nd_ifinfo[ifp->if_index];
1966 if (ndi->nprefixes >= ip6_maxifprefixes / 2) {
1967 lck_rw_done(nd_if_rwlock);
1968 purge_detached(ifp);
1969 lck_rw_lock_shared(nd_if_rwlock);
1970 /*
1971 * Refresh pointer since nd_ifinfo[] may have grown;
1972 * repeating the bounds check against nd_ifinfo_indexlim
1973 * isn't necessary since the array never shrinks.
1974 */
1975 ndi = &nd_ifinfo[ifp->if_index];
1976 }
1977 if (ndi->nprefixes >= ip6_maxifprefixes) {
1978 lck_rw_done(nd_if_rwlock);
e2fac8b1 1979 return(ENOMEM);
b0d623f7
A
1980 }
1981 lck_rw_done(nd_if_rwlock);
e2fac8b1 1982 }
1c79356b 1983
6d2010ae 1984 new = ndpr_alloc(M_WAITOK);
1c79356b
A
1985 if (new == NULL)
1986 return ENOMEM;
1c79356b 1987
6d2010ae
A
1988 NDPR_LOCK(new);
1989 NDPR_LOCK(pr);
1990 new->ndpr_ifp = pr->ndpr_ifp;
1991 new->ndpr_prefix = pr->ndpr_prefix;
1992 new->ndpr_plen = pr->ndpr_plen;
1993 new->ndpr_vltime = pr->ndpr_vltime;
1994 new->ndpr_pltime = pr->ndpr_pltime;
1995 new->ndpr_flags = pr->ndpr_flags;
1996 if (pr->ndpr_stateflags & NDPRF_STATIC)
1997 new->ndpr_stateflags |= NDPRF_STATIC;
1998 NDPR_UNLOCK(pr);
1999 if ((error = in6_init_prefix_ltimes(new)) != 0) {
2000 NDPR_UNLOCK(new);
2001 ndpr_free(new);
2002 return(error);
2003 }
2004 new->ndpr_lastupdate = timenow.tv_sec;
2005 if (newp != NULL) {
2006 *newp = new;
2007 NDPR_ADDREF_LOCKED(new); /* for caller */
2008 }
2009 /* initialization */
1c79356b
A
2010 LIST_INIT(&new->ndpr_advrtrs);
2011 in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen);
2012 /* make prefix in the canonical form */
2013 for (i = 0; i < 4; i++)
2014 new->ndpr_prefix.sin6_addr.s6_addr32[i] &=
2015 new->ndpr_mask.s6_addr32[i];
2016
6d2010ae
A
2017 NDPR_UNLOCK(new);
2018
91447636 2019 lck_mtx_lock(nd6_mutex);
6d2010ae 2020 /* link ndpr_entry to nd_prefix list */
1c79356b 2021 LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry);
6d2010ae
A
2022 new->ndpr_debug |= IFD_ATTACHED;
2023 NDPR_ADDREF(new); /* for nd_prefix list */
2d21ac55 2024
9bccf70c
A
2025 /* ND_OPT_PI_FLAG_ONLINK processing */
2026 if (new->ndpr_raf_onlink) {
2027 int e;
2028
6d2010ae
A
2029 if ((e = nd6_prefix_onlink_common(new, force_scoped,
2030 new->ndpr_ifp->if_index)) != 0) {
9bccf70c 2031 nd6log((LOG_ERR, "nd6_prelist_add: failed to make "
6d2010ae
A
2032 "the prefix %s/%d on-link %s on %s (errno=%d)\n",
2033 ip6_sprintf(&new->ndpr_prefix.sin6_addr),
2034 new->ndpr_plen, force_scoped ? "scoped" :
2035 "non-scoped", if_name(ifp), e));
9bccf70c
A
2036 /* proceed anyway. XXX: is it correct? */
2037 }
2038 }
2039
1c79356b
A
2040 if (dr) {
2041 pfxrtr_add(new, dr);
1c79356b 2042 }
e2fac8b1 2043
b0d623f7
A
2044 lck_rw_lock_shared(nd_if_rwlock);
2045 /*
2046 * Refresh pointer since nd_ifinfo[] may have grown;
2047 * repeating the bounds check against nd_ifinfo_indexlim
2048 * isn't necessary since the array never shrinks.
2049 */
2050 ndi = &nd_ifinfo[ifp->if_index];
6d2010ae 2051 atomic_add_32(&ndi->nprefixes, 1);
b0d623f7 2052 lck_rw_done(nd_if_rwlock);
e2fac8b1 2053
91447636 2054 lck_mtx_unlock(nd6_mutex);
1c79356b
A
2055
2056 return 0;
2057}
2058
6d2010ae
A
2059/*
2060 * Caller must have held an extra reference on nd_prefix.
2061 */
1c79356b 2062void
6d2010ae 2063prelist_remove(struct nd_prefix *pr)
1c79356b
A
2064{
2065 struct nd_pfxrouter *pfr, *next;
b0d623f7 2066 struct ifnet *ifp = pr->ndpr_ifp;
91447636 2067 int e;
1c79356b 2068
6d2010ae
A
2069 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2070 NDPR_LOCK_ASSERT_HELD(pr);
2071
9bccf70c
A
2072 /* make sure to invalidate the prefix until it is really freed. */
2073 pr->ndpr_vltime = 0;
2074 pr->ndpr_pltime = 0;
6d2010ae 2075
9bccf70c
A
2076 /*
2077 * Though these flags are now meaningless, we'd rather keep the value
6d2010ae
A
2078 * of pr->ndpr_raf_onlink and pr->ndpr_raf_auto not to confuse users
2079 * when executing "ndp -p".
9bccf70c 2080 */
9bccf70c 2081
6d2010ae
A
2082 if ((pr->ndpr_stateflags & NDPRF_ONLINK)) {
2083 NDPR_ADDREF_LOCKED(pr);
2084 NDPR_UNLOCK(pr);
2085 lck_mtx_unlock(nd6_mutex);
2086 if ((e = nd6_prefix_offlink(pr)) != 0) {
2087 nd6log((LOG_ERR, "prelist_remove: failed to make "
2088 "%s/%d offlink on %s, errno=%d\n",
2089 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
2090 pr->ndpr_plen, if_name(ifp), e));
2091 /* what should we do? */
2092 }
91447636 2093 lck_mtx_lock(nd6_mutex);
6d2010ae
A
2094 NDPR_LOCK(pr);
2095 if (NDPR_REMREF_LOCKED(pr) == NULL)
2096 return;
2097 }
2d21ac55 2098
6d2010ae
A
2099 if (pr->ndpr_addrcnt > 0)
2100 return; /* notice here? */
2d21ac55 2101
1c79356b
A
2102 /* unlink ndpr_entry from nd_prefix list */
2103 LIST_REMOVE(pr, ndpr_entry);
6d2010ae 2104 pr->ndpr_debug &= ~IFD_ATTACHED;
1c79356b
A
2105
2106 /* free list of routers that adversed the prefix */
2107 for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
2108 next = pfr->pfr_next;
6d2010ae 2109 pfxrtr_del(pfr);
1c79356b 2110 }
9bccf70c 2111
b0d623f7
A
2112 lck_rw_lock_shared(nd_if_rwlock);
2113 if (ifp->if_index < nd_ifinfo_indexlim) {
2114 struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
6d2010ae 2115 atomic_add_32(&ndi->nprefixes, -1);
b0d623f7
A
2116 if (ndi->nprefixes < 0) {
2117 log(LOG_WARNING, "prelist_remove: negative "
2118 "count on %s\n", if_name(ifp));
2119 }
e2fac8b1 2120 }
b0d623f7 2121 lck_rw_done(nd_if_rwlock);
e2fac8b1 2122
6d2010ae
A
2123 /* This must not be the last reference to the nd_prefix */
2124 if (NDPR_REMREF_LOCKED(pr) == NULL) {
2125 panic("%s: unexpected (missing) refcnt ndpr=%p", __func__, pr);
2126 /* NOTREACHED */
2127 }
1c79356b 2128
6d2010ae 2129 pfxlist_onlink_check();
1c79356b
A
2130}
2131
1c79356b 2132int
91447636
A
2133prelist_update(
2134 struct nd_prefix *new,
2135 struct nd_defrouter *dr, /* may be NULL */
6d2010ae
A
2136 struct mbuf *m,
2137 int mcast)
1c79356b 2138{
9bccf70c
A
2139 struct in6_ifaddr *ia6 = NULL, *ia6_match = NULL;
2140 struct ifaddr *ifa;
2141 struct ifnet *ifp = new->ndpr_ifp;
1c79356b 2142 struct nd_prefix *pr;
1c79356b 2143 int error = 0;
9bccf70c 2144 int newprefix = 0;
1c79356b 2145 int auth;
9bccf70c 2146 struct in6_addrlifetime lt6_tmp;
91447636 2147 struct timeval timenow;
1c79356b 2148
6d2010ae
A
2149 /* no need to lock "new" here, as it is local to the caller */
2150 NDPR_LOCK_ASSERT_NOTHELD(new);
2151
1c79356b
A
2152 auth = 0;
2153 if (m) {
2154 /*
2155 * Authenticity for NA consists authentication for
2156 * both IP header and IP datagrams, doesn't it ?
2157 */
2158#if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
2159 auth = (m->m_flags & M_AUTHIPHDR
2160 && m->m_flags & M_AUTHIPDGM) ? 1 : 0;
2161#endif
2162 }
2163
9bccf70c
A
2164
2165 if ((pr = nd6_prefix_lookup(new)) != NULL) {
2166 /*
2167 * nd6_prefix_lookup() ensures that pr and new have the same
2168 * prefix on a same interface.
2169 */
2170
2171 /*
2172 * Update prefix information. Note that the on-link (L) bit
2173 * and the autonomous (A) bit should NOT be changed from 1
2174 * to 0.
2175 */
6d2010ae
A
2176 lck_mtx_lock(nd6_mutex);
2177 NDPR_LOCK(pr);
9bccf70c
A
2178 if (new->ndpr_raf_onlink == 1)
2179 pr->ndpr_raf_onlink = 1;
2180 if (new->ndpr_raf_auto == 1)
2181 pr->ndpr_raf_auto = 1;
2182 if (new->ndpr_raf_onlink) {
2183 pr->ndpr_vltime = new->ndpr_vltime;
2184 pr->ndpr_pltime = new->ndpr_pltime;
2185 pr->ndpr_preferred = new->ndpr_preferred;
2186 pr->ndpr_expire = new->ndpr_expire;
1c79356b
A
2187 }
2188
9bccf70c
A
2189 if (new->ndpr_raf_onlink &&
2190 (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
2191 int e;
2192
6d2010ae
A
2193 NDPR_UNLOCK(pr);
2194 if ((e = nd6_prefix_onlink(pr)) != 0) {
9bccf70c
A
2195 nd6log((LOG_ERR,
2196 "prelist_update: failed to make "
2197 "the prefix %s/%d on-link on %s "
2198 "(errno=%d)\n",
2199 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
2200 pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
2201 /* proceed anyway. XXX: is it correct? */
2202 }
6d2010ae 2203 NDPR_LOCK(pr);
1c79356b 2204 }
6d2010ae
A
2205
2206 if (dr && pfxrtr_lookup(pr, dr) == NULL) {
2207 NDPR_UNLOCK(pr);
9bccf70c 2208 pfxrtr_add(pr, dr);
6d2010ae
A
2209 } else {
2210 NDPR_UNLOCK(pr);
2211 }
91447636 2212 lck_mtx_unlock(nd6_mutex);
9bccf70c
A
2213 } else {
2214 struct nd_prefix *newpr = NULL;
2215
2216 newprefix = 1;
2217
2218 if (new->ndpr_vltime == 0)
2219 goto end;
2220 if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0)
2221 goto end;
2222
2223 bzero(&new->ndpr_addr, sizeof(struct in6_addr));
2224
6d2010ae 2225 error = nd6_prelist_add(new, dr, &newpr, FALSE);
9bccf70c
A
2226 if (error != 0 || newpr == NULL) {
2227 nd6log((LOG_NOTICE, "prelist_update: "
2228 "nd6_prelist_add failed for %s/%d on %s "
2229 "errno=%d, returnpr=%p\n",
2230 ip6_sprintf(&new->ndpr_prefix.sin6_addr),
2231 new->ndpr_plen, if_name(new->ndpr_ifp),
2232 error, newpr));
2233 goto end; /* we should just give up in this case. */
2234 }
1c79356b
A
2235
2236 /*
9bccf70c
A
2237 * XXX: from the ND point of view, we can ignore a prefix
2238 * with the on-link bit being zero. However, we need a
2239 * prefix structure for references from autoconfigured
6d2010ae 2240 * addresses. Thus, we explicitly make sure that the prefix
9bccf70c 2241 * itself expires now.
1c79356b 2242 */
6d2010ae 2243 NDPR_LOCK(newpr);
9bccf70c
A
2244 if (newpr->ndpr_raf_onlink == 0) {
2245 newpr->ndpr_vltime = 0;
2246 newpr->ndpr_pltime = 0;
2247 in6_init_prefix_ltimes(newpr);
2248 }
1c79356b 2249
9bccf70c 2250 pr = newpr;
6d2010ae 2251 NDPR_UNLOCK(newpr);
9bccf70c 2252 }
1c79356b 2253
9bccf70c
A
2254 /*
2255 * Address autoconfiguration based on Section 5.5.3 of RFC 2462.
2256 * Note that pr must be non NULL at this point.
2257 */
1c79356b 2258
9bccf70c
A
2259 /* 5.5.3 (a). Ignore the prefix without the A bit set. */
2260 if (!new->ndpr_raf_auto)
2261 goto afteraddrconf;
1c79356b 2262
9bccf70c
A
2263 /*
2264 * 5.5.3 (b). the link-local prefix should have been ignored in
2265 * nd6_ra_input.
2266 */
1c79356b 2267
6d2010ae
A
2268 /* 5.5.3 (c). Consistency check on lifetimes: pltime <= vltime. */
2269 if (new->ndpr_pltime > new->ndpr_vltime) {
2270 error = EINVAL; /* XXX: won't be used */
2271 goto end;
2272 }
2273
9bccf70c 2274 /*
6d2010ae
A
2275 * 5.5.3 (d). If the prefix advertised is not equal to the prefix of
2276 * an address configured by stateless autoconfiguration already in the
2277 * list of addresses associated with the interface, and the Valid
2278 * Lifetime is not 0, form an address. We first check if we have
2279 * a matching prefix.
2280 * Note: we apply a clarification in rfc2462bis-02 here. We only
2281 * consider autoconfigured addresses while RFC2462 simply said
2282 * "address".
9bccf70c 2283 */
1c79356b 2284
6d2010ae 2285 getmicrotime(&timenow);
91447636 2286
6d2010ae 2287 ifnet_lock_shared(ifp);
9bccf70c
A
2288 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
2289 {
2290 struct in6_ifaddr *ifa6;
6d2010ae 2291 u_int32_t remaininglifetime;
1c79356b 2292
6d2010ae
A
2293 IFA_LOCK(ifa);
2294 if (ifa->ifa_addr->sa_family != AF_INET6) {
2295 IFA_UNLOCK(ifa);
9bccf70c 2296 continue;
6d2010ae 2297 }
9bccf70c 2298 ifa6 = (struct in6_ifaddr *)ifa;
1c79356b 2299
6d2010ae
A
2300 /*
2301 * We only consider autoconfigured addresses as per rfc2462bis.
2302 */
2303 if (!(ifa6->ia6_flags & IN6_IFF_AUTOCONF)) {
2304 IFA_UNLOCK(ifa);
2305 continue;
2306 }
9bccf70c
A
2307 /*
2308 * Spec is not clear here, but I believe we should concentrate
2309 * on unicast (i.e. not anycast) addresses.
2310 * XXX: other ia6_flags? detached or duplicated?
2311 */
6d2010ae
A
2312 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0) {
2313 IFA_UNLOCK(ifa);
9bccf70c 2314 continue;
6d2010ae
A
2315 }
2316 /*
2317 * Ignore the address if it is not associated with a prefix
2318 * or is associated with a prefix that is different from this
2319 * one. (pr is never NULL here)
2320 */
2321 if (ifa6->ia6_ndpr != pr) {
2322 IFA_UNLOCK(ifa);
9bccf70c 2323 continue;
6d2010ae 2324 }
1c79356b 2325
6d2010ae 2326 if (ia6_match == NULL) { /* remember the first one */
9bccf70c 2327 ia6_match = ifa6;
6d2010ae
A
2328 IFA_ADDREF_LOCKED(ifa); /* for ia6_match */
2329 }
1c79356b 2330
9bccf70c
A
2331 /*
2332 * An already autoconfigured address matched. Now that we
2333 * are sure there is at least one matched address, we can
2334 * proceed to 5.5.3. (e): update the lifetimes according to the
2335 * "two hours" rule and the privacy extension.
6d2010ae
A
2336 * We apply some clarifications in rfc2462bis:
2337 * - use remaininglifetime instead of storedlifetime as a
2338 * variable name
2339 * - remove the dead code in the "two-hour" rule
9bccf70c
A
2340 */
2341#define TWOHOUR (120*60)
2342 lt6_tmp = ifa6->ia6_lifetime;
2343
6d2010ae
A
2344 if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
2345 remaininglifetime = ND6_INFINITE_LIFETIME;
2346 else if (timenow.tv_sec - ifa6->ia6_updatetime >
2347 lt6_tmp.ia6t_vltime) {
2348 /*
2349 * The case of "invalid" address. We should usually
2350 * not see this case.
2351 */
2352 remaininglifetime = 0;
2353 } else
2354 remaininglifetime = lt6_tmp.ia6t_vltime -
2355 (timenow.tv_sec - ifa6->ia6_updatetime);
2356
2357 /* when not updating, keep the current stored lifetime. */
2358 lt6_tmp.ia6t_vltime = remaininglifetime;
1c79356b 2359
9bccf70c 2360 if (TWOHOUR < new->ndpr_vltime ||
6d2010ae 2361 remaininglifetime < new->ndpr_vltime) {
9bccf70c 2362 lt6_tmp.ia6t_vltime = new->ndpr_vltime;
6d2010ae 2363 } else if (remaininglifetime <= TWOHOUR) {
9bccf70c
A
2364 if (auth) {
2365 lt6_tmp.ia6t_vltime = new->ndpr_vltime;
2366 }
2367 } else {
1c79356b 2368 /*
9bccf70c 2369 * new->ndpr_vltime <= TWOHOUR &&
6d2010ae 2370 * TWOHOUR < remaininglifetime
1c79356b 2371 */
9bccf70c 2372 lt6_tmp.ia6t_vltime = TWOHOUR;
1c79356b 2373 }
1c79356b 2374
9bccf70c
A
2375 /* The 2 hour rule is not imposed for preferred lifetime. */
2376 lt6_tmp.ia6t_pltime = new->ndpr_pltime;
1c79356b 2377
6d2010ae 2378 /* Special handling for lifetimes of temporary addresses. */
9bccf70c 2379 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
6d2010ae
A
2380 u_int32_t maxvltime, maxpltime;
2381
2382 /* Constrain lifetimes to system limits. */
2383 if (lt6_tmp.ia6t_vltime > ip6_temp_valid_lifetime)
2384 lt6_tmp.ia6t_vltime = ip6_temp_valid_lifetime;
2385 if (lt6_tmp.ia6t_pltime > ip6_temp_preferred_lifetime)
2386 lt6_tmp.ia6t_pltime =
2387 ip6_temp_preferred_lifetime -
2388 ip6_desync_factor;
2389
2390 /*
2391 * According to RFC 4941, section 3.3 (1), we only
2392 * update the lifetimes when they are in the maximum
2393 * intervals.
2394 */
2395 if (ip6_temp_valid_lifetime >
2396 (u_int32_t)((timenow.tv_sec - ifa6->ia6_createtime) +
2397 ip6_desync_factor)) {
2398 maxvltime = ip6_temp_valid_lifetime -
2399 (timenow.tv_sec - ifa6->ia6_createtime) -
2400 ip6_desync_factor;
2401 } else
2402 maxvltime = 0;
2403 if (ip6_temp_preferred_lifetime >
2404 (u_int32_t)((timenow.tv_sec - ifa6->ia6_createtime) +
2405 ip6_desync_factor)) {
2406 maxpltime = ip6_temp_preferred_lifetime -
2407 (timenow.tv_sec - ifa6->ia6_createtime) -
2408 ip6_desync_factor;
2409 } else
2410 maxpltime = 0;
2411
2412 if (lt6_tmp.ia6t_vltime > maxvltime)
2413 lt6_tmp.ia6t_vltime = maxvltime;
2414 if (lt6_tmp.ia6t_pltime > maxpltime)
2415 lt6_tmp.ia6t_pltime = maxpltime;
1c79356b 2416 }
1c79356b 2417
6d2010ae
A
2418 in6_init_address_ltimes(pr, &lt6_tmp,
2419 !!(ifa6->ia6_flags & IN6_IFF_TEMPORARY));
2420
9bccf70c 2421 ifa6->ia6_lifetime = lt6_tmp;
6d2010ae
A
2422 ifa6->ia6_updatetime = timenow.tv_sec;
2423 IFA_UNLOCK(ifa);
9bccf70c 2424 }
91447636 2425 ifnet_lock_done(ifp);
9bccf70c 2426 if (ia6_match == NULL && new->ndpr_vltime) {
6d2010ae
A
2427 int ifidlen;
2428
9bccf70c 2429 /*
6d2010ae 2430 * 5.5.3 (d) (continued)
9bccf70c
A
2431 * No address matched and the valid lifetime is non-zero.
2432 * Create a new address.
2433 */
6d2010ae
A
2434
2435 /*
2436 * Prefix Length check:
2437 * If the sum of the prefix length and interface identifier
2438 * length does not equal 128 bits, the Prefix Information
2439 * option MUST be ignored. The length of the interface
2440 * identifier is defined in a separate link-type specific
2441 * document.
2442 */
2443 ifidlen = in6_if2idlen(ifp);
2444 if (ifidlen < 0) {
2445 /* this should not happen, so we always log it. */
2446 log(LOG_ERR, "prelist_update: IFID undefined (%s)\n",
2447 if_name(ifp));
2448 goto end;
2449 }
2450 NDPR_LOCK(pr);
2451 if (ifidlen + pr->ndpr_plen != 128) {
2452 nd6log((LOG_INFO,
2453 "prelist_update: invalid prefixlen "
2454 "%d for %s, ignored\n",
2455 pr->ndpr_plen, if_name(ifp)));
2456 NDPR_UNLOCK(pr);
2457 goto end;
2458 }
2459 NDPR_UNLOCK(pr);
2460
2461 if ((ia6 = in6_ifadd(new, mcast)) != NULL) {
9bccf70c
A
2462 /*
2463 * note that we should use pr (not new) for reference.
2464 */
6d2010ae
A
2465 IFA_LOCK(&ia6->ia_ifa);
2466 NDPR_LOCK(pr);
9bccf70c 2467 ia6->ia6_ndpr = pr;
6d2010ae
A
2468 NDPR_ADDREF_LOCKED(pr); /* for addr reference */
2469 pr->ndpr_addrcnt++;
2470 VERIFY(pr->ndpr_addrcnt != 0);
2471 NDPR_UNLOCK(pr);
2472 IFA_UNLOCK(&ia6->ia_ifa);
1c79356b 2473
9bccf70c 2474 /*
6d2010ae 2475 * RFC 4941 3.3 (2).
9bccf70c
A
2476 * When a new public address is created as described
2477 * in RFC2462, also create a new temporary address.
2478 *
6d2010ae 2479 * RFC 4941 3.5.
9bccf70c
A
2480 * When an interface connects to a new link, a new
2481 * randomized interface identifier should be generated
2482 * immediately together with a new set of temporary
2483 * addresses. Thus, we specifiy 1 as the 2nd arg of
2484 * in6_tmpifadd().
2485 */
2486 if (ip6_use_tempaddr) {
2487 int e;
6d2010ae 2488 if ((e = in6_tmpifadd(ia6, 1, M_WAITOK)) != 0) {
9bccf70c
A
2489 nd6log((LOG_NOTICE, "prelist_update: "
2490 "failed to create a temporary "
2491 "address, errno=%d\n",
2492 e));
2493 }
2494 }
6d2010ae 2495 IFA_REMREF(&ia6->ia_ifa);
b0d623f7 2496 ia6 = NULL;
1c79356b 2497
6d2010ae
A
2498 /*
2499 * A newly added address might affect the status
2500 * of other addresses, so we check and update it.
2501 * XXX: what if address duplication happens?
2502 */
2503 lck_mtx_lock(nd6_mutex);
2504 pfxlist_onlink_check();
2505 lck_mtx_unlock(nd6_mutex);
2506 } else {
2507 /* just set an error. do not bark here. */
2508 error = EADDRNOTAVAIL; /* XXX: might be unused. */
2509 }
2510 }
2511
2512afteraddrconf:
2513
2514end:
2515 if (pr != NULL)
2516 NDPR_REMREF(pr);
2517 if (ia6_match != NULL)
2518 IFA_REMREF(&ia6_match->ia_ifa);
2519 return error;
2520}
2521
2522/*
2523 * Neighbor Discover Default Router structure reference counting routines.
2524 */
2525static struct nd_defrouter *
2526nddr_alloc(int how)
2527{
2528 struct nd_defrouter *dr;
2529
2530 dr = (how == M_WAITOK) ? zalloc(nddr_zone) : zalloc_noblock(nddr_zone);
2531 if (dr != NULL) {
2532 bzero(dr, nddr_size);
2533 lck_mtx_init(&dr->nddr_lock, ifa_mtx_grp, ifa_mtx_attr);
2534 dr->nddr_debug |= IFD_ALLOC;
2535 if (nddr_debug != 0) {
2536 dr->nddr_debug |= IFD_DEBUG;
2537 dr->nddr_trace = nddr_trace;
2538 }
2539 }
2540 return (dr);
2541}
2542
2543static void
2544nddr_free(struct nd_defrouter *dr)
2545{
2546 NDDR_LOCK(dr);
2547 if (dr->nddr_debug & IFD_ATTACHED) {
2548 panic("%s: attached nddr %p is being freed", __func__, dr);
2549 /* NOTREACHED */
2550 } else if (!(dr->nddr_debug & IFD_ALLOC)) {
2551 panic("%s: nddr %p cannot be freed", __func__, dr);
2552 /* NOTREACHED */
2553 }
2554 dr->nddr_debug &= ~IFD_ALLOC;
2555 NDDR_UNLOCK(dr);
2556
2557 lck_mtx_destroy(&dr->nddr_lock, ifa_mtx_grp);
2558 zfree(nddr_zone, dr);
2559}
2560
2561static void
2562nddr_trace(struct nd_defrouter *dr, int refhold)
2563{
2564 struct nd_defrouter_dbg *dr_dbg = (struct nd_defrouter_dbg *)dr;
2565 ctrace_t *tr;
2566 uint32_t idx;
2567 uint16_t *cnt;
2568
2569 if (!(dr->nddr_debug & IFD_DEBUG)) {
2570 panic("%s: nddr %p has no debug structure", __func__, dr);
2571 /* NOTREACHED */
2572 }
2573 if (refhold) {
2574 cnt = &dr_dbg->nddr_refhold_cnt;
2575 tr = dr_dbg->nddr_refhold;
2576 } else {
2577 cnt = &dr_dbg->nddr_refrele_cnt;
2578 tr = dr_dbg->nddr_refrele;
2579 }
2580
2581 idx = atomic_add_16_ov(cnt, 1) % NDDR_TRACE_HIST_SIZE;
2582 ctrace_record(&tr[idx]);
2583}
2584
2585void
2586nddr_addref(struct nd_defrouter *nddr, int locked)
2587{
2588
2589 if (!locked)
2590 NDDR_LOCK_SPIN(nddr);
2591 else
2592 NDDR_LOCK_ASSERT_HELD(nddr);
2593
2594 if (++nddr->nddr_refcount == 0) {
2595 panic("%s: nddr %p wraparound refcnt\n", __func__, nddr);
2596 /* NOTREACHED */
2597 } else if (nddr->nddr_trace != NULL) {
2598 (*nddr->nddr_trace)(nddr, TRUE);
2599 }
2600
2601 if (!locked)
2602 NDDR_UNLOCK(nddr);
2603}
2604
2605struct nd_defrouter *
2606nddr_remref(struct nd_defrouter *nddr, int locked)
2607{
2608
2609 if (!locked)
2610 NDDR_LOCK_SPIN(nddr);
2611 else
2612 NDDR_LOCK_ASSERT_HELD(nddr);
2613
2614 if (nddr->nddr_refcount == 0) {
2615 panic("%s: nddr %p negative refcnt\n", __func__, nddr);
2616 /* NOTREACHED */
2617 } else if (nddr->nddr_trace != NULL) {
2618 (*nddr->nddr_trace)(nddr, FALSE);
2619 }
2620
2621 if (--nddr->nddr_refcount == 0) {
2622 NDDR_UNLOCK(nddr);
2623 nddr_free(nddr);
2624 nddr = NULL;
2625 }
2626
2627 if (!locked && nddr != NULL)
2628 NDDR_UNLOCK(nddr);
2629
2630 return (nddr);
2631}
2632
2633/*
2634 * Neighbor Discover Prefix structure reference counting routines.
2635 */
2636static struct nd_prefix *
2637ndpr_alloc(int how)
2638{
2639 struct nd_prefix *pr;
2640
2641 pr = (how == M_WAITOK) ? zalloc(ndpr_zone) : zalloc_noblock(ndpr_zone);
2642 if (pr != NULL) {
2643 bzero(pr, ndpr_size);
2644 lck_mtx_init(&pr->ndpr_lock, ifa_mtx_grp, ifa_mtx_attr);
2645 pr->ndpr_debug |= IFD_ALLOC;
2646 if (ndpr_debug != 0) {
2647 pr->ndpr_debug |= IFD_DEBUG;
2648 pr->ndpr_trace = ndpr_trace;
2649 }
2650 }
2651 return (pr);
2652}
2653
2654static void
2655ndpr_free(struct nd_prefix *pr)
2656{
2657 NDPR_LOCK(pr);
2658 if (pr->ndpr_debug & IFD_ATTACHED) {
2659 panic("%s: attached ndpr %p is being freed", __func__, pr);
2660 /* NOTREACHED */
2661 } else if (!(pr->ndpr_debug & IFD_ALLOC)) {
2662 panic("%s: ndpr %p cannot be freed", __func__, pr);
2663 /* NOTREACHED */
2664 }
2665 pr->ndpr_debug &= ~IFD_ALLOC;
2666 NDPR_UNLOCK(pr);
2667
2668 lck_mtx_destroy(&pr->ndpr_lock, ifa_mtx_grp);
2669 zfree(ndpr_zone, pr);
2670}
2671
2672static void
2673ndpr_trace(struct nd_prefix *pr, int refhold)
2674{
2675 struct nd_prefix_dbg *pr_dbg = (struct nd_prefix_dbg *)pr;
2676 ctrace_t *tr;
2677 u_int32_t idx;
2678 u_int16_t *cnt;
2679
2680 if (!(pr->ndpr_debug & IFD_DEBUG)) {
2681 panic("%s: ndpr %p has no debug structure", __func__, pr);
2682 /* NOTREACHED */
2683 }
2684 if (refhold) {
2685 cnt = &pr_dbg->ndpr_refhold_cnt;
2686 tr = pr_dbg->ndpr_refhold;
2687 } else {
2688 cnt = &pr_dbg->ndpr_refrele_cnt;
2689 tr = pr_dbg->ndpr_refrele;
2690 }
2691
2692 idx = atomic_add_16_ov(cnt, 1) % NDPR_TRACE_HIST_SIZE;
2693 ctrace_record(&tr[idx]);
2694}
2695
2696void
2697ndpr_addref(struct nd_prefix *ndpr, int locked)
2698{
2699 if (!locked)
2700 NDPR_LOCK_SPIN(ndpr);
2701 else
2702 NDPR_LOCK_ASSERT_HELD(ndpr);
2703
2704 if (++ndpr->ndpr_refcount == 0) {
2705 panic("%s: ndpr %p wraparound refcnt\n", __func__, ndpr);
2706 /* NOTREACHED */
2707 } else if (ndpr->ndpr_trace != NULL) {
2708 (*ndpr->ndpr_trace)(ndpr, TRUE);
2709 }
2710
2711 if (!locked)
2712 NDPR_UNLOCK(ndpr);
2713}
2714
2715struct nd_prefix *
2716ndpr_remref(struct nd_prefix *ndpr, int locked)
2717{
2718 if (!locked)
2719 NDPR_LOCK_SPIN(ndpr);
2720 else
2721 NDPR_LOCK_ASSERT_HELD(ndpr);
2722
2723 if (ndpr->ndpr_refcount == 0) {
2724 panic("%s: ndpr %p negative refcnt\n", __func__, ndpr);
2725 /* NOTREACHED */
2726 } else if (ndpr->ndpr_trace != NULL) {
2727 (*ndpr->ndpr_trace)(ndpr, FALSE);
1c79356b
A
2728 }
2729
6d2010ae
A
2730 if (--ndpr->ndpr_refcount == 0) {
2731 if (ndpr->ndpr_addrcnt != 0) {
2732 panic("%s: freeing ndpr %p with outstanding address "
2733 "reference (%d)", __func__, ndpr,
2734 ndpr->ndpr_addrcnt);
2735 /* NOTREACHED */
2736 }
2737 NDPR_UNLOCK(ndpr);
2738 ndpr_free(ndpr);
2739 ndpr = NULL;
2740 }
2d21ac55 2741
6d2010ae
A
2742 if (!locked && ndpr != NULL)
2743 NDPR_UNLOCK(ndpr);
9bccf70c 2744
6d2010ae 2745 return (ndpr);
1c79356b
A
2746}
2747
2748/*
2749 * A supplement function used in the on-link detection below;
2750 * detect if a given prefix has a (probably) reachable advertising router.
2751 * XXX: lengthy function name...
2752 */
9bccf70c 2753static struct nd_pfxrouter *
6d2010ae 2754find_pfxlist_reachable_router(struct nd_prefix *pr)
1c79356b
A
2755{
2756 struct nd_pfxrouter *pfxrtr;
2757 struct rtentry *rt;
2758 struct llinfo_nd6 *ln;
2759
91447636 2760 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
6d2010ae 2761 NDPR_LOCK_ASSERT_HELD(pr);
91447636 2762
1c79356b
A
2763 for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
2764 pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
6d2010ae
A
2765 NDPR_UNLOCK(pr);
2766 lck_mtx_unlock(nd6_mutex);
b0d623f7 2767 /* Callee returns a locked route upon success */
1c79356b 2768 if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
b0d623f7
A
2769 pfxrtr->router->ifp, 0)) != NULL) {
2770 RT_LOCK_ASSERT_HELD(rt);
2771 if ((ln = rt->rt_llinfo) != NULL &&
2772 ND6_IS_LLINFO_PROBREACH(ln)) {
2773 RT_REMREF_LOCKED(rt);
2774 RT_UNLOCK(rt);
6d2010ae
A
2775 lck_mtx_lock(nd6_mutex);
2776 NDPR_LOCK(pr);
b0d623f7
A
2777 break; /* found */
2778 }
2779 RT_REMREF_LOCKED(rt);
2780 RT_UNLOCK(rt);
2781 }
6d2010ae
A
2782 lck_mtx_lock(nd6_mutex);
2783 NDPR_LOCK(pr);
1c79356b 2784 }
6d2010ae 2785 NDPR_LOCK_ASSERT_HELD(pr);
1c79356b 2786
6d2010ae 2787 return (pfxrtr);
1c79356b
A
2788
2789}
2790
2791/*
2792 * Check if each prefix in the prefix list has at least one available router
9bccf70c
A
2793 * that advertised the prefix (a router is "available" if its neighbor cache
2794 * entry is reachable or probably reachable).
1c79356b
A
2795 * If the check fails, the prefix may be off-link, because, for example,
2796 * we have moved from the network but the lifetime of the prefix has not
9bccf70c
A
2797 * expired yet. So we should not use the prefix if there is another prefix
2798 * that has an available router.
2799 * But, if there is no prefix that has an available router, we still regards
2800 * all the prefixes as on-link. This is because we can't tell if all the
1c79356b
A
2801 * routers are simply dead or if we really moved from the network and there
2802 * is no router around us.
2803 */
2804void
6d2010ae 2805pfxlist_onlink_check(void)
1c79356b 2806{
6d2010ae 2807 struct nd_prefix *pr, *prclear;
9bccf70c 2808 struct in6_ifaddr *ifa;
6d2010ae
A
2809 struct nd_defrouter *dr;
2810 struct nd_pfxrouter *pfxrtr = NULL;
2811
2812 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2813
2814 while (nd_prefix_busy) {
2815 nd_prefix_waiters++;
2816 msleep(nd_prefix_waitchan, nd6_mutex, (PZERO-1),
2817 __func__, NULL);
2818 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
2819 }
2820 nd_prefix_busy = TRUE;
1c79356b
A
2821
2822 /*
2823 * Check if there is a prefix that has a reachable advertising
2824 * router.
2825 */
6d2010ae
A
2826 pr = nd_prefix.lh_first;
2827 while (pr) {
2828 NDPR_LOCK(pr);
2829 if (pr->ndpr_stateflags & NDPRF_PROCESSED) {
2830 NDPR_UNLOCK(pr);
2831 pr = pr->ndpr_next;
2832 continue;
2833 }
2834 NDPR_ADDREF_LOCKED(pr);
2835 if (pr->ndpr_raf_onlink && find_pfxlist_reachable_router(pr) &&
2836 (pr->ndpr_debug & IFD_ATTACHED)) {
2837 NDPR_UNLOCK(pr);
2838 NDPR_REMREF(pr);
1c79356b 2839 break;
6d2010ae
A
2840 }
2841 pr->ndpr_stateflags |= NDPRF_PROCESSED;
2842 NDPR_UNLOCK(pr);
2843 NDPR_REMREF(pr);
2844 /*
2845 * Since find_pfxlist_reachable_router() drops the nd6_mutex, we
2846 * have to start over, but the NDPRF_PROCESSED flag will stop
2847 * us from checking the same prefix twice.
2848 */
2849 pr = nd_prefix.lh_first;
2850 }
2851 LIST_FOREACH(prclear, &nd_prefix, ndpr_entry) {
2852 NDPR_LOCK(prclear);
2853 prclear->ndpr_stateflags &= ~NDPRF_PROCESSED;
2854 NDPR_UNLOCK(prclear);
1c79356b
A
2855 }
2856
6d2010ae
A
2857 /*
2858 * If we have no such prefix, check whether we still have a router
2859 * that does not advertise any prefixes.
2860 */
2861 if (pr == NULL) {
2862 for (dr = TAILQ_FIRST(&nd_defrouter); dr;
2863 dr = TAILQ_NEXT(dr, dr_entry)) {
2864 struct nd_prefix *pr0;
2865
2866 for (pr0 = nd_prefix.lh_first; pr0;
2867 pr0 = pr0->ndpr_next) {
2868 NDPR_LOCK(pr0);
2869 if ((pfxrtr = pfxrtr_lookup(pr0, dr)) != NULL) {
2870 NDPR_UNLOCK(pr0);
2871 break;
2872 }
2873 NDPR_UNLOCK(pr0);
2874 }
2875 if (pfxrtr != NULL)
2876 break;
2877 }
2878 }
2879 if (pr != NULL || (TAILQ_FIRST(&nd_defrouter) && pfxrtr == NULL)) {
1c79356b 2880 /*
6d2010ae
A
2881 * There is at least one prefix that has a reachable router,
2882 * or at least a router which probably does not advertise
2883 * any prefixes. The latter would be the case when we move
2884 * to a new link where we have a router that does not provide
2885 * prefixes and we configure an address by hand.
9bccf70c
A
2886 * Detach prefixes which have no reachable advertising
2887 * router, and attach other prefixes.
1c79356b 2888 */
6d2010ae
A
2889 pr = nd_prefix.lh_first;
2890 while (pr) {
2891 NDPR_LOCK(pr);
9bccf70c 2892 /*
6d2010ae
A
2893 * We aren't interested prefixes already processed,
2894 * nor in prefixes without the L bit
2895 * set nor in static prefixes
9bccf70c 2896 */
6d2010ae
A
2897 if (pr->ndpr_raf_onlink == 0 ||
2898 pr->ndpr_stateflags & NDPRF_PROCESSED ||
2899 pr->ndpr_stateflags & NDPRF_STATIC) {
2900 NDPR_UNLOCK(pr);
2901 pr = pr->ndpr_next;
9bccf70c 2902 continue;
6d2010ae
A
2903 }
2904 NDPR_ADDREF_LOCKED(pr);
9bccf70c 2905 if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
6d2010ae
A
2906 find_pfxlist_reachable_router(pr) == NULL &&
2907 (pr->ndpr_debug & IFD_ATTACHED))
9bccf70c
A
2908 pr->ndpr_stateflags |= NDPRF_DETACHED;
2909 if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
6d2010ae
A
2910 find_pfxlist_reachable_router(pr) != NULL &&
2911 (pr->ndpr_debug & IFD_ATTACHED))
9bccf70c 2912 pr->ndpr_stateflags &= ~NDPRF_DETACHED;
6d2010ae
A
2913 pr->ndpr_stateflags |= NDPRF_PROCESSED;
2914 NDPR_UNLOCK(pr);
2915 NDPR_REMREF(pr);
2916 /*
2917 * Since find_pfxlist_reachable_router() drops the
2918 * nd6_mutex, we have to start over, but the
2919 * NDPRF_PROCESSED flag will stop us from checking
2920 * the same prefix twice.
2921 */
2922 pr = nd_prefix.lh_first;
1c79356b 2923 }
9bccf70c
A
2924 } else {
2925 /* there is no prefix that has a reachable router */
1c79356b 2926 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
6d2010ae
A
2927 NDPR_LOCK(pr);
2928 if (pr->ndpr_raf_onlink == 0 ||
2929 pr->ndpr_stateflags & NDPRF_STATIC) {
2930 NDPR_UNLOCK(pr);
9bccf70c 2931 continue;
6d2010ae 2932 }
9bccf70c
A
2933 if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0)
2934 pr->ndpr_stateflags &= ~NDPRF_DETACHED;
6d2010ae 2935 NDPR_UNLOCK(pr);
9bccf70c
A
2936 }
2937 }
6d2010ae
A
2938 LIST_FOREACH(prclear, &nd_prefix, ndpr_entry) {
2939 NDPR_LOCK(prclear);
2940 prclear->ndpr_stateflags &= ~NDPRF_PROCESSED;
2941 NDPR_UNLOCK(prclear);
2942 }
2943 VERIFY(nd_prefix_busy);
2944 nd_prefix_busy = FALSE;
2945 if (nd_prefix_waiters > 0) {
2946 nd_prefix_waiters = 0;
2947 wakeup(nd_prefix_waitchan);
2948 }
9bccf70c
A
2949
2950 /*
2951 * Remove each interface route associated with a (just) detached
2952 * prefix, and reinstall the interface route for a (just) attached
2953 * prefix. Note that all attempt of reinstallation does not
2954 * necessarily success, when a same prefix is shared among multiple
2955 * interfaces. Such cases will be handled in nd6_prefix_onlink,
2956 * so we don't have to care about them.
2957 */
6d2010ae
A
2958 pr = nd_prefix.lh_first;
2959 while (pr) {
9bccf70c
A
2960 int e;
2961
6d2010ae
A
2962 NDPR_LOCK(pr);
2963 if (pr->ndpr_raf_onlink == 0 ||
2964 pr->ndpr_stateflags & NDPRF_STATIC) {
2965 NDPR_UNLOCK(pr);
2966 pr = pr->ndpr_next;
9bccf70c 2967 continue;
6d2010ae 2968 }
9bccf70c
A
2969 if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
2970 (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
6d2010ae
A
2971 NDPR_UNLOCK(pr);
2972 lck_mtx_unlock(nd6_mutex);
9bccf70c
A
2973 if ((e = nd6_prefix_offlink(pr)) != 0) {
2974 nd6log((LOG_ERR,
2975 "pfxlist_onlink_check: failed to "
2976 "make %s/%d offlink, errno=%d\n",
2977 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
2978 pr->ndpr_plen, e));
2979 }
6d2010ae
A
2980 lck_mtx_lock(nd6_mutex);
2981 pr = nd_prefix.lh_first;
2982 continue;
9bccf70c
A
2983 }
2984 if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
2985 (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 &&
2986 pr->ndpr_raf_onlink) {
6d2010ae
A
2987 NDPR_UNLOCK(pr);
2988 if ((e = nd6_prefix_onlink(pr)) != 0) {
9bccf70c
A
2989 nd6log((LOG_ERR,
2990 "pfxlist_onlink_check: failed to "
2991 "make %s/%d offlink, errno=%d\n",
2992 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
2993 pr->ndpr_plen, e));
2994 }
6d2010ae
A
2995 } else {
2996 NDPR_UNLOCK(pr);
9bccf70c 2997 }
6d2010ae 2998 pr = pr->ndpr_next;
9bccf70c
A
2999 }
3000
3001 /*
3002 * Changes on the prefix status might affect address status as well.
3003 * Make sure that all addresses derived from an attached prefix are
3004 * attached, and that all addresses derived from a detached prefix are
3005 * detached. Note, however, that a manually configured address should
3006 * always be attached.
3007 * The precise detection logic is same as the one for prefixes.
3008 */
6d2010ae 3009 lck_rw_lock_shared(&in6_ifaddr_rwlock);
91447636 3010 for (ifa = in6_ifaddrs; ifa; ifa = ifa->ia_next) {
6d2010ae 3011 struct nd_prefix *ndpr;
9bccf70c 3012
6d2010ae
A
3013 IFA_LOCK(&ifa->ia_ifa);
3014 if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0) {
3015 IFA_UNLOCK(&ifa->ia_ifa);
3016 continue;
3017 }
3018 if ((ndpr = ifa->ia6_ndpr) == NULL) {
9bccf70c
A
3019 /*
3020 * This can happen when we first configure the address
3021 * (i.e. the address exists, but the prefix does not).
3022 * XXX: complicated relationships...
3023 */
6d2010ae 3024 IFA_UNLOCK(&ifa->ia_ifa);
9bccf70c
A
3025 continue;
3026 }
6d2010ae
A
3027 NDPR_ADDREF(ndpr);
3028 IFA_UNLOCK(&ifa->ia_ifa);
9bccf70c 3029
6d2010ae
A
3030 NDPR_LOCK(ndpr);
3031 if (find_pfxlist_reachable_router(ndpr)) {
3032 NDPR_UNLOCK(ndpr);
3033 NDPR_REMREF(ndpr);
9bccf70c 3034 break;
6d2010ae
A
3035 }
3036 NDPR_UNLOCK(ndpr);
3037 NDPR_REMREF(ndpr);
9bccf70c
A
3038 }
3039 if (ifa) {
91447636 3040 for (ifa = in6_ifaddrs; ifa; ifa = ifa->ia_next) {
6d2010ae 3041 struct nd_prefix *ndpr;
9bccf70c 3042
6d2010ae
A
3043 IFA_LOCK(&ifa->ia_ifa);
3044 if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0) {
3045 IFA_UNLOCK(&ifa->ia_ifa);
9bccf70c 3046 continue;
6d2010ae
A
3047 }
3048 if ((ndpr = ifa->ia6_ndpr) == NULL) {
3049 /* XXX: see above. */
3050 IFA_UNLOCK(&ifa->ia_ifa);
3051 continue;
3052 }
3053 NDPR_ADDREF(ndpr);
3054 IFA_UNLOCK(&ifa->ia_ifa);
3055 NDPR_LOCK(ndpr);
3056 if (find_pfxlist_reachable_router(ndpr)) {
3057 NDPR_UNLOCK(ndpr);
3058 IFA_LOCK(&ifa->ia_ifa);
3059 if (ifa->ia6_flags & IN6_IFF_DETACHED) {
3060 ifa->ia6_flags &= ~IN6_IFF_DETACHED;
3061 ifa->ia6_flags |= IN6_IFF_TENTATIVE;
3062 IFA_UNLOCK(&ifa->ia_ifa);
3063 nd6_dad_start((struct ifaddr *)ifa, 0);
3064 } else {
3065 IFA_UNLOCK(&ifa->ia_ifa);
3066 }
3067 } else {
3068 NDPR_UNLOCK(ndpr);
3069 IFA_LOCK(&ifa->ia_ifa);
9bccf70c 3070 ifa->ia6_flags |= IN6_IFF_DETACHED;
6d2010ae
A
3071 IFA_UNLOCK(&ifa->ia_ifa);
3072 }
3073 NDPR_REMREF(ndpr);
1c79356b
A
3074 }
3075 }
3076 else {
91447636 3077 for (ifa = in6_ifaddrs; ifa; ifa = ifa->ia_next) {
6d2010ae
A
3078 IFA_LOCK(&ifa->ia_ifa);
3079 if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0) {
3080 IFA_UNLOCK(&ifa->ia_ifa);
9bccf70c 3081 continue;
6d2010ae
A
3082 }
3083 if (ifa->ia6_flags & IN6_IFF_DETACHED) {
3084 ifa->ia6_flags &= ~IN6_IFF_DETACHED;
3085 ifa->ia6_flags |= IN6_IFF_TENTATIVE;
3086 IFA_UNLOCK(&ifa->ia_ifa);
3087 /* Do we need a delay in this case? */
3088 nd6_dad_start((struct ifaddr *)ifa, 0);
3089 } else {
3090 IFA_UNLOCK(&ifa->ia_ifa);
3091 }
3092 }
3093 }
3094 lck_rw_done(&in6_ifaddr_rwlock);
3095}
3096
3097static struct nd_prefix *
3098nd6_prefix_equal_lookup(struct nd_prefix *pr, boolean_t primary_only)
3099{
3100 struct nd_prefix *opr;
3101
3102 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
3103
3104 for (opr = nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
3105 if (opr == pr)
3106 continue;
3107
3108 NDPR_LOCK(opr);
3109 if ((opr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
3110 NDPR_UNLOCK(opr);
3111 continue;
3112 }
3113 if (opr->ndpr_plen == pr->ndpr_plen &&
3114 in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
3115 &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen) &&
3116 (!primary_only ||
3117 !(opr->ndpr_stateflags & NDPRF_IFSCOPE))) {
3118 NDPR_ADDREF_LOCKED(opr);
3119 NDPR_UNLOCK(opr);
3120 return (opr);
3121 }
3122 NDPR_UNLOCK(opr);
3123 }
3124 return (NULL);
3125}
3126
3127/*
3128 * Synchronize the interface routes of similar prefixes on different
3129 * interfaces; the one using the default interface would be (re)installed
3130 * as a primary/non-scoped entry, and the rest as scoped entri(es).
3131 */
3132static void
3133nd6_prefix_sync(struct ifnet *ifp)
3134{
3135 struct nd_prefix *pr, *opr;
3136 int err = 0;
3137
3138 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
3139
3140 if (!ip6_doscopedroute || ifp == NULL)
3141 return;
9bccf70c 3142
6d2010ae
A
3143 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
3144 NDPR_LOCK(pr);
3145 if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) {
3146 NDPR_UNLOCK(pr);
3147 continue;
3148 }
3149 if (pr->ndpr_ifp == ifp &&
3150 (pr->ndpr_stateflags & NDPRF_IFSCOPE) &&
3151 !IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) {
3152 NDPR_UNLOCK(pr);
3153 break;
9bccf70c 3154 }
6d2010ae 3155 NDPR_UNLOCK(pr);
1c79356b 3156 }
6d2010ae
A
3157
3158 if (pr == NULL)
3159 return;
3160
3161 /* Remove conflicting entries */
3162 opr = nd6_prefix_equal_lookup(pr, TRUE);
3163 if (opr != NULL) {
91447636 3164 lck_mtx_unlock(nd6_mutex);
6d2010ae
A
3165 err = nd6_prefix_offlink(opr);
3166 lck_mtx_lock(nd6_mutex);
3167 if (err != 0) {
3168 nd6log((LOG_ERR,
3169 "%s: failed to make %s/%d offlink on %s, "
3170 "errno=%d\n", __func__,
3171 ip6_sprintf(&opr->ndpr_prefix.sin6_addr),
3172 opr->ndpr_plen, if_name(opr->ndpr_ifp), err));
3173 }
3174 } else {
3175 nd6log((LOG_ERR,
3176 "%s: scoped %s/%d on %s has no matching unscoped prefix\n",
3177 __func__, ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3178 pr->ndpr_plen, if_name(pr->ndpr_ifp)));
3179 }
3180
3181 lck_mtx_unlock(nd6_mutex);
3182 err = nd6_prefix_offlink(pr);
3183 lck_mtx_lock(nd6_mutex);
3184 if (err != 0) {
3185 nd6log((LOG_ERR,
3186 "%s: failed to make %s/%d offlink on %s, errno=%d\n",
3187 __func__, ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3188 pr->ndpr_plen, if_name(pr->ndpr_ifp), err));
3189 }
3190
3191 /* Add the entries back */
3192 if (opr != NULL) {
3193 err = nd6_prefix_onlink_scoped(opr, opr->ndpr_ifp->if_index);
3194 if (err != 0) {
3195 nd6log((LOG_ERR,
3196 "%s: failed to make %s/%d scoped onlink on %s, "
3197 "errno=%d\n", __func__,
3198 ip6_sprintf(&opr->ndpr_prefix.sin6_addr),
3199 opr->ndpr_plen, if_name(opr->ndpr_ifp), err));
3200 }
3201 }
3202
3203 err = nd6_prefix_onlink_scoped(pr, IFSCOPE_NONE);
3204 if (err != 0) {
3205 nd6log((LOG_ERR,
3206 "%s: failed to make %s/%d onlink on %s, errno=%d\n",
3207 __func__, ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3208 pr->ndpr_plen, if_name(pr->ndpr_ifp), err));
3209 }
3210
3211 if (err != 0) {
3212 nd6log((LOG_ERR,
3213 "%s: error promoting %s/%d to %s from %s\n",
3214 __func__, ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3215 pr->ndpr_plen, if_name(pr->ndpr_ifp),
3216 (opr != NULL) ? if_name(opr->ndpr_ifp) : "NONE"));
3217 } else {
3218 nd6log2((LOG_INFO,
3219 "%s: %s/%d promoted, previously on %s\n",
3220 if_name(pr->ndpr_ifp),
3221 ip6_sprintf(&pr->ndpr_prefix.sin6_addr), pr->ndpr_plen,
3222 (opr != NULL) ? if_name(opr->ndpr_ifp) : "NONE"));
3223 }
3224
3225 if (opr != NULL)
3226 NDPR_REMREF(opr);
1c79356b
A
3227}
3228
6d2010ae
A
3229static int
3230nd6_prefix_onlink_common(struct nd_prefix *pr, boolean_t force_scoped,
3231 unsigned int ifscope)
1c79356b 3232{
9bccf70c
A
3233 struct ifaddr *ifa;
3234 struct ifnet *ifp = pr->ndpr_ifp;
6d2010ae 3235 struct sockaddr_in6 mask6, prefix;
9bccf70c 3236 struct nd_prefix *opr;
b0d623f7 3237 u_int32_t rtflags;
9bccf70c
A
3238 int error = 0;
3239 struct rtentry *rt = NULL;
3240
6d2010ae
A
3241 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_OWNED);
3242
9bccf70c 3243 /* sanity check */
6d2010ae 3244 NDPR_LOCK(pr);
9bccf70c
A
3245 if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
3246 nd6log((LOG_ERR,
6d2010ae
A
3247 "nd6_prefix_onlink: %s/%d on %s scoped=%d is already "
3248 "on-link\n", ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3249 pr->ndpr_plen, if_name(pr->ndpr_ifp),
3250 (pr->ndpr_stateflags & NDPRF_IFSCOPE) ? 1 : 0);
3251 NDPR_UNLOCK(pr);
3252 return (EEXIST));
9bccf70c 3253 }
6d2010ae 3254 NDPR_UNLOCK(pr);
9bccf70c
A
3255
3256 /*
3257 * Add the interface route associated with the prefix. Before
3258 * installing the route, check if there's the same prefix on another
3259 * interface, and the prefix has already installed the interface route.
9bccf70c 3260 */
6d2010ae
A
3261 opr = nd6_prefix_equal_lookup(pr, FALSE);
3262 if (opr != NULL)
3263 NDPR_REMREF(opr);
3264
3265 if (!ip6_doscopedroute) {
3266 /* if an interface route already exists, just return */
3267 if (opr != NULL)
3268 return (0);
3269 ifscope = IFSCOPE_NONE;
3270 } else if (!force_scoped) {
3271 /*
3272 * If a primary/non-scoped interface route already exists,
3273 * install the new one as a scoped entry. If the existing
3274 * interface route is scoped, install new as non-scoped.
3275 */
3276 ifscope = (opr != NULL) ? ifp->if_index : IFSCOPE_NONE;
3277 opr = nd6_prefix_equal_lookup(pr, TRUE);
3278 if (opr != NULL)
3279 NDPR_REMREF(opr);
3280 else if (ifscope != IFSCOPE_NONE)
3281 ifscope = IFSCOPE_NONE;
9bccf70c
A
3282 }
3283
3284 /*
6d2010ae 3285 * We prefer link-local addresses as the associated interface address.
9bccf70c
A
3286 */
3287 /* search for a link-local addr */
3288 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
3289 IN6_IFF_NOTREADY|
3290 IN6_IFF_ANYCAST);
3291 if (ifa == NULL) {
6d2010ae
A
3292 struct in6_ifaddr *ia6;
3293 ifnet_lock_shared(ifp);
3294 IFP_TO_IA6(ifp, ia6);
91447636 3295 ifnet_lock_done(ifp);
6d2010ae
A
3296 if (ia6 != NULL)
3297 ifa = &ia6->ia_ifa;
9bccf70c
A
3298 /* should we care about ia6_flags? */
3299 }
6d2010ae 3300 NDPR_LOCK(pr);
9bccf70c
A
3301 if (ifa == NULL) {
3302 /*
3303 * This can still happen, when, for example, we receive an RA
3304 * containing a prefix with the L bit set and the A bit clear,
3305 * after removing all IPv6 addresses on the receiving
3306 * interface. This should, of course, be rare though.
3307 */
3308 nd6log((LOG_NOTICE,
3309 "nd6_prefix_onlink: failed to find any ifaddr"
3310 " to add route for a prefix(%s/%d) on %s\n",
3311 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3312 pr->ndpr_plen, if_name(ifp)));
6d2010ae
A
3313 NDPR_UNLOCK(pr);
3314 return (0);
9bccf70c 3315 }
1c79356b
A
3316
3317 /*
9bccf70c
A
3318 * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
3319 * ifa->ifa_rtrequest = nd6_rtrequest;
1c79356b 3320 */
9bccf70c
A
3321 bzero(&mask6, sizeof(mask6));
3322 mask6.sin6_len = sizeof(mask6);
3323 mask6.sin6_addr = pr->ndpr_mask;
6d2010ae
A
3324 prefix = pr->ndpr_prefix;
3325 NDPR_UNLOCK(pr);
91447636 3326
6d2010ae 3327 IFA_LOCK_SPIN(ifa);
9bccf70c 3328 rtflags = ifa->ifa_flags | RTF_CLONING | RTF_UP;
6d2010ae 3329 IFA_UNLOCK(ifa);
9bccf70c
A
3330 if (nd6_need_cache(ifp)) {
3331 /* explicitly set in case ifa_flags does not set the flag. */
3332 rtflags |= RTF_CLONING;
3333 } else {
3334 /*
3335 * explicitly clear the cloning bit in case ifa_flags sets it.
3336 */
3337 rtflags &= ~RTF_CLONING;
3338 }
6d2010ae
A
3339
3340 lck_mtx_unlock(nd6_mutex);
3341
3342 error = rtrequest_scoped(RTM_ADD, (struct sockaddr *)&prefix,
3343 ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt,
3344 ifscope);
3345
3346 if (rt != NULL) {
3347 RT_LOCK(rt);
3348 nd6_rtmsg(RTM_ADD, rt);
3349 RT_UNLOCK(rt);
3350 RT_REMREF(rt);
3351 } else {
3352 NDPR_LOCK(pr);
9bccf70c 3353 nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
6d2010ae
A
3354 " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx,"
3355 " scoped=%d, errno = %d\n",
9bccf70c
A
3356 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3357 pr->ndpr_plen, if_name(ifp),
3358 ip6_sprintf(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
6d2010ae
A
3359 ip6_sprintf(&mask6.sin6_addr), rtflags,
3360 (ifscope != IFSCOPE_NONE), error));
3361 NDPR_UNLOCK(pr);
9bccf70c
A
3362 }
3363
6d2010ae
A
3364 lck_mtx_lock(nd6_mutex);
3365
3366 NDPR_LOCK(pr);
3367 pr->ndpr_stateflags &= ~NDPRF_IFSCOPE;
3368 if (rt != NULL || error == EEXIST) {
3369 pr->ndpr_stateflags |= NDPRF_ONLINK;
3370 if (ifscope != IFSCOPE_NONE)
3371 pr->ndpr_stateflags |= NDPRF_IFSCOPE;
3372 }
3373 NDPR_UNLOCK(pr);
9bccf70c 3374
6d2010ae 3375 IFA_REMREF(ifa);
b0d623f7 3376
6d2010ae
A
3377 return (error);
3378}
b0d623f7 3379
6d2010ae
A
3380int
3381nd6_prefix_onlink(struct nd_prefix *pr)
3382{
3383 return (nd6_prefix_onlink_common(pr, FALSE, IFSCOPE_NONE));
9bccf70c
A
3384}
3385
3386int
6d2010ae 3387nd6_prefix_onlink_scoped(struct nd_prefix *pr, unsigned int ifscope)
9bccf70c 3388{
6d2010ae
A
3389 return (nd6_prefix_onlink_common(pr, TRUE, ifscope));
3390}
3391
3392int
3393nd6_prefix_offlink(struct nd_prefix *pr)
3394{
3395 int plen, error = 0;
9bccf70c
A
3396 struct ifnet *ifp = pr->ndpr_ifp;
3397 struct nd_prefix *opr;
6d2010ae 3398 struct sockaddr_in6 sa6, mask6, prefix;
9bccf70c 3399 struct rtentry *rt = NULL;
6d2010ae
A
3400 unsigned int ifscope;
3401
3402 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
9bccf70c
A
3403
3404 /* sanity check */
6d2010ae 3405 NDPR_LOCK(pr);
9bccf70c
A
3406 if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
3407 nd6log((LOG_ERR,
6d2010ae
A
3408 "nd6_prefix_offlink: %s/%d on %s scoped=%d is already "
3409 "off-link\n", ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
3410 pr->ndpr_plen, if_name(pr->ndpr_ifp),
3411 (pr->ndpr_stateflags & NDPRF_IFSCOPE) ? 1 : 0));
3412 NDPR_UNLOCK(pr);
3413 return (EEXIST);
9bccf70c
A
3414 }
3415
1c79356b
A
3416 bzero(&sa6, sizeof(sa6));
3417 sa6.sin6_family = AF_INET6;
3418 sa6.sin6_len = sizeof(sa6);
3419 bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr,
3420 sizeof(struct in6_addr));
3421 bzero(&mask6, sizeof(mask6));
3422 mask6.sin6_family = AF_INET6;
3423 mask6.sin6_len = sizeof(sa6);
3424 bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr));
6d2010ae
A
3425 prefix = pr->ndpr_prefix;
3426 plen = pr->ndpr_plen;
3427 NDPR_UNLOCK(pr);
1c79356b 3428
6d2010ae
A
3429 ifscope = (pr->ndpr_stateflags & NDPRF_IFSCOPE) ?
3430 ifp->if_index : IFSCOPE_NONE;
3431
3432 error = rtrequest_scoped(RTM_DELETE, (struct sockaddr *)&sa6,
3433 NULL, (struct sockaddr *)&mask6, 0, &rt, ifscope);
3434
3435 if (rt != NULL) {
9bccf70c 3436 /* report the route deletion to the routing socket. */
6d2010ae
A
3437 RT_LOCK(rt);
3438 nd6_rtmsg(RTM_DELETE, rt);
3439 RT_UNLOCK(rt);
3440 rtfree(rt);
1c79356b 3441
9bccf70c 3442 /*
6d2010ae
A
3443 * The following check takes place only when Scoped Routing
3444 * is not enabled. There might be the same prefix on another
3445 * interface, the prefix which could not be on-link just
3446 * because we have the interface route (see comments in
3447 * nd6_prefix_onlink). If there's one, try to make the prefix
3448 * on-link on the interface.
9bccf70c 3449 */
6d2010ae
A
3450 lck_mtx_lock(nd6_mutex);
3451 opr = nd_prefix.lh_first;
3452 while (opr) {
3453 /* does not apply in the Scoped Routing case */
3454 if (ip6_doscopedroute)
3455 break;
1c79356b 3456
6d2010ae
A
3457 if (opr == pr) {
3458 opr = opr->ndpr_next;
9bccf70c 3459 continue;
6d2010ae 3460 }
1c79356b 3461
6d2010ae
A
3462 NDPR_LOCK(opr);
3463 if ((opr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
3464 NDPR_UNLOCK(opr);
3465 opr = opr->ndpr_next;
3466 continue;
3467 }
9bccf70c
A
3468 /*
3469 * KAME specific: detached prefixes should not be
3470 * on-link.
3471 */
6d2010ae
A
3472 if ((opr->ndpr_stateflags & NDPRF_DETACHED) != 0) {
3473 NDPR_UNLOCK(opr);
3474 opr = opr->ndpr_next;
9bccf70c 3475 continue;
6d2010ae
A
3476 }
3477 if (opr->ndpr_plen == plen &&
3478 in6_are_prefix_equal(&prefix.sin6_addr,
3479 &opr->ndpr_prefix.sin6_addr, plen)) {
9bccf70c
A
3480 int e;
3481
6d2010ae
A
3482 NDPR_UNLOCK(opr);
3483 lck_mtx_unlock(nd6_mutex);
3484 if ((e = nd6_prefix_onlink(opr)) != 0) {
9bccf70c
A
3485 nd6log((LOG_ERR,
3486 "nd6_prefix_offlink: failed to "
3487 "recover a prefix %s/%d from %s "
3488 "to %s (errno = %d)\n",
3489 ip6_sprintf(&opr->ndpr_prefix.sin6_addr),
3490 opr->ndpr_plen, if_name(ifp),
3491 if_name(opr->ndpr_ifp), e));
3492 }
6d2010ae
A
3493 lck_mtx_lock(nd6_mutex);
3494 opr = nd_prefix.lh_first;
3495 } else {
3496 NDPR_UNLOCK(opr);
3497 opr = opr->ndpr_next;
9bccf70c
A
3498 }
3499 }
6d2010ae
A
3500 lck_mtx_unlock(nd6_mutex);
3501 } else {
9bccf70c
A
3502 nd6log((LOG_ERR,
3503 "nd6_prefix_offlink: failed to delete route: "
6d2010ae
A
3504 "%s/%d on %s, scoped %d, (errno = %d)\n",
3505 ip6_sprintf(&sa6.sin6_addr), plen, if_name(ifp),
3506 (ifscope != IFSCOPE_NONE), error));
1c79356b
A
3507 }
3508
6d2010ae
A
3509 NDPR_LOCK(pr);
3510 pr->ndpr_stateflags &= ~(NDPRF_ONLINK | NDPRF_IFSCOPE);
3511 NDPR_UNLOCK(pr);
9bccf70c 3512
6d2010ae 3513 return (error);
1c79356b
A
3514}
3515
3516static struct in6_ifaddr *
91447636
A
3517in6_ifadd(
3518 struct nd_prefix *pr,
6d2010ae 3519 int mcast)
1c79356b 3520{
9bccf70c 3521 struct ifnet *ifp = pr->ndpr_ifp;
9bccf70c
A
3522 struct in6_aliasreq ifra;
3523 struct in6_ifaddr *ia, *ib;
3524 int error, plen0;
6d2010ae 3525 int updateflags;
1c79356b 3526 struct in6_addr mask;
6d2010ae 3527 int prefixlen;
1c79356b 3528
9bccf70c
A
3529 /*
3530 * find a link-local address (will be interface ID).
3531 * Is it really mandatory? Theoretically, a global or a site-local
3532 * address can be configured without a link-local address, if we
3533 * have a unique interface identifier...
3534 *
3535 * it is not mandatory to have a link-local address, we can generate
3536 * interface identifier on the fly. we do this because:
3537 * (1) it should be the easiest way to find interface identifier.
3538 * (2) RFC2462 5.4 suggesting the use of the same interface identifier
3539 * for multiple addresses on a single interface, and possible shortcut
3540 * of DAD. we omitted DAD for this reason in the past.
6d2010ae 3541 * (3) a user can prevent autoconfiguration of global address
9bccf70c 3542 * by removing link-local address by hand (this is partly because we
6d2010ae 3543 * don't have other way to control the use of IPv6 on an interface.
9bccf70c
A
3544 * this has been our design choice - cf. NRL's "ifconfig auto").
3545 * (4) it is easier to manage when an interface has addresses
3546 * with the same interface identifier, than to have multiple addresses
3547 * with different interface identifiers.
9bccf70c 3548 */
6d2010ae
A
3549 ib = in6ifa_ifpforlinklocal(ifp, 0);/* 0 is OK? */
3550 if (ib == NULL)
3551 return (NULL);
1c79356b 3552
6d2010ae
A
3553 IFA_LOCK(&ib->ia_ifa);
3554 NDPR_LOCK(pr);
3555 prefixlen = pr->ndpr_plen;
3556 in6_len2mask(&mask, prefixlen);
9bccf70c 3557 plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL);
6d2010ae 3558 /* prefixlen + ifidlen must be equal to 128 */
9bccf70c
A
3559 if (prefixlen != plen0) {
3560 nd6log((LOG_INFO, "in6_ifadd: wrong prefixlen for %s "
3561 "(prefix=%d ifid=%d)\n",
3562 if_name(ifp), prefixlen, 128 - plen0));
6d2010ae
A
3563 NDPR_UNLOCK(pr);
3564 IFA_UNLOCK(&ib->ia_ifa);
3565 IFA_REMREF(&ib->ia_ifa);
3566 return (NULL);
1c79356b
A
3567 }
3568
3569 /* make ifaddr */
1c79356b 3570
9bccf70c
A
3571 bzero(&ifra, sizeof(ifra));
3572 /*
3573 * in6_update_ifa() does not use ifra_name, but we accurately set it
3574 * for safety.
3575 */
3576 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
3577 ifra.ifra_addr.sin6_family = AF_INET6;
3578 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
3579 /* prefix */
3580 bcopy(&pr->ndpr_prefix.sin6_addr, &ifra.ifra_addr.sin6_addr,
3581 sizeof(ifra.ifra_addr.sin6_addr));
3582 ifra.ifra_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
3583 ifra.ifra_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
3584 ifra.ifra_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
3585 ifra.ifra_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
1c79356b 3586
9bccf70c 3587 /* interface ID */
6d2010ae
A
3588 ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
3589 (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
3590 ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
3591 (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
3592 ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
3593 (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
3594 ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
3595 (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
3596
9bccf70c
A
3597 /* new prefix mask. */
3598 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
3599 ifra.ifra_prefixmask.sin6_family = AF_INET6;
3600 bcopy(&mask, &ifra.ifra_prefixmask.sin6_addr,
3601 sizeof(ifra.ifra_prefixmask.sin6_addr));
1c79356b 3602
6d2010ae 3603 /* lifetimes. */
9bccf70c
A
3604 ifra.ifra_lifetime.ia6t_vltime = pr->ndpr_vltime;
3605 ifra.ifra_lifetime.ia6t_pltime = pr->ndpr_pltime;
1c79356b 3606
9bccf70c
A
3607 /* XXX: scope zone ID? */
3608
3609 ifra.ifra_flags |= IN6_IFF_AUTOCONF; /* obey autoconf */
6d2010ae
A
3610
3611 NDPR_UNLOCK(pr);
3612 IFA_UNLOCK(&ib->ia_ifa);
3613 IFA_REMREF(&ib->ia_ifa);
3614
9bccf70c 3615 /*
6d2010ae
A
3616 * Make sure that we do not have this address already. This should
3617 * usually not happen, but we can still see this case, e.g., if we
3618 * have manually configured the exact address to be configured.
9bccf70c 3619 */
6d2010ae
A
3620 if ((ib = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr)) != NULL) {
3621 IFA_REMREF(&ib->ia_ifa);
3622 /* this should be rare enough to make an explicit log */
3623 log(LOG_INFO, "in6_ifadd: %s is already configured\n",
3624 ip6_sprintf(&ifra.ifra_addr.sin6_addr));
3625 return (NULL);
3626 }
9bccf70c
A
3627
3628 /*
6d2010ae
A
3629 * Allocate ifaddr structure, link into chain, etc.
3630 * If we are going to create a new address upon receiving a multicasted
3631 * RA, we need to impose a random delay before starting DAD.
3632 * [draft-ietf-ipv6-rfc2462bis-02.txt, Section 5.4.2]
9bccf70c 3633 */
6d2010ae
A
3634 updateflags = 0;
3635 if (mcast)
3636 updateflags |= IN6_IFAUPDATE_DADDELAY;
3637 error = in6_update_ifa(ifp, &ifra, NULL, updateflags, M_WAITOK);
3638 if (error != 0) {
9bccf70c
A
3639 nd6log((LOG_ERR,
3640 "in6_ifadd: failed to make ifaddr %s on %s (errno=%d)\n",
3641 ip6_sprintf(&ifra.ifra_addr.sin6_addr), if_name(ifp),
3642 error));
3643 return(NULL); /* ifaddr must not have been allocated. */
1c79356b 3644 }
1c79356b 3645
9bccf70c 3646 ia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
1c79356b 3647
9bccf70c 3648 in6_post_msg(ifp, KEV_INET6_NEW_RTADV_ADDR, ia);
1c79356b 3649
9bccf70c
A
3650 return(ia); /* this must NOT be NULL. */
3651}
1c79356b 3652
6d2010ae
A
3653#define IA6_NONCONST(i) ((struct in6_ifaddr *)(uintptr_t)(i))
3654
9bccf70c 3655int
91447636
A
3656in6_tmpifadd(
3657 const struct in6_ifaddr *ia0, /* corresponding public address */
b0d623f7
A
3658 int forcegen,
3659 int how)
9bccf70c
A
3660{
3661 struct ifnet *ifp = ia0->ia_ifa.ifa_ifp;
b0d623f7 3662 struct in6_ifaddr *ia, *newia;
9bccf70c
A
3663 struct in6_aliasreq ifra;
3664 int i, error;
3665 int trylimit = 3; /* XXX: adhoc value */
6d2010ae 3666 int updateflags;
9bccf70c
A
3667 u_int32_t randid[2];
3668 time_t vltime0, pltime0;
91447636 3669 struct timeval timenow;
6d2010ae
A
3670 struct in6_addr addr;
3671 struct nd_prefix *ndpr;
91447636
A
3672
3673 getmicrotime(&timenow);
9bccf70c
A
3674
3675 bzero(&ifra, sizeof(ifra));
3676 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
6d2010ae 3677 IFA_LOCK(&IA6_NONCONST(ia0)->ia_ifa);
9bccf70c
A
3678 ifra.ifra_addr = ia0->ia_addr;
3679 /* copy prefix mask */
3680 ifra.ifra_prefixmask = ia0->ia_prefixmask;
3681 /* clear the old IFID */
3682 for (i = 0; i < 4; i++) {
3683 ifra.ifra_addr.sin6_addr.s6_addr32[i]
3684 &= ifra.ifra_prefixmask.sin6_addr.s6_addr32[i];
1c79356b 3685 }
6d2010ae
A
3686 addr = ia0->ia_addr.sin6_addr;
3687 IFA_UNLOCK(&IA6_NONCONST(ia0)->ia_ifa);
1c79356b 3688
6d2010ae 3689again:
9bccf70c 3690 in6_get_tmpifid(ifp, (u_int8_t *)randid,
6d2010ae
A
3691 (const u_int8_t *)&addr.s6_addr[8], forcegen);
3692
3693 ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
3694 (randid[0] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[2]));
3695 ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
3696 (randid[1] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[3]));
1c79356b
A
3697
3698 /*
6d2010ae
A
3699 * in6_get_tmpifid() quite likely provided a unique interface ID.
3700 * However, we may still have a chance to see collision, because
3701 * there may be a time lag between generation of the ID and generation
3702 * of the address. So, we'll do one more sanity check.
1c79356b 3703 */
b0d623f7 3704 if ((ia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr)) != NULL) {
6d2010ae 3705 IFA_REMREF(&ia->ia_ifa);
9bccf70c
A
3706 if (trylimit-- == 0) {
3707 nd6log((LOG_NOTICE, "in6_tmpifadd: failed to find "
3708 "a unique random IFID\n"));
3709 return(EEXIST);
3710 }
3711 forcegen = 1;
3712 goto again;
1c79356b 3713 }
1c79356b 3714
9bccf70c
A
3715 /*
3716 * The Valid Lifetime is the lower of the Valid Lifetime of the
3717 * public address or TEMP_VALID_LIFETIME.
3718 * The Preferred Lifetime is the lower of the Preferred Lifetime
3719 * of the public address or TEMP_PREFERRED_LIFETIME -
3720 * DESYNC_FACTOR.
3721 */
6d2010ae
A
3722 IFA_LOCK(&IA6_NONCONST(ia0)->ia_ifa);
3723 vltime0 = IFA6_IS_INVALID(ia0)
3724 ? 0
3725 : (ia0->ia6_lifetime.ia6t_vltime -
3726 (timenow.tv_sec - ia0->ia6_updatetime));
3727 if (vltime0 > ip6_temp_valid_lifetime)
9bccf70c 3728 vltime0 = ip6_temp_valid_lifetime;
6d2010ae
A
3729 pltime0 = IFA6_IS_DEPRECATED(ia0)
3730 ? 0
3731 : (ia0->ia6_lifetime.ia6t_pltime -
3732 (timenow.tv_sec - ia0->ia6_updatetime));
3733 if (pltime0 > ip6_temp_preferred_lifetime - ip6_desync_factor)
9bccf70c
A
3734 pltime0 = ip6_temp_preferred_lifetime - ip6_desync_factor;
3735 ifra.ifra_lifetime.ia6t_vltime = vltime0;
3736 ifra.ifra_lifetime.ia6t_pltime = pltime0;
6d2010ae 3737 IFA_UNLOCK(&IA6_NONCONST(ia0)->ia_ifa);
9bccf70c
A
3738 /*
3739 * A temporary address is created only if this calculated Preferred
3740 * Lifetime is greater than REGEN_ADVANCE time units.
3741 */
3742 if (ifra.ifra_lifetime.ia6t_pltime <= ip6_temp_regen_advance)
3743 return(0);
1c79356b 3744
9bccf70c 3745 /* XXX: scope zone ID? */
1c79356b 3746
9bccf70c 3747 ifra.ifra_flags |= (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY);
1c79356b 3748
9bccf70c 3749 /* allocate ifaddr structure, link into chain, etc. */
6d2010ae
A
3750 updateflags = 0;
3751
3752 if (how)
3753 updateflags |= IN6_IFAUPDATE_DADDELAY;
3754
3755 if ((error = in6_update_ifa(ifp, &ifra, NULL, updateflags, how)) != 0)
3756 return (error);
1c79356b 3757
9bccf70c
A
3758 newia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
3759 if (newia == NULL) { /* XXX: can it happen? */
3760 nd6log((LOG_ERR,
3761 "in6_tmpifadd: ifa update succeeded, but we got "
3762 "no ifaddr\n"));
3763 return(EINVAL); /* XXX */
1c79356b 3764 }
6d2010ae
A
3765 IFA_LOCK(&IA6_NONCONST(ia0)->ia_ifa);
3766 ndpr = ia0->ia6_ndpr;
3767 if (ndpr == NULL) {
3768 /*
3769 * We lost the race with another thread that has purged
3770 * ia0 address; in this case, purge the tmp addr as well.
3771 */
3772 nd6log((LOG_ERR, "in6_tmpifadd: no public address\n"));
3773 VERIFY(!(ia0->ia6_flags & IN6_IFF_AUTOCONF));
3774 IFA_UNLOCK(&IA6_NONCONST(ia0)->ia_ifa);
3775 in6_purgeaddr(&newia->ia_ifa);
3776 IFA_REMREF(&newia->ia_ifa);
3777 return (EADDRNOTAVAIL);
3778 }
3779 NDPR_ADDREF(ndpr); /* for us */
3780 IFA_UNLOCK(&IA6_NONCONST(ia0)->ia_ifa);
3781 IFA_LOCK(&newia->ia_ifa);
3782 if (newia->ia6_ndpr != NULL) {
3783 NDPR_LOCK(newia->ia6_ndpr);
3784 VERIFY(newia->ia6_ndpr->ndpr_addrcnt != 0);
3785 newia->ia6_ndpr->ndpr_addrcnt--;
3786 NDPR_UNLOCK(newia->ia6_ndpr);
3787 NDPR_REMREF(newia->ia6_ndpr); /* release addr reference */
3788 }
3789 newia->ia6_ndpr = ndpr;
3790 NDPR_LOCK(newia->ia6_ndpr);
3791 newia->ia6_ndpr->ndpr_addrcnt++;
3792 VERIFY(newia->ia6_ndpr->ndpr_addrcnt != 0);
3793 NDPR_ADDREF_LOCKED(newia->ia6_ndpr); /* for addr reference */
3794 NDPR_UNLOCK(newia->ia6_ndpr);
3795 IFA_UNLOCK(&newia->ia_ifa);
55e303ae
A
3796 /*
3797 * A newly added address might affect the status of other addresses.
3798 * XXX: when the temporary address is generated with a new public
3799 * address, the onlink check is redundant. However, it would be safe
3800 * to do the check explicitly everywhere a new address is generated,
3801 * and, in fact, we surely need the check when we create a new
3802 * temporary address due to deprecation of an old temporary address.
3803 */
6d2010ae
A
3804 lck_mtx_lock(nd6_mutex);
3805 pfxlist_onlink_check();
2d21ac55 3806 lck_mtx_unlock(nd6_mutex);
6d2010ae
A
3807 IFA_REMREF(&newia->ia_ifa);
3808
3809 /* remove our reference */
3810 NDPR_REMREF(ndpr);
55e303ae 3811
9bccf70c 3812 return(0);
6d2010ae
A
3813}
3814#undef IA6_NONCONST
1c79356b
A
3815
3816int
3817in6_init_prefix_ltimes(struct nd_prefix *ndpr)
3818{
91447636
A
3819 struct timeval timenow;
3820
6d2010ae
A
3821 NDPR_LOCK_ASSERT_HELD(ndpr);
3822
91447636 3823 getmicrotime(&timenow);
9bccf70c 3824 /* check if preferred lifetime > valid lifetime. RFC2462 5.5.3 (c) */
1c79356b 3825 if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) {
9bccf70c 3826 nd6log((LOG_INFO, "in6_init_prefix_ltimes: preferred lifetime"
1c79356b 3827 "(%d) is greater than valid lifetime(%d)\n",
9bccf70c 3828 (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime));
1c79356b
A
3829 return (EINVAL);
3830 }
3831 if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
3832 ndpr->ndpr_preferred = 0;
3833 else
91447636 3834 ndpr->ndpr_preferred = timenow.tv_sec + ndpr->ndpr_pltime;
1c79356b
A
3835 if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
3836 ndpr->ndpr_expire = 0;
3837 else
91447636 3838 ndpr->ndpr_expire = timenow.tv_sec + ndpr->ndpr_vltime;
1c79356b
A
3839
3840 return 0;
3841}
3842
3843static void
6d2010ae
A
3844in6_init_address_ltimes(__unused struct nd_prefix *new,
3845 struct in6_addrlifetime *lt6, boolean_t is_temporary)
1c79356b 3846{
91447636
A
3847 struct timeval timenow;
3848
3849 getmicrotime(&timenow);
1c79356b 3850 /* Valid lifetime must not be updated unless explicitly specified. */
9bccf70c 3851 /* init ia6t_expire */
6d2010ae 3852 if (!is_temporary && lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
9bccf70c
A
3853 lt6->ia6t_expire = 0;
3854 else {
91447636 3855 lt6->ia6t_expire = timenow.tv_sec;
9bccf70c 3856 lt6->ia6t_expire += lt6->ia6t_vltime;
1c79356b
A
3857 }
3858
3859 /* init ia6t_preferred */
6d2010ae 3860 if (!is_temporary && lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
1c79356b
A
3861 lt6->ia6t_preferred = 0;
3862 else {
91447636 3863 lt6->ia6t_preferred = timenow.tv_sec;
1c79356b
A
3864 lt6->ia6t_preferred += lt6->ia6t_pltime;
3865 }
1c79356b
A
3866}
3867
3868/*
3869 * Delete all the routing table entries that use the specified gateway.
3870 * XXX: this function causes search through all entries of routing table, so
3871 * it shouldn't be called when acting as a router.
3872 */
3873void
91447636
A
3874rt6_flush(
3875 struct in6_addr *gateway,
3876 struct ifnet *ifp)
1c79356b
A
3877{
3878 struct radix_node_head *rnh = rt_tables[AF_INET6];
1c79356b
A
3879
3880 /* We'll care only link-local addresses */
3881 if (!IN6_IS_ADDR_LINKLOCAL(gateway)) {
1c79356b
A
3882 return;
3883 }
b0d623f7 3884 lck_mtx_lock(rnh_lock);
1c79356b
A
3885 /* XXX: hack for KAME's link-local address kludge */
3886 gateway->s6_addr16[1] = htons(ifp->if_index);
3887
3888 rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
b0d623f7 3889 lck_mtx_unlock(rnh_lock);
1c79356b
A
3890}
3891
3892static int
91447636
A
3893rt6_deleteroute(
3894 struct radix_node *rn,
3895 void *arg)
1c79356b
A
3896{
3897#define SIN6(s) ((struct sockaddr_in6 *)s)
3898 struct rtentry *rt = (struct rtentry *)rn;
3899 struct in6_addr *gate = (struct in6_addr *)arg;
3900
b0d623f7 3901 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
91447636 3902
b0d623f7
A
3903 RT_LOCK(rt);
3904 if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6) {
3905 RT_UNLOCK(rt);
1c79356b 3906 return(0);
b0d623f7 3907 }
1c79356b 3908
b0d623f7
A
3909 if (!IN6_ARE_ADDR_EQUAL(gate, &SIN6(rt->rt_gateway)->sin6_addr)) {
3910 RT_UNLOCK(rt);
1c79356b 3911 return(0);
b0d623f7 3912 }
9bccf70c
A
3913 /*
3914 * Do not delete a static route.
3915 * XXX: this seems to be a bit ad-hoc. Should we consider the
3916 * 'cloned' bit instead?
3917 */
b0d623f7
A
3918 if ((rt->rt_flags & RTF_STATIC) != 0) {
3919 RT_UNLOCK(rt);
9bccf70c 3920 return(0);
b0d623f7 3921 }
1c79356b
A
3922 /*
3923 * We delete only host route. This means, in particular, we don't
3924 * delete default route.
3925 */
b0d623f7
A
3926 if ((rt->rt_flags & RTF_HOST) == 0) {
3927 RT_UNLOCK(rt);
1c79356b 3928 return(0);
b0d623f7 3929 }
1c79356b 3930
b0d623f7
A
3931 /*
3932 * Safe to drop rt_lock and use rt_key, rt_gateway, since holding
3933 * rnh_lock here prevents another thread from calling rt_setgate()
3934 * on this route.
3935 */
3936 RT_UNLOCK(rt);
3937 return (rtrequest_locked(RTM_DELETE, rt_key(rt), rt->rt_gateway,
3938 rt_mask(rt), rt->rt_flags, 0));
1c79356b
A
3939#undef SIN6
3940}
3941
3942int
91447636
A
3943nd6_setdefaultiface(
3944 int ifindex)
1c79356b
A
3945{
3946 int error = 0;
b0d623f7 3947 ifnet_t def_ifp = NULL;
6d2010ae
A
3948
3949 lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
1c79356b 3950
b0d623f7
A
3951 ifnet_head_lock_shared();
3952 if (ifindex < 0 || if_index < ifindex) {
3953 ifnet_head_done();
1c79356b 3954 return(EINVAL);
b0d623f7
A
3955 }
3956 def_ifp = ifindex2ifnet[ifindex];
3957 ifnet_head_done();
1c79356b 3958
91447636 3959 lck_mtx_lock(nd6_mutex);
1c79356b 3960 if (nd6_defifindex != ifindex) {
6d2010ae
A
3961 struct ifnet *odef_ifp = nd6_defifp;
3962
1c79356b
A
3963 nd6_defifindex = ifindex;
3964 if (nd6_defifindex > 0)
b0d623f7 3965 nd6_defifp = def_ifp;
1c79356b
A
3966 else
3967 nd6_defifp = NULL;
3968
6d2010ae
A
3969 if (nd6_defifp != NULL)
3970 nd6log((LOG_INFO, "%s: is now the default "
3971 "interface (was %s)\n", if_name(nd6_defifp),
3972 odef_ifp != NULL ? if_name(odef_ifp) : "NONE"));
3973 else
3974 nd6log((LOG_INFO, "No default interface set\n"));
3975
1c79356b
A
3976 /*
3977 * If the Default Router List is empty, install a route
3978 * to the specified interface as default or remove the default
3979 * route when the default interface becomes canceled.
3980 * The check for the queue is actually redundant, but
3981 * we do this here to avoid re-install the default route
3982 * if the list is NOT empty.
3983 */
6d2010ae
A
3984 if (ip6_doscopedroute || TAILQ_FIRST(&nd_defrouter) == NULL) {
3985 defrtrlist_sync(nd6_defifp);
3986 nd6_prefix_sync(nd6_defifp);
3987 }
9bccf70c
A
3988
3989 /*
3990 * Our current implementation assumes one-to-one maping between
3991 * interfaces and links, so it would be natural to use the
3992 * default interface as the default link.
3993 */
3994 scope6_setdefault(nd6_defifp);
1c79356b 3995 }
91447636 3996 lck_mtx_unlock(nd6_mutex);
6d2010ae 3997
1c79356b
A
3998 return(error);
3999}