1/*
2 * Copyright (c) 1998-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29/*
30 * Copyright (c) 1982, 1986, 1993
31 *	The Regents of the University of California.  All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 *    notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 *    notice, this list of conditions and the following disclaimer in the
40 *    documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 *    must display the following acknowledgement:
43 *	This product includes software developed by the University of
44 *	California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 *    may be used to endorse or promote products derived from this software
47 *    without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 *	@(#)uipc_domain.c	8.3 (Berkeley) 2/14/95
62 */
63
64#include <sys/param.h>
65#include <sys/socket.h>
66#include <sys/protosw.h>
67#include <sys/domain.h>
68#include <sys/mcache.h>
69#include <sys/mbuf.h>
70#include <sys/time.h>
71#include <sys/kernel.h>
72#include <sys/systm.h>
73#include <sys/proc_internal.h>
74#include <sys/sysctl.h>
75#include <sys/syslog.h>
76#include <sys/queue.h>
77
78#include <net/dlil.h>
79
80#include <mach/boolean.h>
81#include <pexpert/pexpert.h>
82
83static void pr_init_old(struct protosw *, struct domain *);
84static void init_proto(struct protosw *, struct domain *);
85static void attach_proto(struct protosw *, struct domain *);
86static void detach_proto(struct protosw *, struct domain *);
87static void dom_init_old(struct domain *);
88static void init_domain(struct domain *);
89static void attach_domain(struct domain *);
90static void detach_domain(struct domain *);
91static struct protosw *pffindprotonotype_locked(int, int, int);
92static struct domain *pffinddomain_locked(int);
93
94static boolean_t domain_timeout_run;	/* domain timer is scheduled to run */
95static boolean_t domain_draining;
96static void domain_sched_timeout(void);
97static void domain_timeout(void *);
98
99lck_grp_t	*domain_proto_mtx_grp;
100lck_attr_t	*domain_proto_mtx_attr;
101static lck_grp_attr_t	*domain_proto_mtx_grp_attr;
102decl_lck_mtx_data(static, domain_proto_mtx);
103decl_lck_mtx_data(static, domain_timeout_mtx);
104
105static u_int64_t _net_uptime;
106
107static void
108pr_init_old(struct protosw *pp, struct domain *dp)
109{
110#pragma unused(dp)
111	VERIFY(pp->pr_flags & PR_OLD);
112	VERIFY(pp->pr_old != NULL);
113
114	if (pp->pr_old->pr_init != NULL)
115		pp->pr_old->pr_init();
116}
117
118static void
119init_proto(struct protosw *pp, struct domain *dp)
120{
121	VERIFY(pp->pr_flags & PR_ATTACHED);
122
123	if (!(pp->pr_flags & PR_INITIALIZED)) {
124		TAILQ_INIT(&pp->pr_filter_head);
125		if (pp->pr_init != NULL)
126			pp->pr_init(pp, dp);
127		pp->pr_flags |= PR_INITIALIZED;
128	}
129}
130
131static void
132attach_proto(struct protosw *pp, struct domain *dp)
133{
134	domain_proto_mtx_lock_assert_held();
135	VERIFY(!(pp->pr_flags & PR_ATTACHED));
136	VERIFY(pp->pr_domain == NULL);
137	VERIFY(pp->pr_protosw == NULL);
138
139	TAILQ_INSERT_TAIL(&dp->dom_protosw, pp, pr_entry);
140	pp->pr_flags |= PR_ATTACHED;
141	pp->pr_domain = dp;
142	pp->pr_protosw = pp;
143
144	/* do some cleaning up on user request callbacks */
145	pru_sanitize(pp->pr_usrreqs);
146}
147
148static void
149detach_proto(struct protosw *pp, struct domain *dp)
150{
151	domain_proto_mtx_lock_assert_held();
152	VERIFY(pp->pr_flags & PR_ATTACHED);
153	VERIFY(pp->pr_domain == dp);
154	VERIFY(pp->pr_protosw == pp);
155
156	TAILQ_REMOVE(&dp->dom_protosw, pp, pr_entry);
157	pp->pr_flags &= ~PR_ATTACHED;
158	pp->pr_domain = NULL;
159	pp->pr_protosw = NULL;
160}
161
162static void
163dom_init_old(struct domain *dp)
164{
165	VERIFY(dp->dom_flags & DOM_OLD);
166	VERIFY(dp->dom_old != NULL);
167
168	if (dp->dom_old->dom_init != NULL)
169		dp->dom_old->dom_init();
170}
171
172static void
173init_domain(struct domain *dp)
174{
175	VERIFY(dp->dom_flags & DOM_ATTACHED);
176
177	if (!(dp->dom_flags & DOM_INITIALIZED)) {
178		lck_mtx_init(&dp->dom_mtx_s, domain_proto_mtx_grp,
179		    domain_proto_mtx_attr);
180		dp->dom_mtx = &dp->dom_mtx_s;
181		TAILQ_INIT(&dp->dom_protosw);
182		if (dp->dom_init != NULL)
183			dp->dom_init(dp);
184		dp->dom_flags |= DOM_INITIALIZED;
185	}
186
187	/* Recompute for new protocol */
188	if (_max_linkhdr < 16)		/* XXX - Sheesh; everything's ether? */
189		_max_linkhdr = 16;
190	_max_linkhdr = max_linkhdr;	/* round it up */
191
192	if (dp->dom_protohdrlen > _max_protohdr)
193		_max_protohdr = dp->dom_protohdrlen;
194	_max_protohdr = max_protohdr;	/* round it up */
195
196	max_hdr = max_linkhdr + max_protohdr;
197	max_datalen = MHLEN - max_hdr;
198}
199
200static void
201attach_domain(struct domain *dp)
202{
203	domain_proto_mtx_lock_assert_held();
204	VERIFY(!(dp->dom_flags & DOM_ATTACHED));
205
206	TAILQ_INSERT_TAIL(&domains, dp, dom_entry);
207	dp->dom_flags |= DOM_ATTACHED;
208}
209
210static void
211detach_domain(struct domain *dp)
212{
213	domain_proto_mtx_lock_assert_held();
214	VERIFY(dp->dom_flags & DOM_ATTACHED);
215
216	TAILQ_REMOVE(&domains, dp, dom_entry);
217	dp->dom_flags &= ~DOM_ATTACHED;
218
219	if (dp->dom_flags & DOM_OLD) {
220		struct domain_old *odp = dp->dom_old;
221
222		VERIFY(odp != NULL);
223		odp->dom_next = NULL;
224		odp->dom_mtx = NULL;
225	}
226}
227
228/*
229 * Exported (private) routine, indirection of net_add_domain.
230 */
231void
232net_add_domain_old(struct domain_old *odp)
233{
234	struct domain *dp;
235	domain_guard_t guard;
236
237	VERIFY(odp != NULL);
238
239	guard = domain_guard_deploy();
240	if ((dp = pffinddomain_locked(odp->dom_family)) != NULL) {
241		/*
242		 * There is really nothing better than to panic here,
243		 * as the caller would not have been able to handle
244		 * any failures otherwise.
245		 */
246		panic("%s: domain (%d,%s) already exists for %s\n", __func__,
247		    dp->dom_family, dp->dom_name, odp->dom_name);
248		/* NOTREACHED */
249	}
250
251	/* Make sure nothing is currently pointing to the odp. */
252	TAILQ_FOREACH(dp, &domains, dom_entry) {
253		if (dp->dom_old == odp) {
254			panic("%s: domain %p (%d,%s) is already "
255			    "associated with %p (%d,%s)\n", __func__,
256			    odp, odp->dom_family, odp->dom_name, dp,
257			    dp->dom_family, dp->dom_name);
258			/* NOTREACHED */
259		}
260	}
261
262	if (odp->dom_protosw != NULL) {
263		panic("%s: domain (%d,%s) protocols need to added "
264		    "via net_add_proto\n", __func__, odp->dom_family,
265		    odp->dom_name);
266		/* NOTREACHED */
267	}
268
269	dp = _MALLOC(sizeof (*dp), M_TEMP, M_WAITOK | M_ZERO);
270	if (dp == NULL) {
271		/*
272		 * There is really nothing better than to panic here,
273		 * as the caller would not have been able to handle
274		 * any failures otherwise.
275		 */
276		panic("%s: unable to allocate memory for domain family "
277		    "%d (%s)\n", __func__, odp->dom_family, odp->dom_name);
278		/* NOTREACHED */
279	}
280
281	/* Copy everything but dom_init, dom_mtx, dom_next and dom_refs */
282	dp->dom_family		= odp->dom_family;
283	dp->dom_flags		= (odp->dom_flags & DOMF_USERFLAGS) | DOM_OLD;
284	dp->dom_name		= odp->dom_name;
285	dp->dom_init		= dom_init_old;
286	dp->dom_externalize	= odp->dom_externalize;
287	dp->dom_dispose		= odp->dom_dispose;
288	dp->dom_rtattach	= odp->dom_rtattach;
289	dp->dom_rtoffset	= odp->dom_rtoffset;
290	dp->dom_maxrtkey	= odp->dom_maxrtkey;
291	dp->dom_protohdrlen	= odp->dom_protohdrlen;
292	dp->dom_old		= odp;
293
294	attach_domain(dp);
295	init_domain(dp);
296
297	/* Point the mutex back to the internal structure's */
298	odp->dom_mtx		= dp->dom_mtx;
299	domain_guard_release(guard);
300}
301
302/*
303 * Exported (private) routine, indirection of net_del_domain.
304 */
305int
306net_del_domain_old(struct domain_old *odp)
307{
308	struct domain *dp1, *dp2;
309	int error = 0;
310	domain_guard_t guard;
311
312	VERIFY(odp != NULL);
313
314	guard = domain_guard_deploy();
315	if (odp->dom_refs != 0) {
316		error = EBUSY;
317		goto done;
318	}
319
320	TAILQ_FOREACH_SAFE(dp1, &domains, dom_entry, dp2) {
321		if (!(dp1->dom_flags & DOM_OLD))
322			continue;
323		VERIFY(dp1->dom_old != NULL);
324		if (odp == dp1->dom_old)
325			break;
326	}
327	if (dp1 != NULL) {
328		struct protosw *pp1, *pp2;
329
330		VERIFY(dp1->dom_flags & DOM_OLD);
331		VERIFY(dp1->dom_old == odp);
332
333		/* Remove all protocols attached to this domain */
334		TAILQ_FOREACH_SAFE(pp1, &dp1->dom_protosw, pr_entry, pp2) {
335			detach_proto(pp1, dp1);
336			if (pp1->pr_usrreqs->pru_flags & PRUF_OLD)
337				FREE(pp1->pr_usrreqs, M_TEMP);
338			if (pp1->pr_flags & PR_OLD)
339				FREE(pp1, M_TEMP);
340		}
341
342		detach_domain(dp1);
343		FREE(dp1, M_TEMP);
344	} else {
345		error = EPFNOSUPPORT;
346	}
347done:
348	domain_guard_release(guard);
349	return (error);
350}
351
352/*
353 * Internal routine, not exported.
354 *
355 * net_add_proto - link a protosw into a domain's protosw chain
356 *
357 * NOTE: Caller must have acquired domain_proto_mtx
358 */
359int
360net_add_proto(struct protosw *pp, struct domain *dp, int doinit)
361{
362	struct protosw *pp1;
363
364	/*
365	 * This could be called as part of initializing the domain,
366	 * and thus DOM_INITIALIZED may not be set (yet).
367	 */
368	domain_proto_mtx_lock_assert_held();
369	VERIFY(!(pp->pr_flags & PR_ATTACHED));
370
371	/* pr_domain is set only after the protocol is attached */
372	if (pp->pr_domain != NULL) {
373		panic("%s: domain (%d,%s), proto %d has non-NULL pr_domain!\n",
374		    __func__, dp->dom_family, dp->dom_name, pp->pr_protocol);
375		/* NOTREACHED */
376	}
377
378	if (pp->pr_usrreqs == NULL) {
379		panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
380		    __func__, dp->dom_family, dp->dom_name, pp->pr_protocol);
381		/* NOTREACHED */
382	}
383
384	TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) {
385		if (pp1->pr_type == pp->pr_type &&
386		    pp1->pr_protocol == pp->pr_protocol)
387			return (EEXIST);
388	}
389
390	attach_proto(pp, dp);
391	if (doinit)
392		net_init_proto(pp, dp);
393
394	return (0);
395}
396
397void
398net_init_proto(struct protosw *pp, struct domain *dp)
399{
400	/*
401	 * This could be called as part of initializing the domain,
402	 * and thus DOM_INITIALIZED may not be set (yet).  The protocol
403	 * must have been attached via net_addr_protosw() by now.
404	 */
405	domain_proto_mtx_lock_assert_held();
406	VERIFY(pp->pr_flags & PR_ATTACHED);
407
408	init_proto(pp, dp);
409}
410
411/*
412 * Exported (private) routine, indirection of net_add_proto.
413 */
414int
415net_add_proto_old(struct protosw_old *opp, struct domain_old *odp)
416{
417	struct pr_usrreqs_old *opru;
418	struct pr_usrreqs *pru = NULL;
419	struct protosw *pp = NULL, *pp1;
420	int error = 0;
421	struct domain *dp;
422	domain_guard_t guard;
423
424	/*
425	 * This could be called as part of initializing the domain,
426	 * and thus DOM_INITIALIZED may not be set (yet).
427	 */
428	guard = domain_guard_deploy();
429
430	/* Make sure the domain has been added via net_add_domain */
431	TAILQ_FOREACH(dp, &domains, dom_entry) {
432		if (!(dp->dom_flags & DOM_OLD))
433			continue;
434		if (dp->dom_old == odp)
435			break;
436	}
437	if (dp == NULL) {
438		error = EINVAL;
439		goto done;
440	}
441
442	TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) {
443		if (pp1->pr_type == opp->pr_type &&
444		    pp1->pr_protocol == opp->pr_protocol) {
445			error = EEXIST;
446			goto done;
447		}
448	}
449
450	if ((opru = opp->pr_usrreqs) == NULL) {
451		panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
452		    __func__, odp->dom_family, odp->dom_name, opp->pr_protocol);
453		/* NOTREACHED */
454	}
455
456	pru = _MALLOC(sizeof (*pru), M_TEMP, M_WAITOK | M_ZERO);
457	if (pru == NULL) {
458		error = ENOMEM;
459		goto done;
460	}
461
462	pru->pru_flags		= PRUF_OLD;
463	pru->pru_abort		= opru->pru_abort;
464	pru->pru_accept		= opru->pru_accept;
465	pru->pru_attach		= opru->pru_attach;
466	pru->pru_bind		= opru->pru_bind;
467	pru->pru_connect	= opru->pru_connect;
468	pru->pru_connect2	= opru->pru_connect2;
469	pru->pru_control	= opru->pru_control;
470	pru->pru_detach		= opru->pru_detach;
471	pru->pru_disconnect	= opru->pru_disconnect;
472	pru->pru_listen		= opru->pru_listen;
473	pru->pru_peeraddr	= opru->pru_peeraddr;
474	pru->pru_rcvd		= opru->pru_rcvd;
475	pru->pru_rcvoob		= opru->pru_rcvoob;
476	pru->pru_send		= opru->pru_send;
477	pru->pru_sense		= opru->pru_sense;
478	pru->pru_shutdown	= opru->pru_shutdown;
479	pru->pru_sockaddr	= opru->pru_sockaddr;
480	pru->pru_sosend		= opru->pru_sosend;
481	pru->pru_soreceive	= opru->pru_soreceive;
482	pru->pru_sopoll		= opru->pru_sopoll;
483
484	pp = _MALLOC(sizeof (*pp), M_TEMP, M_WAITOK | M_ZERO);
485	if (pp == NULL) {
486		error = ENOMEM;
487		goto done;
488	}
489
490	/*
491	 * Protocol fast and slow timers are now deprecated.
492	 */
493	if (opp->pr_unused != NULL) {
494		printf("%s: domain (%d,%s), proto %d: pr_fasttimo is "
495		    "deprecated and won't be called\n", __func__,
496		    odp->dom_family, odp->dom_name, opp->pr_protocol);
497	}
498	if (opp->pr_unused2 != NULL) {
499		printf("%s: domain (%d,%s), proto %d: pr_slowtimo is "
500		    "deprecated and won't be called\n", __func__,
501		    odp->dom_family, odp->dom_name, opp->pr_protocol);
502	}
503
504	/* Copy everything but pr_init, pr_next, pr_domain, pr_protosw */
505	pp->pr_type		= opp->pr_type;
506	pp->pr_protocol		= opp->pr_protocol;
507	pp->pr_flags		= (opp->pr_flags & PRF_USERFLAGS) | PR_OLD;
508	pp->pr_input		= opp->pr_input;
509	pp->pr_output		= opp->pr_output;
510	pp->pr_ctlinput		= opp->pr_ctlinput;
511	pp->pr_ctloutput	= opp->pr_ctloutput;
512	pp->pr_usrreqs		= pru;
513	pp->pr_init		= pr_init_old;
514	pp->pr_drain		= opp->pr_drain;
515	pp->pr_sysctl		= opp->pr_sysctl;
516	pp->pr_lock		= opp->pr_lock;
517	pp->pr_unlock		= opp->pr_unlock;
518	pp->pr_getlock		= opp->pr_getlock;
519	pp->pr_old		= opp;
520
521	/* attach as well as initialize */
522	attach_proto(pp, dp);
523	net_init_proto(pp, dp);
524done:
525	if (error != 0) {
526		printf("%s: domain (%d,%s), proto %d: failed to attach, "
527		    "error %d\n", __func__, odp->dom_family,
528		    odp->dom_name, opp->pr_protocol, error);
529
530		if (pru != NULL)
531			FREE(pru, M_TEMP);
532		if (pp != NULL)
533			FREE(pp, M_TEMP);
534	}
535
536	domain_guard_release(guard);
537	return (error);
538}
539
540/*
541 * Internal routine, not exported.
542 *
543 * net_del_proto - remove a protosw from a domain's protosw chain.
544 * Search the protosw chain for the element with matching data.
545 * Then unlink and return.
546 *
547 * NOTE: Caller must have acquired domain_proto_mtx
548 */
549int
550net_del_proto(int type, int protocol, struct domain *dp)
551{
552	struct protosw *pp;
553
554	/*
555	 * This could be called as part of initializing the domain,
556	 * and thus DOM_INITIALIZED may not be set (yet).
557	 */
558	domain_proto_mtx_lock_assert_held();
559
560	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
561		if (pp->pr_type == type && pp->pr_protocol == protocol)
562			break;
563	}
564	if (pp == NULL)
565		return (ENXIO);
566
567	detach_proto(pp, dp);
568	if (pp->pr_usrreqs->pru_flags & PRUF_OLD)
569		FREE(pp->pr_usrreqs, M_TEMP);
570	if (pp->pr_flags & PR_OLD)
571		FREE(pp, M_TEMP);
572
573	return (0);
574}
575
576/*
577 * Exported (private) routine, indirection of net_del_proto.
578 */
579int
580net_del_proto_old(int type, int protocol, struct domain_old *odp)
581{
582	int error = 0;
583	struct protosw *pp;
584	struct domain *dp;
585	domain_guard_t guard;
586
587	/*
588	 * This could be called as part of initializing the domain,
589	 * and thus DOM_INITIALIZED may not be set (yet).
590	 */
591	guard = domain_guard_deploy();
592
593	/* Make sure the domain has been added via net_add_domain */
594	TAILQ_FOREACH(dp, &domains, dom_entry) {
595		if (!(dp->dom_flags & DOM_OLD))
596			continue;
597		if (dp->dom_old == odp)
598			break;
599	}
600	if (dp == NULL) {
601		error = ENXIO;
602		goto done;
603	}
604
605	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
606		if (pp->pr_type == type && pp->pr_protocol == protocol)
607			break;
608	}
609	if (pp == NULL) {
610		error = ENXIO;
611		goto done;
612	}
613	detach_proto(pp, dp);
614	if (pp->pr_usrreqs->pru_flags & PRUF_OLD)
615		FREE(pp->pr_usrreqs, M_TEMP);
616	if (pp->pr_flags & PR_OLD)
617		FREE(pp, M_TEMP);
618
619done:
620	domain_guard_release(guard);
621	return (error);
622}
623
624static void
625domain_sched_timeout(void)
626{
627	lck_mtx_assert(&domain_timeout_mtx, LCK_MTX_ASSERT_OWNED);
628
629	if (!domain_timeout_run && domain_draining) {
630		domain_timeout_run = TRUE;
631		timeout(domain_timeout, NULL, hz);
632	}
633}
634
635void
636net_drain_domains(void)
637{
638	lck_mtx_lock(&domain_timeout_mtx);
639	domain_draining = TRUE;
640	domain_sched_timeout();
641	lck_mtx_unlock(&domain_timeout_mtx);
642}
643
644#if INET6
645extern struct domain inet6domain_s;
646#endif
647#if IPSEC
648extern struct domain keydomain_s;
649#endif
650
651extern struct domain routedomain_s, ndrvdomain_s, inetdomain_s;
652extern struct domain systemdomain_s, localdomain_s;
653
654#if MULTIPATH
655extern struct domain mpdomain_s;
656#endif /* MULTIPATH */
657
658static void
659domain_timeout(void *arg)
660{
661#pragma unused(arg)
662	struct protosw *pp;
663	struct domain *dp;
664	domain_guard_t guard;
665
666	lck_mtx_lock(&domain_timeout_mtx);
667	if (domain_draining) {
668		domain_draining = FALSE;
669		lck_mtx_unlock(&domain_timeout_mtx);
670
671		guard = domain_guard_deploy();
672		TAILQ_FOREACH(dp, &domains, dom_entry) {
673			TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
674				if (pp->pr_drain != NULL)
675					(*pp->pr_drain)();
676			}
677		}
678		domain_guard_release(guard);
679
680		lck_mtx_lock(&domain_timeout_mtx);
681	}
682
683	/* re-arm the timer if there's work to do */
684	domain_timeout_run = FALSE;
685	domain_sched_timeout();
686	lck_mtx_unlock(&domain_timeout_mtx);
687}
688
689void
690domaininit(void)
691{
692	struct domain *dp;
693	domain_guard_t guard;
694
695	/*
696	 * allocate lock group attribute and group for domain mutexes
697	 */
698	domain_proto_mtx_grp_attr = lck_grp_attr_alloc_init();
699
700	domain_proto_mtx_grp = lck_grp_alloc_init("domain",
701	    domain_proto_mtx_grp_attr);
702
703	/*
704	 * allocate the lock attribute for per domain mutexes
705	 */
706	domain_proto_mtx_attr = lck_attr_alloc_init();
707
708	lck_mtx_init(&domain_proto_mtx, domain_proto_mtx_grp,
709	    domain_proto_mtx_attr);
710	lck_mtx_init(&domain_timeout_mtx, domain_proto_mtx_grp,
711	    domain_proto_mtx_attr);
712
713	guard = domain_guard_deploy();
714	/*
715	 * Add all the static domains to the domains list.  route domain
716	 * gets added and initialized last, since we need it to attach
717	 * rt_tables[] to everything that's already there.  This also
718	 * means that domains added after this point won't get their
719	 * dom_rtattach() called on rt_tables[].
720	 */
721	attach_domain(&inetdomain_s);
722#if INET6
723	attach_domain(&inet6domain_s);
724#endif /* INET6 */
725#if MULTIPATH
726	attach_domain(&mpdomain_s);
727#endif /* MULTIPATH */
728	attach_domain(&systemdomain_s);
729	attach_domain(&localdomain_s);
730#if IPSEC
731	attach_domain(&keydomain_s);
732#endif /* IPSEC */
733	attach_domain(&ndrvdomain_s);
734	attach_domain(&routedomain_s);	/* must be last domain */
735
736	/*
737	 * Now ask them all to init (XXX including the routing domain,
738	 * see above)
739	 */
740	TAILQ_FOREACH(dp, &domains, dom_entry)
741		init_domain(dp);
742
743	domain_guard_release(guard);
744}
745
746static __inline__ struct domain *
747pffinddomain_locked(int pf)
748{
749	struct domain *dp;
750
751	domain_proto_mtx_lock_assert_held();
752
753	TAILQ_FOREACH(dp, &domains, dom_entry) {
754		if (dp->dom_family == pf)
755			break;
756	}
757	return (dp);
758}
759
760struct protosw *
761pffindtype(int family, int type)
762{
763	struct protosw *pp = NULL;
764	struct domain *dp;
765	domain_guard_t guard;
766
767	guard = domain_guard_deploy();
768	if ((dp = pffinddomain_locked(family)) == NULL)
769		goto done;
770
771	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
772		if (pp->pr_type != 0 && pp->pr_type == type)
773			goto done;
774	}
775done:
776	domain_guard_release(guard);
777	return (pp);
778}
779
780/*
781 * Internal routine, not exported.
782 */
783struct domain *
784pffinddomain(int pf)
785{
786	struct domain *dp;
787	domain_guard_t guard;
788
789	guard = domain_guard_deploy();
790	dp = pffinddomain_locked(pf);
791	domain_guard_release(guard);
792	return (dp);
793}
794
795/*
796 * Exported (private) routine, indirection of pffinddomain.
797 */
798struct domain_old *
799pffinddomain_old(int pf)
800{
801	struct domain_old *odp = NULL;
802	struct domain *dp;
803	domain_guard_t guard;
804
805	guard = domain_guard_deploy();
806	if ((dp = pffinddomain_locked(pf)) != NULL && (dp->dom_flags & DOM_OLD))
807		odp = dp->dom_old;
808	domain_guard_release(guard);
809	return (odp);
810}
811
812/*
813 * Internal routine, not exported.
814 */
815struct protosw *
816pffindproto(int family, int protocol, int type)
817{
818	struct protosw *pp;
819	domain_guard_t guard;
820
821	guard = domain_guard_deploy();
822	pp = pffindproto_locked(family, protocol, type);
823	domain_guard_release(guard);
824	return (pp);
825}
826
827struct protosw *
828pffindproto_locked(int family, int protocol, int type)
829{
830	struct protosw *maybe = NULL;
831	struct protosw *pp;
832	struct domain *dp;
833
834	domain_proto_mtx_lock_assert_held();
835
836	if (family == 0)
837		return (0);
838
839	dp = pffinddomain_locked(family);
840	if (dp == NULL)
841		return (NULL);
842
843	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
844		if ((pp->pr_protocol == protocol) && (pp->pr_type == type))
845			return (pp);
846
847		if (type == SOCK_RAW && pp->pr_type == SOCK_RAW &&
848		    pp->pr_protocol == 0 && maybe == NULL)
849			maybe = pp;
850	}
851	return (maybe);
852}
853
854/*
855 * Exported (private) routine, indirection of pffindproto.
856 */
857struct protosw_old *
858pffindproto_old(int family, int protocol, int type)
859{
860	struct protosw_old *opr = NULL;
861	struct protosw *pp;
862	domain_guard_t guard;
863
864	guard = domain_guard_deploy();
865	if ((pp = pffindproto_locked(family, protocol, type)) != NULL &&
866	    (pp->pr_flags & PR_OLD))
867		opr = pp->pr_old;
868	domain_guard_release(guard);
869	return (opr);
870}
871
872static struct protosw *
873pffindprotonotype_locked(int family, int protocol, int type)
874{
875#pragma unused(type)
876	struct domain *dp;
877	struct protosw *pp;
878
879	domain_proto_mtx_lock_assert_held();
880
881	if (family == 0)
882		return (0);
883
884	dp = pffinddomain_locked(family);
885	if (dp == NULL)
886		return (NULL);
887
888	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
889		if (pp->pr_protocol == protocol)
890			return (pp);
891	}
892	return (NULL);
893}
894
895struct protosw *
896pffindprotonotype(int family, int protocol)
897{
898	struct protosw *pp;
899	domain_guard_t guard;
900
901	if (protocol == 0)
902		return (NULL);
903
904	guard = domain_guard_deploy();
905	pp = pffindprotonotype_locked(family, protocol, 0);
906	domain_guard_release(guard);
907	return (pp);
908}
909
910void
911pfctlinput(int cmd, struct sockaddr *sa)
912{
913	pfctlinput2(cmd, sa, NULL);
914}
915
916void
917pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam)
918{
919	struct domain *dp;
920	struct protosw *pp;
921	domain_guard_t guard;
922
923	if (sa == NULL)
924		return;
925
926	guard = domain_guard_deploy();
927	TAILQ_FOREACH(dp, &domains, dom_entry) {
928		TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
929			if (pp->pr_ctlinput != NULL)
930				(*pp->pr_ctlinput)(cmd, sa, ctlparam);
931		}
932	}
933	domain_guard_release(guard);
934}
935
936void
937net_update_uptime(void)
938{
939	struct timeval tv;
940
941	microuptime(&tv);
942	_net_uptime = tv.tv_sec;
943	/*
944	 * Round up the timer to the nearest integer value because otherwise
945	 * we might setup networking timers that are off by almost 1 second.
946	 */
947	if (tv.tv_usec > 500000)
948		_net_uptime++;
949}
950
951void
952net_update_uptime_secs(uint64_t secs)
953{
954	_net_uptime = secs;
955}
956
957/*
958 * Convert our uin64_t net_uptime to a struct timeval.
959 */
960void
961net_uptime2timeval(struct timeval *tv)
962{
963	if (tv == NULL)
964		return;
965
966	tv->tv_usec = 0;
967	tv->tv_sec = net_uptime();
968}
969
970/*
971 * An alternative way to obtain the coarse-grained uptime (in seconds)
972 * for networking code which do not require high-precision timestamp,
973 * as this is significantly cheaper than microuptime().
974 */
975u_int64_t
976net_uptime(void)
977{
978	if (_net_uptime == 0)
979		net_update_uptime();
980
981	return (_net_uptime);
982}
983
984void
985domain_proto_mtx_lock_assert_held(void)
986{
987	lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
988}
989
990void
991domain_proto_mtx_lock_assert_notheld(void)
992{
993	lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
994}
995
996domain_guard_t
997domain_guard_deploy(void)
998{
999	net_thread_marks_t marks;
1000
1001	marks = net_thread_marks_push(NET_THREAD_HELD_DOMAIN);
1002	if (marks != net_thread_marks_none) {
1003		lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1004		lck_mtx_lock(&domain_proto_mtx);
1005	}
1006	else
1007		lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1008
1009	return ((domain_guard_t)(const void*)marks);
1010}
1011
1012void
1013domain_guard_release(domain_guard_t guard)
1014{
1015	net_thread_marks_t marks = (net_thread_marks_t)(const void*)guard;
1016
1017	if (marks != net_thread_marks_none) {
1018		lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1019		lck_mtx_unlock(&domain_proto_mtx);
1020		net_thread_marks_pop(marks);
1021	}
1022	else
1023		lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1024}
1025
1026domain_unguard_t
1027domain_unguard_deploy(void)
1028{
1029	net_thread_marks_t marks;
1030
1031	marks = net_thread_unmarks_push(NET_THREAD_HELD_DOMAIN);
1032	if (marks != net_thread_marks_none) {
1033		lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1034		lck_mtx_unlock(&domain_proto_mtx);
1035	}
1036	else
1037		lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1038
1039	return ((domain_unguard_t)(const void*)marks);
1040}
1041
1042void
1043domain_unguard_release(domain_unguard_t unguard)
1044{
1045	net_thread_marks_t marks = (net_thread_marks_t)(const void*)unguard;
1046
1047	if (marks != net_thread_marks_none) {
1048		lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1049		lck_mtx_lock(&domain_proto_mtx);
1050		net_thread_unmarks_pop(marks);
1051	}
1052	else
1053		lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1054}
1055