2 * Copyright (c) 1998-2013 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>
80 #include <mach/boolean.h>
81 #include <pexpert/pexpert.h>
83 static void pr_init_old(struct protosw
*, struct domain
*);
84 static void init_proto(struct protosw
*, struct domain
*);
85 static void attach_proto(struct protosw
*, struct domain
*);
86 static void detach_proto(struct protosw
*, struct domain
*);
87 static void dom_init_old(struct domain
*);
88 static void init_domain(struct domain
*);
89 static void attach_domain(struct domain
*);
90 static void detach_domain(struct domain
*);
91 static struct protosw
*pffindprotonotype_locked(int, int, int);
92 static struct domain
*pffinddomain_locked(int);
94 static boolean_t domain_timeout_run
; /* domain timer is scheduled to run */
95 static boolean_t domain_draining
;
96 static void domain_sched_timeout(void);
97 static void domain_timeout(void *);
99 lck_grp_t
*domain_proto_mtx_grp
;
100 lck_attr_t
*domain_proto_mtx_attr
;
101 static lck_grp_attr_t
*domain_proto_mtx_grp_attr
;
102 decl_lck_mtx_data(static, domain_proto_mtx
);
103 decl_lck_mtx_data(static, domain_timeout_mtx
);
105 extern sysctlfn net_sysctl
;
107 static u_int64_t _net_uptime
;
110 pr_init_old(struct protosw
*pp
, struct domain
*dp
)
113 VERIFY(pp
->pr_flags
& PR_OLD
);
114 VERIFY(pp
->pr_old
!= NULL
);
116 if (pp
->pr_old
->pr_init
!= NULL
)
117 pp
->pr_old
->pr_init();
121 init_proto(struct protosw
*pp
, struct domain
*dp
)
123 VERIFY(pp
->pr_flags
& PR_ATTACHED
);
125 if (!(pp
->pr_flags
& PR_INITIALIZED
)) {
126 TAILQ_INIT(&pp
->pr_filter_head
);
127 if (pp
->pr_init
!= NULL
)
129 pp
->pr_flags
|= PR_INITIALIZED
;
134 attach_proto(struct protosw
*pp
, struct domain
*dp
)
136 domain_proto_mtx_lock_assert_held();
137 VERIFY(!(pp
->pr_flags
& PR_ATTACHED
));
138 VERIFY(pp
->pr_domain
== NULL
);
139 VERIFY(pp
->pr_protosw
== NULL
);
141 TAILQ_INSERT_TAIL(&dp
->dom_protosw
, pp
, pr_entry
);
142 pp
->pr_flags
|= PR_ATTACHED
;
146 /* do some cleaning up on user request callbacks */
147 pru_sanitize(pp
->pr_usrreqs
);
151 detach_proto(struct protosw
*pp
, struct domain
*dp
)
153 domain_proto_mtx_lock_assert_held();
154 VERIFY(pp
->pr_flags
& PR_ATTACHED
);
155 VERIFY(pp
->pr_domain
== dp
);
156 VERIFY(pp
->pr_protosw
== pp
);
158 TAILQ_REMOVE(&dp
->dom_protosw
, pp
, pr_entry
);
159 pp
->pr_flags
&= ~PR_ATTACHED
;
160 pp
->pr_domain
= NULL
;
161 pp
->pr_protosw
= NULL
;
165 dom_init_old(struct domain
*dp
)
167 VERIFY(dp
->dom_flags
& DOM_OLD
);
168 VERIFY(dp
->dom_old
!= NULL
);
170 if (dp
->dom_old
->dom_init
!= NULL
)
171 dp
->dom_old
->dom_init();
175 init_domain(struct domain
*dp
)
177 VERIFY(dp
->dom_flags
& DOM_ATTACHED
);
179 if (!(dp
->dom_flags
& DOM_INITIALIZED
)) {
180 lck_mtx_init(&dp
->dom_mtx_s
, domain_proto_mtx_grp
,
181 domain_proto_mtx_attr
);
182 dp
->dom_mtx
= &dp
->dom_mtx_s
;
183 TAILQ_INIT(&dp
->dom_protosw
);
184 if (dp
->dom_init
!= NULL
)
186 dp
->dom_flags
|= DOM_INITIALIZED
;
189 /* Recompute for new protocol */
190 if (_max_linkhdr
< 16) /* XXX - Sheesh; everything's ether? */
192 _max_linkhdr
= max_linkhdr
; /* round it up */
194 if (dp
->dom_protohdrlen
> _max_protohdr
)
195 _max_protohdr
= dp
->dom_protohdrlen
;
196 _max_protohdr
= max_protohdr
; /* round it up */
198 max_hdr
= max_linkhdr
+ max_protohdr
;
199 max_datalen
= MHLEN
- max_hdr
;
203 attach_domain(struct domain
*dp
)
205 domain_proto_mtx_lock_assert_held();
206 VERIFY(!(dp
->dom_flags
& DOM_ATTACHED
));
208 TAILQ_INSERT_TAIL(&domains
, dp
, dom_entry
);
209 dp
->dom_flags
|= DOM_ATTACHED
;
213 detach_domain(struct domain
*dp
)
215 domain_proto_mtx_lock_assert_held();
216 VERIFY(dp
->dom_flags
& DOM_ATTACHED
);
218 TAILQ_REMOVE(&domains
, dp
, dom_entry
);
219 dp
->dom_flags
&= ~DOM_ATTACHED
;
221 if (dp
->dom_flags
& DOM_OLD
) {
222 struct domain_old
*odp
= dp
->dom_old
;
225 odp
->dom_next
= NULL
;
231 * Exported (private) routine, indirection of net_add_domain.
234 net_add_domain_old(struct domain_old
*odp
)
237 domain_guard_t guard
;
241 guard
= domain_guard_deploy();
242 if ((dp
= pffinddomain_locked(odp
->dom_family
)) != NULL
) {
244 * There is really nothing better than to panic here,
245 * as the caller would not have been able to handle
246 * any failures otherwise.
248 panic("%s: domain (%d,%s) already exists for %s\n", __func__
,
249 dp
->dom_family
, dp
->dom_name
, odp
->dom_name
);
253 /* Make sure nothing is currently pointing to the odp. */
254 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
255 if (dp
->dom_old
== odp
) {
256 panic("%s: domain %p (%d,%s) is already "
257 "associated with %p (%d,%s)\n", __func__
,
258 odp
, odp
->dom_family
, odp
->dom_name
, dp
,
259 dp
->dom_family
, dp
->dom_name
);
264 if (odp
->dom_protosw
!= NULL
) {
265 panic("%s: domain (%d,%s) protocols need to added "
266 "via net_add_proto\n", __func__
, odp
->dom_family
,
271 dp
= _MALLOC(sizeof (*dp
), M_TEMP
, M_WAITOK
| M_ZERO
);
274 * There is really nothing better than to panic here,
275 * as the caller would not have been able to handle
276 * any failures otherwise.
278 panic("%s: unable to allocate memory for domain family "
279 "%d (%s)\n", __func__
, odp
->dom_family
, odp
->dom_name
);
283 /* Copy everything but dom_init, dom_mtx, dom_next and dom_refs */
284 dp
->dom_family
= odp
->dom_family
;
285 dp
->dom_flags
= (odp
->dom_flags
& DOMF_USERFLAGS
) | DOM_OLD
;
286 dp
->dom_name
= odp
->dom_name
;
287 dp
->dom_init
= dom_init_old
;
288 dp
->dom_externalize
= odp
->dom_externalize
;
289 dp
->dom_dispose
= odp
->dom_dispose
;
290 dp
->dom_rtattach
= odp
->dom_rtattach
;
291 dp
->dom_rtoffset
= odp
->dom_rtoffset
;
292 dp
->dom_maxrtkey
= odp
->dom_maxrtkey
;
293 dp
->dom_protohdrlen
= odp
->dom_protohdrlen
;
299 /* Point the mutex back to the internal structure's */
300 odp
->dom_mtx
= dp
->dom_mtx
;
301 domain_guard_release(guard
);
305 * Exported (private) routine, indirection of net_del_domain.
308 net_del_domain_old(struct domain_old
*odp
)
310 struct domain
*dp1
, *dp2
;
312 domain_guard_t guard
;
316 guard
= domain_guard_deploy();
317 if (odp
->dom_refs
!= 0) {
322 TAILQ_FOREACH_SAFE(dp1
, &domains
, dom_entry
, dp2
) {
323 if (!(dp1
->dom_flags
& DOM_OLD
))
325 VERIFY(dp1
->dom_old
!= NULL
);
326 if (odp
== dp1
->dom_old
)
330 struct protosw
*pp1
, *pp2
;
332 VERIFY(dp1
->dom_flags
& DOM_OLD
);
333 VERIFY(dp1
->dom_old
== odp
);
335 /* Remove all protocols attached to this domain */
336 TAILQ_FOREACH_SAFE(pp1
, &dp1
->dom_protosw
, pr_entry
, pp2
) {
337 detach_proto(pp1
, dp1
);
338 if (pp1
->pr_usrreqs
->pru_flags
& PRUF_OLD
)
339 FREE(pp1
->pr_usrreqs
, M_TEMP
);
340 if (pp1
->pr_flags
& PR_OLD
)
347 error
= EPFNOSUPPORT
;
350 domain_guard_release(guard
);
355 * Internal routine, not exported.
357 * net_add_proto - link a protosw into a domain's protosw chain
359 * NOTE: Caller must have acquired domain_proto_mtx
362 net_add_proto(struct protosw
*pp
, struct domain
*dp
, int doinit
)
367 * This could be called as part of initializing the domain,
368 * and thus DOM_INITIALIZED may not be set (yet).
370 domain_proto_mtx_lock_assert_held();
371 VERIFY(!(pp
->pr_flags
& PR_ATTACHED
));
373 /* pr_domain is set only after the protocol is attached */
374 if (pp
->pr_domain
!= NULL
) {
375 panic("%s: domain (%d,%s), proto %d has non-NULL pr_domain!\n",
376 __func__
, dp
->dom_family
, dp
->dom_name
, pp
->pr_protocol
);
380 if (pp
->pr_usrreqs
== NULL
) {
381 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
382 __func__
, dp
->dom_family
, dp
->dom_name
, pp
->pr_protocol
);
386 TAILQ_FOREACH(pp1
, &dp
->dom_protosw
, pr_entry
) {
387 if (pp1
->pr_type
== pp
->pr_type
&&
388 pp1
->pr_protocol
== pp
->pr_protocol
)
392 attach_proto(pp
, dp
);
394 net_init_proto(pp
, dp
);
400 net_init_proto(struct protosw
*pp
, struct domain
*dp
)
403 * This could be called as part of initializing the domain,
404 * and thus DOM_INITIALIZED may not be set (yet). The protocol
405 * must have been attached via net_addr_protosw() by now.
407 domain_proto_mtx_lock_assert_held();
408 VERIFY(pp
->pr_flags
& PR_ATTACHED
);
414 * Exported (private) routine, indirection of net_add_proto.
417 net_add_proto_old(struct protosw_old
*opp
, struct domain_old
*odp
)
419 struct pr_usrreqs_old
*opru
;
420 struct pr_usrreqs
*pru
= NULL
;
421 struct protosw
*pp
= NULL
, *pp1
;
424 domain_guard_t guard
;
427 * This could be called as part of initializing the domain,
428 * and thus DOM_INITIALIZED may not be set (yet).
430 guard
= domain_guard_deploy();
432 /* Make sure the domain has been added via net_add_domain */
433 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
434 if (!(dp
->dom_flags
& DOM_OLD
))
436 if (dp
->dom_old
== odp
)
444 TAILQ_FOREACH(pp1
, &dp
->dom_protosw
, pr_entry
) {
445 if (pp1
->pr_type
== opp
->pr_type
&&
446 pp1
->pr_protocol
== opp
->pr_protocol
) {
452 if ((opru
= opp
->pr_usrreqs
) == NULL
) {
453 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
454 __func__
, odp
->dom_family
, odp
->dom_name
, opp
->pr_protocol
);
458 pru
= _MALLOC(sizeof (*pru
), M_TEMP
, M_WAITOK
| M_ZERO
);
464 pru
->pru_flags
= PRUF_OLD
;
465 pru
->pru_abort
= opru
->pru_abort
;
466 pru
->pru_accept
= opru
->pru_accept
;
467 pru
->pru_attach
= opru
->pru_attach
;
468 pru
->pru_bind
= opru
->pru_bind
;
469 pru
->pru_connect
= opru
->pru_connect
;
470 pru
->pru_connect2
= opru
->pru_connect2
;
471 pru
->pru_control
= opru
->pru_control
;
472 pru
->pru_detach
= opru
->pru_detach
;
473 pru
->pru_disconnect
= opru
->pru_disconnect
;
474 pru
->pru_listen
= opru
->pru_listen
;
475 pru
->pru_peeraddr
= opru
->pru_peeraddr
;
476 pru
->pru_rcvd
= opru
->pru_rcvd
;
477 pru
->pru_rcvoob
= opru
->pru_rcvoob
;
478 pru
->pru_send
= opru
->pru_send
;
479 pru
->pru_sense
= opru
->pru_sense
;
480 pru
->pru_shutdown
= opru
->pru_shutdown
;
481 pru
->pru_sockaddr
= opru
->pru_sockaddr
;
482 pru
->pru_sosend
= opru
->pru_sosend
;
483 pru
->pru_soreceive
= opru
->pru_soreceive
;
484 pru
->pru_sopoll
= opru
->pru_sopoll
;
486 pp
= _MALLOC(sizeof (*pp
), M_TEMP
, M_WAITOK
| M_ZERO
);
493 * Protocol fast and slow timers are now deprecated.
495 if (opp
->pr_unused
!= NULL
) {
496 printf("%s: domain (%d,%s), proto %d: pr_fasttimo is "
497 "deprecated and won't be called\n", __func__
,
498 odp
->dom_family
, odp
->dom_name
, opp
->pr_protocol
);
500 if (opp
->pr_unused2
!= NULL
) {
501 printf("%s: domain (%d,%s), proto %d: pr_slowtimo is "
502 "deprecated and won't be called\n", __func__
,
503 odp
->dom_family
, odp
->dom_name
, opp
->pr_protocol
);
506 /* Copy everything but pr_init, pr_next, pr_domain, pr_protosw */
507 pp
->pr_type
= opp
->pr_type
;
508 pp
->pr_protocol
= opp
->pr_protocol
;
509 pp
->pr_flags
= (opp
->pr_flags
& PRF_USERFLAGS
) | PR_OLD
;
510 pp
->pr_input
= opp
->pr_input
;
511 pp
->pr_output
= opp
->pr_output
;
512 pp
->pr_ctlinput
= opp
->pr_ctlinput
;
513 pp
->pr_ctloutput
= opp
->pr_ctloutput
;
514 pp
->pr_usrreqs
= pru
;
515 pp
->pr_init
= pr_init_old
;
516 pp
->pr_drain
= opp
->pr_drain
;
517 pp
->pr_sysctl
= opp
->pr_sysctl
;
518 pp
->pr_lock
= opp
->pr_lock
;
519 pp
->pr_unlock
= opp
->pr_unlock
;
520 pp
->pr_getlock
= opp
->pr_getlock
;
523 /* attach as well as initialize */
524 attach_proto(pp
, dp
);
525 net_init_proto(pp
, dp
);
528 printf("%s: domain (%d,%s), proto %d: failed to attach, "
529 "error %d\n", __func__
, odp
->dom_family
,
530 odp
->dom_name
, opp
->pr_protocol
, error
);
538 domain_guard_release(guard
);
543 * Internal routine, not exported.
545 * net_del_proto - remove a protosw from a domain's protosw chain.
546 * Search the protosw chain for the element with matching data.
547 * Then unlink and return.
549 * NOTE: Caller must have acquired domain_proto_mtx
552 net_del_proto(int type
, int protocol
, struct domain
*dp
)
557 * This could be called as part of initializing the domain,
558 * and thus DOM_INITIALIZED may not be set (yet).
560 domain_proto_mtx_lock_assert_held();
562 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
563 if (pp
->pr_type
== type
&& pp
->pr_protocol
== protocol
)
569 detach_proto(pp
, dp
);
570 if (pp
->pr_usrreqs
->pru_flags
& PRUF_OLD
)
571 FREE(pp
->pr_usrreqs
, M_TEMP
);
572 if (pp
->pr_flags
& PR_OLD
)
579 * Exported (private) routine, indirection of net_del_proto.
582 net_del_proto_old(int type
, int protocol
, struct domain_old
*odp
)
587 domain_guard_t guard
;
590 * This could be called as part of initializing the domain,
591 * and thus DOM_INITIALIZED may not be set (yet).
593 guard
= domain_guard_deploy();
595 /* Make sure the domain has been added via net_add_domain */
596 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
597 if (!(dp
->dom_flags
& DOM_OLD
))
599 if (dp
->dom_old
== odp
)
607 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
608 if (pp
->pr_type
== type
&& pp
->pr_protocol
== protocol
)
615 detach_proto(pp
, dp
);
616 if (pp
->pr_usrreqs
->pru_flags
& PRUF_OLD
)
617 FREE(pp
->pr_usrreqs
, M_TEMP
);
618 if (pp
->pr_flags
& PR_OLD
)
622 domain_guard_release(guard
);
627 domain_sched_timeout(void)
629 lck_mtx_assert(&domain_timeout_mtx
, LCK_MTX_ASSERT_OWNED
);
631 if (!domain_timeout_run
&& domain_draining
) {
632 domain_timeout_run
= TRUE
;
633 timeout(domain_timeout
, NULL
, hz
);
638 net_drain_domains(void)
640 lck_mtx_lock(&domain_timeout_mtx
);
641 domain_draining
= TRUE
;
642 domain_sched_timeout();
643 lck_mtx_unlock(&domain_timeout_mtx
);
647 extern struct domain inet6domain_s
;
650 extern struct domain keydomain_s
;
653 extern struct domain routedomain_s
, ndrvdomain_s
, inetdomain_s
;
654 extern struct domain systemdomain_s
, localdomain_s
;
657 extern struct domain mpdomain_s
;
658 #endif /* MULTIPATH */
661 domain_timeout(void *arg
)
666 domain_guard_t guard
;
668 lck_mtx_lock(&domain_timeout_mtx
);
669 if (domain_draining
) {
670 domain_draining
= FALSE
;
671 lck_mtx_unlock(&domain_timeout_mtx
);
673 guard
= domain_guard_deploy();
674 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
675 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
676 if (pp
->pr_drain
!= NULL
)
680 domain_guard_release(guard
);
682 lck_mtx_lock(&domain_timeout_mtx
);
685 /* re-arm the timer if there's work to do */
686 domain_timeout_run
= FALSE
;
687 domain_sched_timeout();
688 lck_mtx_unlock(&domain_timeout_mtx
);
695 domain_guard_t guard
;
698 * allocate lock group attribute and group for domain mutexes
700 domain_proto_mtx_grp_attr
= lck_grp_attr_alloc_init();
702 domain_proto_mtx_grp
= lck_grp_alloc_init("domain",
703 domain_proto_mtx_grp_attr
);
706 * allocate the lock attribute for per domain mutexes
708 domain_proto_mtx_attr
= lck_attr_alloc_init();
710 lck_mtx_init(&domain_proto_mtx
, domain_proto_mtx_grp
,
711 domain_proto_mtx_attr
);
712 lck_mtx_init(&domain_timeout_mtx
, domain_proto_mtx_grp
,
713 domain_proto_mtx_attr
);
715 guard
= domain_guard_deploy();
717 * Add all the static domains to the domains list. route domain
718 * gets added and initialized last, since we need it to attach
719 * rt_tables[] to everything that's already there. This also
720 * means that domains added after this point won't get their
721 * dom_rtattach() called on rt_tables[].
723 attach_domain(&inetdomain_s
);
725 attach_domain(&inet6domain_s
);
728 attach_domain(&mpdomain_s
);
729 #endif /* MULTIPATH */
730 attach_domain(&systemdomain_s
);
731 attach_domain(&localdomain_s
);
733 attach_domain(&keydomain_s
);
735 attach_domain(&ndrvdomain_s
);
736 attach_domain(&routedomain_s
); /* must be last domain */
739 * Now ask them all to init (XXX including the routing domain,
742 TAILQ_FOREACH(dp
, &domains
, dom_entry
)
745 domain_guard_release(guard
);
748 static __inline__
struct domain
*
749 pffinddomain_locked(int pf
)
753 domain_proto_mtx_lock_assert_held();
755 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
756 if (dp
->dom_family
== pf
)
763 pffindtype(int family
, int type
)
765 struct protosw
*pp
= NULL
;
767 domain_guard_t guard
;
769 guard
= domain_guard_deploy();
770 if ((dp
= pffinddomain_locked(family
)) == NULL
)
773 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
774 if (pp
->pr_type
!= 0 && pp
->pr_type
== type
)
778 domain_guard_release(guard
);
783 * Internal routine, not exported.
789 domain_guard_t guard
;
791 guard
= domain_guard_deploy();
792 dp
= pffinddomain_locked(pf
);
793 domain_guard_release(guard
);
798 * Exported (private) routine, indirection of pffinddomain.
801 pffinddomain_old(int pf
)
803 struct domain_old
*odp
= NULL
;
805 domain_guard_t guard
;
807 guard
= domain_guard_deploy();
808 if ((dp
= pffinddomain_locked(pf
)) != NULL
&& (dp
->dom_flags
& DOM_OLD
))
810 domain_guard_release(guard
);
815 * Internal routine, not exported.
818 pffindproto(int family
, int protocol
, int type
)
821 domain_guard_t guard
;
823 guard
= domain_guard_deploy();
824 pp
= pffindproto_locked(family
, protocol
, type
);
825 domain_guard_release(guard
);
830 pffindproto_locked(int family
, int protocol
, int type
)
832 struct protosw
*maybe
= NULL
;
836 domain_proto_mtx_lock_assert_held();
841 dp
= pffinddomain_locked(family
);
845 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
846 if ((pp
->pr_protocol
== protocol
) && (pp
->pr_type
== type
))
849 if (type
== SOCK_RAW
&& pp
->pr_type
== SOCK_RAW
&&
850 pp
->pr_protocol
== 0 && maybe
== NULL
)
857 * Exported (private) routine, indirection of pffindproto.
860 pffindproto_old(int family
, int protocol
, int type
)
862 struct protosw_old
*opr
= NULL
;
864 domain_guard_t guard
;
866 guard
= domain_guard_deploy();
867 if ((pp
= pffindproto_locked(family
, protocol
, type
)) != NULL
&&
868 (pp
->pr_flags
& PR_OLD
))
870 domain_guard_release(guard
);
874 static struct protosw
*
875 pffindprotonotype_locked(int family
, int protocol
, int type
)
881 domain_proto_mtx_lock_assert_held();
886 dp
= pffinddomain_locked(family
);
890 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
891 if (pp
->pr_protocol
== protocol
)
898 pffindprotonotype(int family
, int protocol
)
901 domain_guard_t guard
;
906 guard
= domain_guard_deploy();
907 pp
= pffindprotonotype_locked(family
, protocol
, 0);
908 domain_guard_release(guard
);
913 net_sysctl(int *name
, u_int namelen
, user_addr_t oldp
, size_t *oldlenp
,
914 user_addr_t newp
, size_t newlen
, struct proc
*p
)
917 int family
, protocol
, error
= 0;
920 domain_guard_t guard
;
923 * All sysctl names at this level are nonterminal;
924 * next two components are protocol family and protocol number,
925 * then at least one addition component.
928 return (EISDIR
); /* overloaded */
935 guard
= domain_guard_deploy();
936 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
937 if (dp
->dom_family
== family
)
945 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
946 if (pp
->pr_protocol
== protocol
&& pp
->pr_sysctl
!= NULL
) {
947 error
= (*pp
->pr_sysctl
)(name
+ 2, namelen
- 2,
948 (void *)(uintptr_t)oldp
, oldlenp
,
949 (void *)(uintptr_t)newp
, newlen
);
955 domain_guard_release(guard
);
960 pfctlinput(int cmd
, struct sockaddr
*sa
)
962 pfctlinput2(cmd
, sa
, NULL
);
966 pfctlinput2(int cmd
, struct sockaddr
*sa
, void *ctlparam
)
970 domain_guard_t guard
;
975 guard
= domain_guard_deploy();
976 TAILQ_FOREACH(dp
, &domains
, dom_entry
) {
977 TAILQ_FOREACH(pp
, &dp
->dom_protosw
, pr_entry
) {
978 if (pp
->pr_ctlinput
!= NULL
)
979 (*pp
->pr_ctlinput
)(cmd
, sa
, ctlparam
);
982 domain_guard_release(guard
);
986 net_update_uptime(void)
991 _net_uptime
= tv
.tv_sec
;
993 * Round up the timer to the nearest integer value because otherwise
994 * we might setup networking timers that are off by almost 1 second.
996 if (tv
.tv_usec
> 500000)
1001 net_update_uptime_secs(uint64_t secs
)
1007 * Convert our uin64_t net_uptime to a struct timeval.
1010 net_uptime2timeval(struct timeval
*tv
)
1016 tv
->tv_sec
= net_uptime();
1020 * An alternative way to obtain the coarse-grained uptime (in seconds)
1021 * for networking code which do not require high-precision timestamp,
1022 * as this is significantly cheaper than microuptime().
1027 if (_net_uptime
== 0)
1028 net_update_uptime();
1030 return (_net_uptime
);
1034 domain_proto_mtx_lock_assert_held(void)
1036 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1040 domain_proto_mtx_lock_assert_notheld(void)
1042 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1046 domain_guard_deploy(void)
1048 net_thread_marks_t marks
;
1050 marks
= net_thread_marks_push(NET_THREAD_HELD_DOMAIN
);
1051 if (marks
!= net_thread_marks_none
) {
1052 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1053 lck_mtx_lock(&domain_proto_mtx
);
1056 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1058 return ((domain_guard_t
)(const void*)marks
);
1062 domain_guard_release(domain_guard_t guard
)
1064 net_thread_marks_t marks
= (net_thread_marks_t
)(const void*)guard
;
1066 if (marks
!= net_thread_marks_none
) {
1067 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1068 lck_mtx_unlock(&domain_proto_mtx
);
1069 net_thread_marks_pop(marks
);
1072 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1076 domain_unguard_deploy(void)
1078 net_thread_marks_t marks
;
1080 marks
= net_thread_unmarks_push(NET_THREAD_HELD_DOMAIN
);
1081 if (marks
!= net_thread_marks_none
) {
1082 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
1083 lck_mtx_unlock(&domain_proto_mtx
);
1086 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1088 return ((domain_unguard_t
)(const void*)marks
);
1092 domain_unguard_release(domain_unguard_t unguard
)
1094 net_thread_marks_t marks
= (net_thread_marks_t
)(const void*)unguard
;
1096 if (marks
!= net_thread_marks_none
) {
1097 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1098 lck_mtx_lock(&domain_proto_mtx
);
1099 net_thread_unmarks_pop(marks
);
1102 lck_mtx_assert(&domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);