2 * Copyright (c) 1998-2018 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
30 * Copyright (c) 1982, 1986, 1993
31 * The Regents of the University of California. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
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.
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
61 * @(#)uipc_domain.c 8.3 (Berkeley) 2/14/95
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>
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>
79 #include <net/nwk_wq.h>
81 #include <mach/boolean.h>
82 #include <pexpert/pexpert.h>
84 /* Eventhandler context for protocol events */
85 struct eventhandler_lists_ctxt protoctl_evhdlr_ctxt
;
87 static void pr_init_old(struct protosw
*, struct domain
*);
88 static void init_proto(struct protosw
*, struct domain
*);
89 static void attach_proto(struct protosw
*, struct domain
*);
90 static void detach_proto(struct protosw
*, struct domain
*);
91 static void dom_init_old(struct domain
*);
92 static void init_domain(struct domain
*);
93 static void attach_domain(struct domain
*);
94 static void detach_domain(struct domain
*);
95 static struct protosw
*pffindprotonotype_locked(int, int, int);
96 static struct domain
*pffinddomain_locked(int);
98 static boolean_t domain_timeout_run
; /* domain timer is scheduled to run */
99 static boolean_t domain_draining
;
100 static void domain_sched_timeout(void);
101 static void domain_timeout(void *);
103 lck_grp_t
*domain_proto_mtx_grp
;
104 lck_attr_t
*domain_proto_mtx_attr
;
105 static lck_grp_attr_t
*domain_proto_mtx_grp_attr
;
106 decl_lck_mtx_data(static, domain_proto_mtx
);
107 decl_lck_mtx_data(static, domain_timeout_mtx
);
109 u_int64_t _net_uptime
;
110 u_int64_t _net_uptime_ms
;
112 #if (DEVELOPMENT || DEBUG)
114 SYSCTL_DECL(_kern_ipc
);
116 static int sysctl_do_drain_domains SYSCTL_HANDLER_ARGS
;
118 SYSCTL_PROC(_kern_ipc
, OID_AUTO
, do_drain_domains
,
119 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
,
121 sysctl_do_drain_domains
, "I", "force manual drain domains");
123 #endif /* DEVELOPMENT || DEBUG */
126 pr_init_old(struct protosw
*pp
, struct domain
*dp
)
129 VERIFY(pp
->pr_flags
& PR_OLD
);
130 VERIFY(pp
->pr_old
!= NULL
);
132 if (pp
->pr_old
->pr_init
!= NULL
) {
133 pp
->pr_old
->pr_init();
138 init_proto(struct protosw
*pp
, struct domain
*dp
)
140 VERIFY(pp
->pr_flags
& PR_ATTACHED
);
142 if (!(pp
->pr_flags
& PR_INITIALIZED
)) {
143 TAILQ_INIT(&pp
->pr_filter_head
);
144 if (pp
->pr_init
!= NULL
) {
147 pp
->pr_flags
|= PR_INITIALIZED
;
152 attach_proto(struct protosw
*pp
, struct domain
*dp
)
154 domain_proto_mtx_lock_assert_held();
155 VERIFY(!(pp
->pr_flags
& PR_ATTACHED
));
156 VERIFY(pp
->pr_domain
== NULL
);
157 VERIFY(pp
->pr_protosw
== NULL
);
159 TAILQ_INSERT_TAIL(&dp
->dom_protosw
, pp
, pr_entry
);
160 pp
->pr_flags
|= PR_ATTACHED
;
164 /* do some cleaning up on user request callbacks */
165 pru_sanitize(pp
->pr_usrreqs
);
169 detach_proto(struct protosw
*pp
, struct domain
*dp
)
171 domain_proto_mtx_lock_assert_held();
172 VERIFY(pp
->pr_flags
& PR_ATTACHED
);
173 VERIFY(pp
->pr_domain
== dp
);
174 VERIFY(pp
->pr_protosw
== pp
);
176 TAILQ_REMOVE(&dp
->dom_protosw
, pp
, pr_entry
);
177 pp
->pr_flags
&= ~PR_ATTACHED
;
178 pp
->pr_domain
= NULL
;
179 pp
->pr_protosw
= NULL
;
183 dom_init_old(struct domain
*dp
)
185 VERIFY(dp
->dom_flags
& DOM_OLD
);
186 VERIFY(dp
->dom_old
!= NULL
);
188 if (dp
->dom_old
->dom_init
!= NULL
) {
189 dp
->dom_old
->dom_init();
194 init_domain(struct domain
*dp
)
196 VERIFY(dp
->dom_flags
& DOM_ATTACHED
);
198 if (!(dp
->dom_flags
& DOM_INITIALIZED
)) {
199 lck_mtx_init(&dp
->dom_mtx_s
, domain_proto_mtx_grp
,
200 domain_proto_mtx_attr
);
201 dp
->dom_mtx
= &dp
->dom_mtx_s
;
202 TAILQ_INIT(&dp
->dom_protosw
);
203 if (dp
->dom_init
!= NULL
) {
206 dp
->dom_flags
|= DOM_INITIALIZED
;
209 /* Recompute for new protocol */
210 if (_max_linkhdr
< 16) { /* XXX - Sheesh; everything's ether? */
213 _max_linkhdr
= max_linkhdr
; /* round it up */
215 if (dp
->dom_protohdrlen
> _max_protohdr
) {
216 _max_protohdr
= dp
->dom_protohdrlen
;
218 _max_protohdr
= max_protohdr
; /* round it up */
220 max_hdr
= max_linkhdr
+ max_protohdr
;
221 max_datalen
= MHLEN
- max_hdr
;
225 attach_domain(struct domain
*dp
)
227 domain_proto_mtx_lock_assert_held();
228 VERIFY(!(dp
->dom_flags
& DOM_ATTACHED
));
230 TAILQ_INSERT_TAIL(&domains
, dp
, dom_entry
);
231 dp
->dom_flags
|= DOM_ATTACHED
;
235 detach_domain(struct domain
*dp
)
237 domain_proto_mtx_lock_assert_held();
238 VERIFY(dp
->dom_flags
& DOM_ATTACHED
);
240 TAILQ_REMOVE(&domains
, dp
, dom_entry
);
241 dp
->dom_flags
&= ~DOM_ATTACHED
;
243 if (dp
->dom_flags
& DOM_OLD
) {
244 struct domain_old
*odp
= dp
->dom_old
;
247 odp
->dom_next
= NULL
;
253 * Exported (private) routine, indirection of net_add_domain.
256 net_add_domain_old(struct domain_old
*odp
)
259 domain_guard_t guard
;
263 guard
= domain_guard_deploy();
264 if ((dp
= pffinddomain_locked(odp
->dom_family
)) != NULL
) {
266 * There is really nothing better than to panic here,
267 * as the caller would not have been able to handle
268 * any failures otherwise.
270 panic("%s: domain (%d,%s) already exists for %s\n", __func__
,
271 dp
->dom_family
, dp
->dom_name
, odp
->dom_name
);
275 /* Make sure nothing is currently pointing to the odp. */
276 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
277 if (dp
->dom_old
== odp
) {
278 panic("%s: domain %p (%d,%s) is already "
279 "associated with %p (%d,%s)\n", __func__
,
280 odp
, odp
->dom_family
, odp
->dom_name
, dp
,
281 dp
->dom_family
, dp
->dom_name
);
286 if (odp
->dom_protosw
!= NULL
) {
287 panic("%s: domain (%d,%s) protocols need to added "
288 "via net_add_proto\n", __func__
, odp
->dom_family
,
293 dp
= _MALLOC(sizeof(*dp
), M_TEMP
, M_WAITOK
| M_ZERO
);
296 * There is really nothing better than to panic here,
297 * as the caller would not have been able to handle
298 * any failures otherwise.
300 panic("%s: unable to allocate memory for domain family "
301 "%d (%s)\n", __func__
, odp
->dom_family
, odp
->dom_name
);
305 /* Copy everything but dom_init, dom_mtx, dom_next and dom_refs */
306 dp
->dom_family
= odp
->dom_family
;
307 dp
->dom_flags
= (odp
->dom_flags
& DOMF_USERFLAGS
) | DOM_OLD
;
308 dp
->dom_name
= odp
->dom_name
;
309 dp
->dom_init
= dom_init_old
;
310 dp
->dom_externalize
= odp
->dom_externalize
;
311 dp
->dom_dispose
= odp
->dom_dispose
;
312 dp
->dom_rtattach
= odp
->dom_rtattach
;
313 dp
->dom_rtoffset
= odp
->dom_rtoffset
;
314 dp
->dom_maxrtkey
= odp
->dom_maxrtkey
;
315 dp
->dom_protohdrlen
= odp
->dom_protohdrlen
;
321 /* Point the mutex back to the internal structure's */
322 odp
->dom_mtx
= dp
->dom_mtx
;
323 domain_guard_release(guard
);
327 * Exported (private) routine, indirection of net_del_domain.
330 net_del_domain_old(struct domain_old
*odp
)
332 struct domain
*dp1
, *dp2
;
334 domain_guard_t guard
;
338 guard
= domain_guard_deploy();
339 if (odp
->dom_refs
!= 0) {
344 TAILQ_FOREACH_SAFE(dp1
, &domains
, dom_entry
, dp2
) {
345 if (!(dp1
->dom_flags
& DOM_OLD
)) {
348 VERIFY(dp1
->dom_old
!= NULL
);
349 if (odp
== dp1
->dom_old
) {
354 struct protosw
*pp1
, *pp2
;
356 VERIFY(dp1
->dom_flags
& DOM_OLD
);
357 VERIFY(dp1
->dom_old
== odp
);
359 /* Remove all protocols attached to this domain */
360 TAILQ_FOREACH_SAFE(pp1
, &dp1
->dom_protosw
, pr_entry
, pp2
) {
361 detach_proto(pp1
, dp1
);
362 if (pp1
->pr_usrreqs
->pru_flags
& PRUF_OLD
) {
363 FREE(pp1
->pr_usrreqs
, M_TEMP
);
365 if (pp1
->pr_flags
& PR_OLD
) {
373 error
= EPFNOSUPPORT
;
376 domain_guard_release(guard
);
381 * Internal routine, not exported.
383 * net_add_proto - link a protosw into a domain's protosw chain
385 * NOTE: Caller must have acquired domain_proto_mtx
388 net_add_proto(struct protosw
*pp
, struct domain
*dp
, int doinit
)
393 * This could be called as part of initializing the domain,
394 * and thus DOM_INITIALIZED may not be set (yet).
396 domain_proto_mtx_lock_assert_held();
397 VERIFY(!(pp
->pr_flags
& PR_ATTACHED
));
399 /* pr_domain is set only after the protocol is attached */
400 if (pp
->pr_domain
!= NULL
) {
401 panic("%s: domain (%d,%s), proto %d has non-NULL pr_domain!\n",
402 __func__
, dp
->dom_family
, dp
->dom_name
, pp
->pr_protocol
);
406 if (pp
->pr_usrreqs
== NULL
) {
407 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
408 __func__
, dp
->dom_family
, dp
->dom_name
, pp
->pr_protocol
);
412 TAILQ_FOREACH(pp1
, &dp
->dom_protosw
, pr_entry
) {
413 if (pp1
->pr_type
== pp
->pr_type
&&
414 pp1
->pr_protocol
== pp
->pr_protocol
) {
419 attach_proto(pp
, dp
);
421 net_init_proto(pp
, dp
);
428 net_init_proto(struct protosw
*pp
, struct domain
*dp
)
431 * This could be called as part of initializing the domain,
432 * and thus DOM_INITIALIZED may not be set (yet). The protocol
433 * must have been attached via net_addr_protosw() by now.
435 domain_proto_mtx_lock_assert_held();
436 VERIFY(pp
->pr_flags
& PR_ATTACHED
);
442 * Exported (private) routine, indirection of net_add_proto.
445 net_add_proto_old(struct protosw_old
*opp
, struct domain_old
*odp
)
447 struct pr_usrreqs_old
*opru
;
448 struct pr_usrreqs
*pru
= NULL
;
449 struct protosw
*pp
= NULL
, *pp1
;
452 domain_guard_t guard
;
455 * This could be called as part of initializing the domain,
456 * and thus DOM_INITIALIZED may not be set (yet).
458 guard
= domain_guard_deploy();
460 /* Make sure the domain has been added via net_add_domain */
461 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
462 if (!(dp
->dom_flags
& DOM_OLD
)) {
465 if (dp
->dom_old
== odp
) {
474 TAILQ_FOREACH(pp1
, &dp
->dom_protosw
, pr_entry
) {
475 if (pp1
->pr_type
== opp
->pr_type
&&
476 pp1
->pr_protocol
== opp
->pr_protocol
) {
482 if ((opru
= opp
->pr_usrreqs
) == NULL
) {
483 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
484 __func__
, odp
->dom_family
, odp
->dom_name
, opp
->pr_protocol
);
488 pru
= _MALLOC(sizeof(*pru
), M_TEMP
, M_WAITOK
| M_ZERO
);
494 pru
->pru_flags
= PRUF_OLD
;
495 pru
->pru_abort
= opru
->pru_abort
;
496 pru
->pru_accept
= opru
->pru_accept
;
497 pru
->pru_attach
= opru
->pru_attach
;
498 pru
->pru_bind
= opru
->pru_bind
;
499 pru
->pru_connect
= opru
->pru_connect
;
500 pru
->pru_connect2
= opru
->pru_connect2
;
501 pru
->pru_control
= opru
->pru_control
;
502 pru
->pru_detach
= opru
->pru_detach
;
503 pru
->pru_disconnect
= opru
->pru_disconnect
;
504 pru
->pru_listen
= opru
->pru_listen
;
505 pru
->pru_peeraddr
= opru
->pru_peeraddr
;
506 pru
->pru_rcvd
= opru
->pru_rcvd
;
507 pru
->pru_rcvoob
= opru
->pru_rcvoob
;
508 pru
->pru_send
= opru
->pru_send
;
509 pru
->pru_sense
= opru
->pru_sense
;
510 pru
->pru_shutdown
= opru
->pru_shutdown
;
511 pru
->pru_sockaddr
= opru
->pru_sockaddr
;
512 pru
->pru_sosend
= opru
->pru_sosend
;
513 pru
->pru_soreceive
= opru
->pru_soreceive
;
514 pru
->pru_sopoll
= opru
->pru_sopoll
;
516 pp
= _MALLOC(sizeof(*pp
), M_TEMP
, M_WAITOK
| M_ZERO
);
523 * Protocol fast and slow timers are now deprecated.
525 if (opp
->pr_unused
!= NULL
) {
526 printf("%s: domain (%d,%s), proto %d: pr_fasttimo is "
527 "deprecated and won't be called\n", __func__
,
528 odp
->dom_family
, odp
->dom_name
, opp
->pr_protocol
);
530 if (opp
->pr_unused2
!= NULL
) {
531 printf("%s: domain (%d,%s), proto %d: pr_slowtimo is "
532 "deprecated and won't be called\n", __func__
,
533 odp
->dom_family
, odp
->dom_name
, opp
->pr_protocol
);
536 /* Copy everything but pr_init, pr_next, pr_domain, pr_protosw */
537 pp
->pr_type
= opp
->pr_type
;
538 pp
->pr_protocol
= opp
->pr_protocol
;
539 pp
->pr_flags
= (opp
->pr_flags
& PRF_USERFLAGS
) | PR_OLD
;
540 pp
->pr_input
= opp
->pr_input
;
541 pp
->pr_output
= opp
->pr_output
;
542 pp
->pr_ctlinput
= opp
->pr_ctlinput
;
543 pp
->pr_ctloutput
= opp
->pr_ctloutput
;
544 pp
->pr_usrreqs
= pru
;
545 pp
->pr_init
= pr_init_old
;
546 pp
->pr_drain
= opp
->pr_drain
;
547 pp
->pr_sysctl
= opp
->pr_sysctl
;
548 pp
->pr_lock
= opp
->pr_lock
;
549 pp
->pr_unlock
= opp
->pr_unlock
;
550 pp
->pr_getlock
= opp
->pr_getlock
;
553 /* attach as well as initialize */
554 attach_proto(pp
, dp
);
555 net_init_proto(pp
, dp
);
558 printf("%s: domain (%d,%s), proto %d: failed to attach, "
559 "error %d\n", __func__
, odp
->dom_family
,
560 odp
->dom_name
, opp
->pr_protocol
, error
);
570 domain_guard_release(guard
);
575 * Internal routine, not exported.
577 * net_del_proto - remove a protosw from a domain's protosw chain.
578 * Search the protosw chain for the element with matching data.
579 * Then unlink and return.
581 * NOTE: Caller must have acquired domain_proto_mtx
584 net_del_proto(int type
, int protocol
, struct domain
*dp
)
589 * This could be called as part of initializing the domain,
590 * and thus DOM_INITIALIZED may not be set (yet).
592 domain_proto_mtx_lock_assert_held();
594 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
595 if (pp
->pr_type
== type
&& pp
->pr_protocol
== protocol
) {
603 detach_proto(pp
, dp
);
604 if (pp
->pr_usrreqs
->pru_flags
& PRUF_OLD
) {
605 FREE(pp
->pr_usrreqs
, M_TEMP
);
607 if (pp
->pr_flags
& PR_OLD
) {
615 * Exported (private) routine, indirection of net_del_proto.
618 net_del_proto_old(int type
, int protocol
, struct domain_old
*odp
)
623 domain_guard_t guard
;
626 * This could be called as part of initializing the domain,
627 * and thus DOM_INITIALIZED may not be set (yet).
629 guard
= domain_guard_deploy();
631 /* Make sure the domain has been added via net_add_domain */
632 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
633 if (!(dp
->dom_flags
& DOM_OLD
)) {
636 if (dp
->dom_old
== odp
) {
645 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
646 if (pp
->pr_type
== type
&& pp
->pr_protocol
== protocol
) {
654 detach_proto(pp
, dp
);
655 if (pp
->pr_usrreqs
->pru_flags
& PRUF_OLD
) {
656 FREE(pp
->pr_usrreqs
, M_TEMP
);
658 if (pp
->pr_flags
& PR_OLD
) {
663 domain_guard_release(guard
);
668 domain_sched_timeout(void)
670 LCK_MTX_ASSERT(&domain_timeout_mtx
, LCK_MTX_ASSERT_OWNED
);
672 if (!domain_timeout_run
&& domain_draining
) {
673 domain_timeout_run
= TRUE
;
674 timeout(domain_timeout
, NULL
, hz
);
679 net_drain_domains(void)
681 lck_mtx_lock(&domain_timeout_mtx
);
682 domain_draining
= TRUE
;
683 domain_sched_timeout();
684 lck_mtx_unlock(&domain_timeout_mtx
);
687 extern struct domain inet6domain_s
;
689 extern struct domain keydomain_s
;
692 extern struct domain routedomain_s
, ndrvdomain_s
, inetdomain_s
;
693 extern struct domain systemdomain_s
, localdomain_s
;
694 extern struct domain vsockdomain_s
;
697 extern struct domain mpdomain_s
;
698 #endif /* MULTIPATH */
701 domain_timeout(void *arg
)
706 domain_guard_t guard
;
708 lck_mtx_lock(&domain_timeout_mtx
);
709 if (domain_draining
) {
710 domain_draining
= FALSE
;
711 lck_mtx_unlock(&domain_timeout_mtx
);
713 guard
= domain_guard_deploy();
714 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
715 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
716 if (pp
->pr_drain
!= NULL
) {
721 domain_guard_release(guard
);
723 lck_mtx_lock(&domain_timeout_mtx
);
726 /* re-arm the timer if there's work to do */
727 domain_timeout_run
= FALSE
;
728 domain_sched_timeout();
729 lck_mtx_unlock(&domain_timeout_mtx
);
736 domain_guard_t guard
;
738 eventhandler_lists_ctxt_init(&protoctl_evhdlr_ctxt
);
740 * allocate lock group attribute and group for domain mutexes
742 domain_proto_mtx_grp_attr
= lck_grp_attr_alloc_init();
744 domain_proto_mtx_grp
= lck_grp_alloc_init("domain",
745 domain_proto_mtx_grp_attr
);
748 * allocate the lock attribute for per domain mutexes
750 domain_proto_mtx_attr
= lck_attr_alloc_init();
752 lck_mtx_init(&domain_proto_mtx
, domain_proto_mtx_grp
,
753 domain_proto_mtx_attr
);
754 lck_mtx_init(&domain_timeout_mtx
, domain_proto_mtx_grp
,
755 domain_proto_mtx_attr
);
757 guard
= domain_guard_deploy();
759 * Add all the static domains to the domains list. route domain
760 * gets added and initialized last, since we need it to attach
761 * rt_tables[] to everything that's already there. This also
762 * means that domains added after this point won't get their
763 * dom_rtattach() called on rt_tables[].
765 attach_domain(&inetdomain_s
);
766 attach_domain(&inet6domain_s
);
768 attach_domain(&mpdomain_s
);
769 #endif /* MULTIPATH */
770 attach_domain(&systemdomain_s
);
771 attach_domain(&localdomain_s
);
773 attach_domain(&keydomain_s
);
775 attach_domain(&ndrvdomain_s
);
776 attach_domain(&vsockdomain_s
);
777 attach_domain(&routedomain_s
); /* must be last domain */
780 * Now ask them all to init (XXX including the routing domain,
783 TAILQ_FOREACH(dp
, &domains
, dom_entry
)
786 domain_guard_release(guard
);
789 static __inline__
struct domain
*
790 pffinddomain_locked(int pf
)
794 domain_proto_mtx_lock_assert_held();
796 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
797 if (dp
->dom_family
== pf
) {
805 pffindtype(int family
, int type
)
807 struct protosw
*pp
= NULL
;
809 domain_guard_t guard
;
811 guard
= domain_guard_deploy();
812 if ((dp
= pffinddomain_locked(family
)) == NULL
) {
816 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
817 if (pp
->pr_type
!= 0 && pp
->pr_type
== type
) {
822 domain_guard_release(guard
);
827 * Internal routine, not exported.
833 domain_guard_t guard
;
835 guard
= domain_guard_deploy();
836 dp
= pffinddomain_locked(pf
);
837 domain_guard_release(guard
);
842 * Exported (private) routine, indirection of pffinddomain.
845 pffinddomain_old(int pf
)
847 struct domain_old
*odp
= NULL
;
849 domain_guard_t guard
;
851 guard
= domain_guard_deploy();
852 if ((dp
= pffinddomain_locked(pf
)) != NULL
&& (dp
->dom_flags
& DOM_OLD
)) {
855 domain_guard_release(guard
);
860 * Internal routine, not exported.
863 pffindproto(int family
, int protocol
, int type
)
866 domain_guard_t guard
;
868 guard
= domain_guard_deploy();
869 pp
= pffindproto_locked(family
, protocol
, type
);
870 domain_guard_release(guard
);
875 pffindproto_locked(int family
, int protocol
, int type
)
877 struct protosw
*maybe
= NULL
;
881 domain_proto_mtx_lock_assert_held();
887 dp
= pffinddomain_locked(family
);
892 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
893 if ((pp
->pr_protocol
== protocol
) && (pp
->pr_type
== type
)) {
897 if (type
== SOCK_RAW
&& pp
->pr_type
== SOCK_RAW
&&
898 pp
->pr_protocol
== 0 && maybe
== NULL
) {
906 * Exported (private) routine, indirection of pffindproto.
909 pffindproto_old(int family
, int protocol
, int type
)
911 struct protosw_old
*opr
= NULL
;
913 domain_guard_t guard
;
915 guard
= domain_guard_deploy();
916 if ((pp
= pffindproto_locked(family
, protocol
, type
)) != NULL
&&
917 (pp
->pr_flags
& PR_OLD
)) {
920 domain_guard_release(guard
);
924 static struct protosw
*
925 pffindprotonotype_locked(int family
, int protocol
, int type
)
931 domain_proto_mtx_lock_assert_held();
937 dp
= pffinddomain_locked(family
);
942 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
943 if (pp
->pr_protocol
== protocol
) {
951 pffindprotonotype(int family
, int protocol
)
954 domain_guard_t guard
;
960 guard
= domain_guard_deploy();
961 pp
= pffindprotonotype_locked(family
, protocol
, 0);
962 domain_guard_release(guard
);
967 pfctlinput(int cmd
, struct sockaddr
*sa
)
969 pfctlinput2(cmd
, sa
, NULL
);
973 pfctlinput2(int cmd
, struct sockaddr
*sa
, void *ctlparam
)
977 domain_guard_t guard
;
983 guard
= domain_guard_deploy();
984 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
985 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
986 if (pp
->pr_ctlinput
!= NULL
) {
987 (*pp
->pr_ctlinput
)(cmd
, sa
, ctlparam
, NULL
);
991 domain_guard_release(guard
);
995 net_update_uptime_with_time(const struct timeval
*tvp
)
997 _net_uptime
= tvp
->tv_sec
;
999 * Round up the timer to the nearest integer value because otherwise
1000 * we might setup networking timers that are off by almost 1 second.
1002 if (tvp
->tv_usec
> 500000) {
1006 /* update milliseconds variant */
1007 _net_uptime_ms
= (((u_int64_t
)tvp
->tv_sec
* 1000) +
1008 ((u_int64_t
)tvp
->tv_usec
/ 1000));
1012 net_update_uptime(void)
1018 net_update_uptime_with_time(&tv
);
1022 * Convert our uin64_t net_uptime to a struct timeval.
1025 net_uptime2timeval(struct timeval
*tv
)
1032 tv
->tv_sec
= (time_t)net_uptime();
1036 * An alternative way to obtain the coarse-grained uptime (in seconds)
1037 * for networking code which do not require high-precision timestamp,
1038 * as this is significantly cheaper than microuptime().
1043 if (_net_uptime
== 0) {
1044 net_update_uptime();
1053 if (_net_uptime_ms
== 0) {
1054 net_update_uptime();
1057 return _net_uptime_ms
;
1061 domain_proto_mtx_lock_assert_held(void)
1063 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1067 domain_proto_mtx_lock_assert_notheld(void)
1069 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1073 domain_guard_deploy(void)
1075 net_thread_marks_t marks
;
1077 marks
= net_thread_marks_push(NET_THREAD_HELD_DOMAIN
);
1078 if (marks
!= net_thread_marks_none
) {
1079 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1080 lck_mtx_lock(&domain_proto_mtx
);
1082 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1085 return (domain_guard_t
)(const void*)marks
;
1089 domain_guard_release(domain_guard_t guard
)
1091 net_thread_marks_t marks
= (net_thread_marks_t
)(const void*)guard
;
1093 if (marks
!= net_thread_marks_none
) {
1094 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1095 lck_mtx_unlock(&domain_proto_mtx
);
1096 net_thread_marks_pop(marks
);
1098 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1103 domain_unguard_deploy(void)
1105 net_thread_marks_t marks
;
1107 marks
= net_thread_unmarks_push(NET_THREAD_HELD_DOMAIN
);
1108 if (marks
!= net_thread_marks_none
) {
1109 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1110 lck_mtx_unlock(&domain_proto_mtx
);
1112 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1115 return (domain_unguard_t
)(const void*)marks
;
1119 domain_unguard_release(domain_unguard_t unguard
)
1121 net_thread_marks_t marks
= (net_thread_marks_t
)(const void*)unguard
;
1123 if (marks
!= net_thread_marks_none
) {
1124 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1125 lck_mtx_lock(&domain_proto_mtx
);
1126 net_thread_unmarks_pop(marks
);
1128 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1133 #if (DEVELOPMENT || DEBUG)
1136 sysctl_do_drain_domains SYSCTL_HANDLER_ARGS
1138 #pragma unused(arg1, arg2)
1142 error
= sysctl_handle_int(oidp
, &dummy
, 0, req
);
1143 if (error
|| req
->newptr
== USER_ADDR_NULL
) {
1147 net_drain_domains();
1152 #endif /* DEVELOPMENT || DEBUG */