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 static LCK_GRP_DECLARE(domain_proto_mtx_grp
, "domain");
104 static LCK_ATTR_DECLARE(domain_proto_mtx_attr
, 0, 0);
105 static LCK_MTX_DECLARE_ATTR(domain_proto_mtx
,
106 &domain_proto_mtx_grp
, &domain_proto_mtx_attr
);
107 static LCK_MTX_DECLARE_ATTR(domain_timeout_mtx
,
108 &domain_proto_mtx_grp
, &domain_proto_mtx_attr
);
110 u_int64_t _net_uptime
;
111 u_int64_t _net_uptime_ms
;
113 #if (DEVELOPMENT || DEBUG)
115 SYSCTL_DECL(_kern_ipc
);
117 static int sysctl_do_drain_domains SYSCTL_HANDLER_ARGS
;
119 SYSCTL_PROC(_kern_ipc
, OID_AUTO
, do_drain_domains
,
120 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
,
122 sysctl_do_drain_domains
, "I", "force manual drain domains");
124 #endif /* DEVELOPMENT || DEBUG */
127 pr_init_old(struct protosw
*pp
, struct domain
*dp
)
130 VERIFY(pp
->pr_flags
& PR_OLD
);
131 VERIFY(pp
->pr_old
!= NULL
);
133 if (pp
->pr_old
->pr_init
!= NULL
) {
134 pp
->pr_old
->pr_init();
139 init_proto(struct protosw
*pp
, struct domain
*dp
)
141 VERIFY(pp
->pr_flags
& PR_ATTACHED
);
143 if (!(pp
->pr_flags
& PR_INITIALIZED
)) {
144 TAILQ_INIT(&pp
->pr_filter_head
);
145 if (pp
->pr_init
!= NULL
) {
148 pp
->pr_flags
|= PR_INITIALIZED
;
153 attach_proto(struct protosw
*pp
, struct domain
*dp
)
155 domain_proto_mtx_lock_assert_held();
156 VERIFY(!(pp
->pr_flags
& PR_ATTACHED
));
157 VERIFY(pp
->pr_domain
== NULL
);
158 VERIFY(pp
->pr_protosw
== NULL
);
160 TAILQ_INSERT_TAIL(&dp
->dom_protosw
, pp
, pr_entry
);
161 pp
->pr_flags
|= PR_ATTACHED
;
165 /* do some cleaning up on user request callbacks */
166 pru_sanitize(pp
->pr_usrreqs
);
170 detach_proto(struct protosw
*pp
, struct domain
*dp
)
172 domain_proto_mtx_lock_assert_held();
173 VERIFY(pp
->pr_flags
& PR_ATTACHED
);
174 VERIFY(pp
->pr_domain
== dp
);
175 VERIFY(pp
->pr_protosw
== pp
);
177 TAILQ_REMOVE(&dp
->dom_protosw
, pp
, pr_entry
);
178 pp
->pr_flags
&= ~PR_ATTACHED
;
179 pp
->pr_domain
= NULL
;
180 pp
->pr_protosw
= NULL
;
184 dom_init_old(struct domain
*dp
)
186 VERIFY(dp
->dom_flags
& DOM_OLD
);
187 VERIFY(dp
->dom_old
!= NULL
);
189 if (dp
->dom_old
->dom_init
!= NULL
) {
190 dp
->dom_old
->dom_init();
195 init_domain(struct domain
*dp
)
197 VERIFY(dp
->dom_flags
& DOM_ATTACHED
);
199 if (!(dp
->dom_flags
& DOM_INITIALIZED
)) {
200 lck_mtx_init(&dp
->dom_mtx_s
, &domain_proto_mtx_grp
,
201 &domain_proto_mtx_attr
);
202 dp
->dom_mtx
= &dp
->dom_mtx_s
;
203 TAILQ_INIT(&dp
->dom_protosw
);
204 if (dp
->dom_init
!= NULL
) {
207 dp
->dom_flags
|= DOM_INITIALIZED
;
210 /* Recompute for new protocol */
211 if (_max_linkhdr
< 16) { /* XXX - Sheesh; everything's ether? */
214 _max_linkhdr
= max_linkhdr
; /* round it up */
216 if (dp
->dom_protohdrlen
> _max_protohdr
) {
217 _max_protohdr
= dp
->dom_protohdrlen
;
219 _max_protohdr
= max_protohdr
; /* round it up */
221 max_hdr
= max_linkhdr
+ max_protohdr
;
222 max_datalen
= MHLEN
- max_hdr
;
226 attach_domain(struct domain
*dp
)
228 domain_proto_mtx_lock_assert_held();
229 VERIFY(!(dp
->dom_flags
& DOM_ATTACHED
));
231 TAILQ_INSERT_TAIL(&domains
, dp
, dom_entry
);
232 dp
->dom_flags
|= DOM_ATTACHED
;
236 detach_domain(struct domain
*dp
)
238 domain_proto_mtx_lock_assert_held();
239 VERIFY(dp
->dom_flags
& DOM_ATTACHED
);
241 TAILQ_REMOVE(&domains
, dp
, dom_entry
);
242 dp
->dom_flags
&= ~DOM_ATTACHED
;
244 if (dp
->dom_flags
& DOM_OLD
) {
245 struct domain_old
*odp
= dp
->dom_old
;
248 odp
->dom_next
= NULL
;
254 * Exported (private) routine, indirection of net_add_domain.
257 net_add_domain_old(struct domain_old
*odp
)
260 domain_guard_t guard
;
264 guard
= domain_guard_deploy();
265 if ((dp
= pffinddomain_locked(odp
->dom_family
)) != NULL
) {
267 * There is really nothing better than to panic here,
268 * as the caller would not have been able to handle
269 * any failures otherwise.
271 panic("%s: domain (%d,%s) already exists for %s\n", __func__
,
272 dp
->dom_family
, dp
->dom_name
, odp
->dom_name
);
276 /* Make sure nothing is currently pointing to the odp. */
277 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
278 if (dp
->dom_old
== odp
) {
279 panic("%s: domain %p (%d,%s) is already "
280 "associated with %p (%d,%s)\n", __func__
,
281 odp
, odp
->dom_family
, odp
->dom_name
, dp
,
282 dp
->dom_family
, dp
->dom_name
);
287 if (odp
->dom_protosw
!= NULL
) {
288 panic("%s: domain (%d,%s) protocols need to added "
289 "via net_add_proto\n", __func__
, odp
->dom_family
,
294 dp
= kheap_alloc(KHEAP_DEFAULT
, sizeof(struct domain
), Z_WAITOK
| Z_ZERO
);
297 * There is really nothing better than to panic here,
298 * as the caller would not have been able to handle
299 * any failures otherwise.
301 panic("%s: unable to allocate memory for domain family "
302 "%d (%s)\n", __func__
, odp
->dom_family
, odp
->dom_name
);
306 /* Copy everything but dom_init, dom_mtx, dom_next and dom_refs */
307 dp
->dom_family
= odp
->dom_family
;
308 dp
->dom_flags
= (odp
->dom_flags
& DOMF_USERFLAGS
) | DOM_OLD
;
309 dp
->dom_name
= odp
->dom_name
;
310 dp
->dom_init
= dom_init_old
;
311 dp
->dom_externalize
= odp
->dom_externalize
;
312 dp
->dom_dispose
= odp
->dom_dispose
;
313 dp
->dom_rtattach
= odp
->dom_rtattach
;
314 dp
->dom_rtoffset
= odp
->dom_rtoffset
;
315 dp
->dom_maxrtkey
= odp
->dom_maxrtkey
;
316 dp
->dom_protohdrlen
= odp
->dom_protohdrlen
;
322 /* Point the mutex back to the internal structure's */
323 odp
->dom_mtx
= dp
->dom_mtx
;
324 domain_guard_release(guard
);
328 * Exported (private) routine, indirection of net_del_domain.
331 net_del_domain_old(struct domain_old
*odp
)
333 struct domain
*dp1
, *dp2
;
335 domain_guard_t guard
;
339 guard
= domain_guard_deploy();
340 if (odp
->dom_refs
!= 0) {
345 TAILQ_FOREACH_SAFE(dp1
, &domains
, dom_entry
, dp2
) {
346 if (!(dp1
->dom_flags
& DOM_OLD
)) {
349 VERIFY(dp1
->dom_old
!= NULL
);
350 if (odp
== dp1
->dom_old
) {
355 struct protosw
*pp1
, *pp2
;
357 VERIFY(dp1
->dom_flags
& DOM_OLD
);
358 VERIFY(dp1
->dom_old
== odp
);
360 /* Remove all protocols attached to this domain */
361 TAILQ_FOREACH_SAFE(pp1
, &dp1
->dom_protosw
, pr_entry
, pp2
) {
362 detach_proto(pp1
, dp1
);
363 if (pp1
->pr_usrreqs
->pru_flags
& PRUF_OLD
) {
364 kheap_free(KHEAP_DEFAULT
, pp1
->pr_usrreqs
, sizeof(struct pr_usrreqs
));
366 if (pp1
->pr_flags
& PR_OLD
) {
367 kheap_free(KHEAP_DEFAULT
, pp1
, sizeof(struct protosw
));
372 kheap_free(KHEAP_DEFAULT
, dp1
, sizeof(struct domain
));
374 error
= EPFNOSUPPORT
;
377 domain_guard_release(guard
);
382 * Internal routine, not exported.
384 * net_add_proto - link a protosw into a domain's protosw chain
386 * NOTE: Caller must have acquired domain_proto_mtx
389 net_add_proto(struct protosw
*pp
, struct domain
*dp
, int doinit
)
394 * This could be called as part of initializing the domain,
395 * and thus DOM_INITIALIZED may not be set (yet).
397 domain_proto_mtx_lock_assert_held();
398 VERIFY(!(pp
->pr_flags
& PR_ATTACHED
));
400 /* pr_domain is set only after the protocol is attached */
401 if (pp
->pr_domain
!= NULL
) {
402 panic("%s: domain (%d,%s), proto %d has non-NULL pr_domain!\n",
403 __func__
, dp
->dom_family
, dp
->dom_name
, pp
->pr_protocol
);
407 if (pp
->pr_usrreqs
== NULL
) {
408 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
409 __func__
, dp
->dom_family
, dp
->dom_name
, pp
->pr_protocol
);
413 TAILQ_FOREACH(pp1
, &dp
->dom_protosw
, pr_entry
) {
414 if (pp1
->pr_type
== pp
->pr_type
&&
415 pp1
->pr_protocol
== pp
->pr_protocol
) {
420 attach_proto(pp
, dp
);
422 net_init_proto(pp
, dp
);
429 net_init_proto(struct protosw
*pp
, struct domain
*dp
)
432 * This could be called as part of initializing the domain,
433 * and thus DOM_INITIALIZED may not be set (yet). The protocol
434 * must have been attached via net_addr_protosw() by now.
436 domain_proto_mtx_lock_assert_held();
437 VERIFY(pp
->pr_flags
& PR_ATTACHED
);
443 * Exported (private) routine, indirection of net_add_proto.
446 net_add_proto_old(struct protosw_old
*opp
, struct domain_old
*odp
)
448 struct pr_usrreqs_old
*opru
;
449 struct pr_usrreqs
*pru
= NULL
;
450 struct protosw
*pp
= NULL
, *pp1
;
453 domain_guard_t guard
;
456 * This could be called as part of initializing the domain,
457 * and thus DOM_INITIALIZED may not be set (yet).
459 guard
= domain_guard_deploy();
461 /* Make sure the domain has been added via net_add_domain */
462 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
463 if (!(dp
->dom_flags
& DOM_OLD
)) {
466 if (dp
->dom_old
== odp
) {
475 TAILQ_FOREACH(pp1
, &dp
->dom_protosw
, pr_entry
) {
476 if (pp1
->pr_type
== opp
->pr_type
&&
477 pp1
->pr_protocol
== opp
->pr_protocol
) {
483 if ((opru
= opp
->pr_usrreqs
) == NULL
) {
484 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
485 __func__
, odp
->dom_family
, odp
->dom_name
, opp
->pr_protocol
);
489 pru
= kheap_alloc(KHEAP_DEFAULT
, sizeof(struct pr_usrreqs
),
496 pru
->pru_flags
= PRUF_OLD
;
497 pru
->pru_abort
= opru
->pru_abort
;
498 pru
->pru_accept
= opru
->pru_accept
;
499 pru
->pru_attach
= opru
->pru_attach
;
500 pru
->pru_bind
= opru
->pru_bind
;
501 pru
->pru_connect
= opru
->pru_connect
;
502 pru
->pru_connect2
= opru
->pru_connect2
;
503 pru
->pru_control
= opru
->pru_control
;
504 pru
->pru_detach
= opru
->pru_detach
;
505 pru
->pru_disconnect
= opru
->pru_disconnect
;
506 pru
->pru_listen
= opru
->pru_listen
;
507 pru
->pru_peeraddr
= opru
->pru_peeraddr
;
508 pru
->pru_rcvd
= opru
->pru_rcvd
;
509 pru
->pru_rcvoob
= opru
->pru_rcvoob
;
510 pru
->pru_send
= opru
->pru_send
;
511 pru
->pru_sense
= opru
->pru_sense
;
512 pru
->pru_shutdown
= opru
->pru_shutdown
;
513 pru
->pru_sockaddr
= opru
->pru_sockaddr
;
514 pru
->pru_sosend
= opru
->pru_sosend
;
515 pru
->pru_soreceive
= opru
->pru_soreceive
;
516 pru
->pru_sopoll
= opru
->pru_sopoll
;
518 pp
= kheap_alloc(KHEAP_DEFAULT
, sizeof(struct protosw
), Z_WAITOK
| Z_ZERO
);
525 * Protocol fast and slow timers are now deprecated.
527 if (opp
->pr_unused
!= NULL
) {
528 printf("%s: domain (%d,%s), proto %d: pr_fasttimo is "
529 "deprecated and won't be called\n", __func__
,
530 odp
->dom_family
, odp
->dom_name
, opp
->pr_protocol
);
532 if (opp
->pr_unused2
!= NULL
) {
533 printf("%s: domain (%d,%s), proto %d: pr_slowtimo is "
534 "deprecated and won't be called\n", __func__
,
535 odp
->dom_family
, odp
->dom_name
, opp
->pr_protocol
);
538 /* Copy everything but pr_init, pr_next, pr_domain, pr_protosw */
539 pp
->pr_type
= opp
->pr_type
;
540 pp
->pr_protocol
= opp
->pr_protocol
;
541 pp
->pr_flags
= (opp
->pr_flags
& PRF_USERFLAGS
) | PR_OLD
;
542 pp
->pr_input
= opp
->pr_input
;
543 pp
->pr_output
= opp
->pr_output
;
544 pp
->pr_ctlinput
= opp
->pr_ctlinput
;
545 pp
->pr_ctloutput
= opp
->pr_ctloutput
;
546 pp
->pr_usrreqs
= pru
;
547 pp
->pr_init
= pr_init_old
;
548 pp
->pr_drain
= opp
->pr_drain
;
549 pp
->pr_sysctl
= opp
->pr_sysctl
;
550 pp
->pr_lock
= opp
->pr_lock
;
551 pp
->pr_unlock
= opp
->pr_unlock
;
552 pp
->pr_getlock
= opp
->pr_getlock
;
555 /* attach as well as initialize */
556 attach_proto(pp
, dp
);
557 net_init_proto(pp
, dp
);
560 printf("%s: domain (%d,%s), proto %d: failed to attach, "
561 "error %d\n", __func__
, odp
->dom_family
,
562 odp
->dom_name
, opp
->pr_protocol
, error
);
564 kheap_free(KHEAP_DEFAULT
, pru
, sizeof(struct pr_usrreqs
));
565 kheap_free(KHEAP_DEFAULT
, pp
, sizeof(struct protosw
));
568 domain_guard_release(guard
);
573 * Internal routine, not exported.
575 * net_del_proto - remove a protosw from a domain's protosw chain.
576 * Search the protosw chain for the element with matching data.
577 * Then unlink and return.
579 * NOTE: Caller must have acquired domain_proto_mtx
582 net_del_proto(int type
, int protocol
, struct domain
*dp
)
587 * This could be called as part of initializing the domain,
588 * and thus DOM_INITIALIZED may not be set (yet).
590 domain_proto_mtx_lock_assert_held();
592 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
593 if (pp
->pr_type
== type
&& pp
->pr_protocol
== protocol
) {
601 detach_proto(pp
, dp
);
602 if (pp
->pr_usrreqs
->pru_flags
& PRUF_OLD
) {
603 kheap_free(KHEAP_DEFAULT
, pp
->pr_usrreqs
, sizeof(struct pr_usrreqs
));
605 if (pp
->pr_flags
& PR_OLD
) {
606 kheap_free(KHEAP_DEFAULT
, pp
, sizeof(struct protosw
));
613 * Exported (private) routine, indirection of net_del_proto.
616 net_del_proto_old(int type
, int protocol
, struct domain_old
*odp
)
621 domain_guard_t guard
;
624 * This could be called as part of initializing the domain,
625 * and thus DOM_INITIALIZED may not be set (yet).
627 guard
= domain_guard_deploy();
629 /* Make sure the domain has been added via net_add_domain */
630 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
631 if (!(dp
->dom_flags
& DOM_OLD
)) {
634 if (dp
->dom_old
== odp
) {
643 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
644 if (pp
->pr_type
== type
&& pp
->pr_protocol
== protocol
) {
652 detach_proto(pp
, dp
);
653 if (pp
->pr_usrreqs
->pru_flags
& PRUF_OLD
) {
654 kheap_free(KHEAP_DEFAULT
, pp
->pr_usrreqs
, sizeof(struct pr_usrreqs
));
656 if (pp
->pr_flags
& PR_OLD
) {
657 kheap_free(KHEAP_DEFAULT
, pp
, sizeof(struct protosw
));
661 domain_guard_release(guard
);
666 domain_sched_timeout(void)
668 LCK_MTX_ASSERT(&domain_timeout_mtx
, LCK_MTX_ASSERT_OWNED
);
670 if (!domain_timeout_run
&& domain_draining
) {
671 domain_timeout_run
= TRUE
;
672 timeout(domain_timeout
, NULL
, hz
);
677 net_drain_domains(void)
679 lck_mtx_lock(&domain_timeout_mtx
);
680 domain_draining
= TRUE
;
681 domain_sched_timeout();
682 lck_mtx_unlock(&domain_timeout_mtx
);
685 extern struct domain inet6domain_s
;
687 extern struct domain keydomain_s
;
690 extern struct domain routedomain_s
, ndrvdomain_s
, inetdomain_s
;
691 extern struct domain systemdomain_s
, localdomain_s
;
692 extern struct domain vsockdomain_s
;
695 extern struct domain mpdomain_s
;
696 #endif /* MULTIPATH */
699 domain_timeout(void *arg
)
704 domain_guard_t guard
;
706 lck_mtx_lock(&domain_timeout_mtx
);
707 if (domain_draining
) {
708 domain_draining
= FALSE
;
709 lck_mtx_unlock(&domain_timeout_mtx
);
711 guard
= domain_guard_deploy();
712 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
713 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
714 if (pp
->pr_drain
!= NULL
) {
719 domain_guard_release(guard
);
721 lck_mtx_lock(&domain_timeout_mtx
);
724 /* re-arm the timer if there's work to do */
725 domain_timeout_run
= FALSE
;
726 domain_sched_timeout();
727 lck_mtx_unlock(&domain_timeout_mtx
);
734 domain_guard_t guard
;
736 eventhandler_lists_ctxt_init(&protoctl_evhdlr_ctxt
);
738 guard
= domain_guard_deploy();
740 * Add all the static domains to the domains list. route domain
741 * gets added and initialized last, since we need it to attach
742 * rt_tables[] to everything that's already there. This also
743 * means that domains added after this point won't get their
744 * dom_rtattach() called on rt_tables[].
746 attach_domain(&inetdomain_s
);
747 attach_domain(&inet6domain_s
);
749 attach_domain(&mpdomain_s
);
750 #endif /* MULTIPATH */
751 attach_domain(&systemdomain_s
);
752 attach_domain(&localdomain_s
);
754 attach_domain(&keydomain_s
);
756 attach_domain(&ndrvdomain_s
);
757 attach_domain(&vsockdomain_s
);
758 attach_domain(&routedomain_s
); /* must be last domain */
761 * Now ask them all to init (XXX including the routing domain,
764 TAILQ_FOREACH(dp
, &domains
, dom_entry
)
767 domain_guard_release(guard
);
770 static __inline__
struct domain
*
771 pffinddomain_locked(int pf
)
775 domain_proto_mtx_lock_assert_held();
777 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
778 if (dp
->dom_family
== pf
) {
786 pffindtype(int family
, int type
)
788 struct protosw
*pp
= NULL
;
790 domain_guard_t guard
;
792 guard
= domain_guard_deploy();
793 if ((dp
= pffinddomain_locked(family
)) == NULL
) {
797 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
798 if (pp
->pr_type
!= 0 && pp
->pr_type
== type
) {
803 domain_guard_release(guard
);
808 * Internal routine, not exported.
814 domain_guard_t guard
;
816 guard
= domain_guard_deploy();
817 dp
= pffinddomain_locked(pf
);
818 domain_guard_release(guard
);
823 * Exported (private) routine, indirection of pffinddomain.
826 pffinddomain_old(int pf
)
828 struct domain_old
*odp
= NULL
;
830 domain_guard_t guard
;
832 guard
= domain_guard_deploy();
833 if ((dp
= pffinddomain_locked(pf
)) != NULL
&& (dp
->dom_flags
& DOM_OLD
)) {
836 domain_guard_release(guard
);
841 * Internal routine, not exported.
844 pffindproto(int family
, int protocol
, int type
)
847 domain_guard_t guard
;
849 guard
= domain_guard_deploy();
850 pp
= pffindproto_locked(family
, protocol
, type
);
851 domain_guard_release(guard
);
856 pffindproto_locked(int family
, int protocol
, int type
)
858 struct protosw
*maybe
= NULL
;
862 domain_proto_mtx_lock_assert_held();
868 dp
= pffinddomain_locked(family
);
873 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
874 if ((pp
->pr_protocol
== protocol
) && (pp
->pr_type
== type
)) {
878 if (type
== SOCK_RAW
&& pp
->pr_type
== SOCK_RAW
&&
879 pp
->pr_protocol
== 0 && maybe
== NULL
) {
887 * Exported (private) routine, indirection of pffindproto.
890 pffindproto_old(int family
, int protocol
, int type
)
892 struct protosw_old
*opr
= NULL
;
894 domain_guard_t guard
;
896 guard
= domain_guard_deploy();
897 if ((pp
= pffindproto_locked(family
, protocol
, type
)) != NULL
&&
898 (pp
->pr_flags
& PR_OLD
)) {
901 domain_guard_release(guard
);
905 static struct protosw
*
906 pffindprotonotype_locked(int family
, int protocol
, int type
)
912 domain_proto_mtx_lock_assert_held();
918 dp
= pffinddomain_locked(family
);
923 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
924 if (pp
->pr_protocol
== protocol
) {
932 pffindprotonotype(int family
, int protocol
)
935 domain_guard_t guard
;
941 guard
= domain_guard_deploy();
942 pp
= pffindprotonotype_locked(family
, protocol
, 0);
943 domain_guard_release(guard
);
948 pfctlinput(int cmd
, struct sockaddr
*sa
)
950 pfctlinput2(cmd
, sa
, NULL
);
954 pfctlinput2(int cmd
, struct sockaddr
*sa
, void *ctlparam
)
958 domain_guard_t guard
;
964 guard
= domain_guard_deploy();
965 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
966 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
967 if (pp
->pr_ctlinput
!= NULL
) {
968 (*pp
->pr_ctlinput
)(cmd
, sa
, ctlparam
, NULL
);
972 domain_guard_release(guard
);
976 net_update_uptime_with_time(const struct timeval
*tvp
)
978 _net_uptime
= tvp
->tv_sec
;
980 * Round up the timer to the nearest integer value because otherwise
981 * we might setup networking timers that are off by almost 1 second.
983 if (tvp
->tv_usec
> 500000) {
987 /* update milliseconds variant */
988 _net_uptime_ms
= (((u_int64_t
)tvp
->tv_sec
* 1000) +
989 ((u_int64_t
)tvp
->tv_usec
/ 1000));
993 net_update_uptime(void)
999 net_update_uptime_with_time(&tv
);
1003 * Convert our uin64_t net_uptime to a struct timeval.
1006 net_uptime2timeval(struct timeval
*tv
)
1013 tv
->tv_sec
= (time_t)net_uptime();
1017 * An alternative way to obtain the coarse-grained uptime (in seconds)
1018 * for networking code which do not require high-precision timestamp,
1019 * as this is significantly cheaper than microuptime().
1024 if (_net_uptime
== 0) {
1025 net_update_uptime();
1034 if (_net_uptime_ms
== 0) {
1035 net_update_uptime();
1038 return _net_uptime_ms
;
1042 domain_proto_mtx_lock_assert_held(void)
1044 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1048 domain_proto_mtx_lock_assert_notheld(void)
1050 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1054 domain_guard_deploy(void)
1056 net_thread_marks_t marks
;
1058 marks
= net_thread_marks_push(NET_THREAD_HELD_DOMAIN
);
1059 if (marks
!= net_thread_marks_none
) {
1060 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1061 lck_mtx_lock(&domain_proto_mtx
);
1063 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1066 return (domain_guard_t
)(const void*)marks
;
1070 domain_guard_release(domain_guard_t guard
)
1072 net_thread_marks_t marks
= (net_thread_marks_t
)(const void*)guard
;
1074 if (marks
!= net_thread_marks_none
) {
1075 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1076 lck_mtx_unlock(&domain_proto_mtx
);
1077 net_thread_marks_pop(marks
);
1079 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1084 domain_unguard_deploy(void)
1086 net_thread_marks_t marks
;
1088 marks
= net_thread_unmarks_push(NET_THREAD_HELD_DOMAIN
);
1089 if (marks
!= net_thread_marks_none
) {
1090 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1091 lck_mtx_unlock(&domain_proto_mtx
);
1093 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1096 return (domain_unguard_t
)(const void*)marks
;
1100 domain_unguard_release(domain_unguard_t unguard
)
1102 net_thread_marks_t marks
= (net_thread_marks_t
)(const void*)unguard
;
1104 if (marks
!= net_thread_marks_none
) {
1105 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1106 lck_mtx_lock(&domain_proto_mtx
);
1107 net_thread_unmarks_pop(marks
);
1109 LCK_MTX_ASSERT(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1114 #if (DEVELOPMENT || DEBUG)
1117 sysctl_do_drain_domains SYSCTL_HANDLER_ARGS
1119 #pragma unused(arg1, arg2)
1123 error
= sysctl_handle_int(oidp
, &dummy
, 0, req
);
1124 if (error
|| req
->newptr
== USER_ADDR_NULL
) {
1128 net_drain_domains();
1133 #endif /* DEVELOPMENT || DEBUG */