2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1998, 1999 Apple Computer, Inc. All Rights Reserved */
23 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
25 * Copyright (c) 1982, 1986, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * @(#)uipc_domain.c 8.3 (Berkeley) 2/14/95
59 #include <sys/param.h>
60 #include <sys/socket.h>
61 #include <sys/protosw.h>
62 #include <sys/domain.h>
65 #include <sys/kernel.h>
66 #include <sys/systm.h>
67 #include <sys/proc_internal.h>
68 #include <sys/sysctl.h>
69 #include <sys/syslog.h>
70 #include <sys/queue.h>
72 void pffasttimo(void *);
73 void pfslowtimo(void *);
76 * Add/delete 'domain': Link structure into system list,
77 * invoke the domain init, and then the proto inits.
78 * To delete, just remove from the list (dom_refs must be zero)
81 lck_grp_t
*domain_proto_mtx_grp
;
82 lck_attr_t
*domain_proto_mtx_attr
;
83 static lck_grp_attr_t
*domain_proto_mtx_grp_attr
;
84 lck_mtx_t
*domain_proto_mtx
;
85 extern int do_reclaim
;
87 void init_domain(register struct domain
*dp
)
91 if ((dp
->dom_mtx
= lck_mtx_alloc_init(domain_proto_mtx_grp
, domain_proto_mtx_attr
)) == NULL
) {
92 printf("init_domain: can't init domain mtx for domain=%s\n", dp
->dom_name
);
93 return; /* we have a problem... */
99 /* and then init the currently installed protos in this domain */
101 for (pr
= dp
->dom_protosw
; pr
; pr
= pr
->pr_next
) {
102 if (pr
->pr_usrreqs
== 0)
103 panic("domaininit: %ssw[%d] has no usrreqs!",
105 (int)(pr
- dp
->dom_protosw
));
111 /* Recompute for new protocol */
112 if (max_linkhdr
< 16) /* XXX - Sheesh; everything's ether? */
114 if (dp
->dom_protohdrlen
> max_protohdr
)
115 max_protohdr
= dp
->dom_protohdrlen
;
116 max_hdr
= max_linkhdr
+ max_protohdr
;
117 max_datalen
= MHLEN
- max_hdr
;
120 void concat_domain(struct domain
*dp
)
122 lck_mtx_assert(domain_proto_mtx
, LCK_MTX_ASSERT_OWNED
);
123 dp
->dom_next
= domains
;
128 net_add_domain(register struct domain
*dp
)
129 { register struct protosw
*pr
;
131 kprintf("Adding domain %s (family %d)\n", dp
->dom_name
,
133 /* First, link in the domain */
135 lck_mtx_lock(domain_proto_mtx
);
139 lck_mtx_unlock(domain_proto_mtx
);
144 net_del_domain(register struct domain
*dp
)
145 { register struct domain
*dp1
, *dp2
;
146 register int retval
= 0;
148 lck_mtx_lock(domain_proto_mtx
);
151 lck_mtx_unlock(domain_proto_mtx
);
155 for (dp2
= NULL
, dp1
= domains
; dp1
; dp2
= dp1
, dp1
= dp1
->dom_next
)
161 dp2
->dom_next
= dp1
->dom_next
;
163 domains
= dp1
->dom_next
;
165 retval
= EPFNOSUPPORT
;
166 lck_mtx_unlock(domain_proto_mtx
);
172 * net_add_proto - link a protosw into a domain's protosw chain
174 * note: protocols must use their own domain lock before calling net_add_proto
177 net_add_proto(register struct protosw
*pp
,
178 register struct domain
*dp
)
179 { register struct protosw
*pp1
, *pp2
;
181 for (pp2
= NULL
, pp1
= dp
->dom_protosw
; pp1
; pp1
= pp1
->pr_next
)
182 { if (pp1
->pr_type
== pp
->pr_type
&&
183 pp1
->pr_protocol
== pp
->pr_protocol
) {
189 dp
->dom_protosw
= pp
;
193 TAILQ_INIT(&pp
->pr_filter_head
);
197 /* Make sure pr_init isn't called again!! */
203 * net_del_proto - remove a protosw from a domain's protosw chain.
204 * Search the protosw chain for the element with matching data.
205 * Then unlink and return.
207 * note: protocols must use their own domain lock before calling net_del_proto
210 net_del_proto(register int type
,
211 register int protocol
,
212 register struct domain
*dp
)
213 { register struct protosw
*pp1
, *pp2
;
215 for (pp2
= NULL
, pp1
= dp
->dom_protosw
; pp1
; pp1
= pp1
->pr_next
)
216 { if (pp1
->pr_type
== type
&&
217 pp1
->pr_protocol
== protocol
)
225 pp2
->pr_next
= pp1
->pr_next
;
227 dp
->dom_protosw
= pp1
->pr_next
;
234 { register struct domain
*dp
;
235 register struct protosw
*pr
;
236 extern struct domain localdomain
, routedomain
, ndrvdomain
, inetdomain
;
237 extern struct domain systemdomain
;
239 extern struct domain nsdomain
;
242 extern struct domain isodomain
;
245 extern struct domain ccittdomain
;
249 extern struct domain atalkdomain
;
252 extern struct domain inet6domain
;
255 extern struct domain keydomain
;
259 * allocate lock group attribute and group for domain mutexes
261 domain_proto_mtx_grp_attr
= lck_grp_attr_alloc_init();
262 lck_grp_attr_setdefault(domain_proto_mtx_grp_attr
);
264 domain_proto_mtx_grp
= lck_grp_alloc_init("domain", domain_proto_mtx_grp_attr
);
267 * allocate the lock attribute for per domain mutexes
269 domain_proto_mtx_attr
= lck_attr_alloc_init();
270 lck_attr_setdefault(domain_proto_mtx_attr
);
272 if ((domain_proto_mtx
= lck_mtx_alloc_init(domain_proto_mtx_grp
, domain_proto_mtx_attr
)) == NULL
) {
273 printf("domaininit: can't init domain mtx for domain list\n");
274 return; /* we have a problem... */
277 * Add all the static domains to the domains list
280 lck_mtx_lock(domain_proto_mtx
);
282 concat_domain(&localdomain
);
283 concat_domain(&routedomain
);
284 concat_domain(&inetdomain
);
286 concat_domain(&atalkdomain
);
289 concat_domain(&inet6domain
);
292 concat_domain(&keydomain
);
296 concat_domain(&nsdomain
);
299 concat_domain(&isodomain
);
302 concat_domain(&ccittdomain
);
304 concat_domain(&ndrvdomain
);
306 concat_domain(&systemdomain
);
309 * Now ask them all to init (XXX including the routing domain,
312 for (dp
= domains
; dp
; dp
= dp
->dom_next
)
315 lck_mtx_unlock(domain_proto_mtx
);
316 timeout(pffasttimo
, NULL
, 1);
317 timeout(pfslowtimo
, NULL
, 1);
321 pffindtype(family
, type
)
324 register struct domain
*dp
;
325 register struct protosw
*pr
;
327 lck_mtx_assert(domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
328 lck_mtx_lock(domain_proto_mtx
);
329 for (dp
= domains
; dp
; dp
= dp
->dom_next
)
330 if (dp
->dom_family
== family
)
332 lck_mtx_unlock(domain_proto_mtx
);
335 for (pr
= dp
->dom_protosw
; pr
; pr
= pr
->pr_next
)
336 if (pr
->pr_type
&& pr
->pr_type
== type
) {
337 lck_mtx_unlock(domain_proto_mtx
);
340 lck_mtx_unlock(domain_proto_mtx
);
348 lck_mtx_assert(domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
349 lck_mtx_lock(domain_proto_mtx
);
352 { if (dp
->dom_family
== pf
) {
353 lck_mtx_unlock(domain_proto_mtx
);
358 lck_mtx_unlock(domain_proto_mtx
);
363 pffindproto(family
, protocol
, type
)
364 int family
, protocol
, type
;
366 register struct protosw
*pr
;
367 lck_mtx_assert(domain_proto_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
368 lck_mtx_lock(domain_proto_mtx
);
369 pr
= pffindproto_locked(family
, protocol
, type
);
370 lck_mtx_unlock(domain_proto_mtx
);
375 pffindproto_locked(family
, protocol
, type
)
376 int family
, protocol
, type
;
378 register struct domain
*dp
;
379 register struct protosw
*pr
;
380 struct protosw
*maybe
= 0;
384 for (dp
= domains
; dp
; dp
= dp
->dom_next
)
385 if (dp
->dom_family
== family
)
389 for (pr
= dp
->dom_protosw
; pr
; pr
= pr
->pr_next
) {
390 if ((pr
->pr_protocol
== protocol
) && (pr
->pr_type
== type
))
393 if (type
== SOCK_RAW
&& pr
->pr_type
== SOCK_RAW
&&
394 pr
->pr_protocol
== 0 && maybe
== (struct protosw
*)0)
401 net_sysctl(int *name
, u_int namelen
, user_addr_t oldp
, size_t *oldlenp
,
402 user_addr_t newp
, size_t newlen
, struct proc
*p
)
404 register struct domain
*dp
;
405 register struct protosw
*pr
;
406 int family
, protocol
, error
;
409 * All sysctl names at this level are nonterminal;
410 * next two components are protocol family and protocol number,
411 * then at least one addition component.
414 return (EISDIR
); /* overloaded */
420 lck_mtx_lock(domain_proto_mtx
);
421 for (dp
= domains
; dp
; dp
= dp
->dom_next
)
422 if (dp
->dom_family
== family
)
424 lck_mtx_unlock(domain_proto_mtx
);
425 return (ENOPROTOOPT
);
427 for (pr
= dp
->dom_protosw
; pr
; pr
= pr
->pr_next
)
428 if (pr
->pr_protocol
== protocol
&& pr
->pr_sysctl
) {
429 error
= (*pr
->pr_sysctl
)(name
+ 2, namelen
- 2,
430 oldp
, oldlenp
, newp
, newlen
);
431 lck_mtx_unlock(domain_proto_mtx
);
434 lck_mtx_unlock(domain_proto_mtx
);
435 return (ENOPROTOOPT
);
443 pfctlinput2(cmd
, sa
, (void*)0);
447 pfctlinput2(cmd
, sa
, ctlparam
)
458 lck_mtx_lock(domain_proto_mtx
);
459 for (dp
= domains
; dp
; dp
= dp
->dom_next
)
460 for (pr
= dp
->dom_protosw
; pr
; pr
= pr
->pr_next
)
462 (*pr
->pr_ctlinput
)(cmd
, sa
, ctlparam
);
463 lck_mtx_unlock(domain_proto_mtx
);
470 register struct domain
*dp
;
471 register struct protosw
*pr
;
473 lck_mtx_lock(domain_proto_mtx
);
474 for (dp
= domains
; dp
; dp
= dp
->dom_next
)
475 for (pr
= dp
->dom_protosw
; pr
; pr
= pr
->pr_next
) {
477 (*pr
->pr_slowtimo
)();
478 if (do_reclaim
&& pr
->pr_drain
)
482 lck_mtx_unlock(domain_proto_mtx
);
483 timeout(pfslowtimo
, NULL
, hz
/2);
491 register struct domain
*dp
;
492 register struct protosw
*pr
;
494 lck_mtx_lock(domain_proto_mtx
);
495 for (dp
= domains
; dp
; dp
= dp
->dom_next
)
496 for (pr
= dp
->dom_protosw
; pr
; pr
= pr
->pr_next
)
498 (*pr
->pr_fasttimo
)();
499 lck_mtx_unlock(domain_proto_mtx
);
500 timeout(pffasttimo
, NULL
, hz
/5);