]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/uipc_domain.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / bsd / kern / uipc_domain.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
A
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.
8f6c56a5 11 *
6601e61a
A
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
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
21 */
22/* Copyright (c) 1998, 1999 Apple Computer, Inc. All Rights Reserved */
23/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24/*
25 * Copyright (c) 1982, 1986, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
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.
43 *
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
54 * SUCH DAMAGE.
55 *
56 * @(#)uipc_domain.c 8.3 (Berkeley) 2/14/95
57 */
58
59#include <sys/param.h>
60#include <sys/socket.h>
61#include <sys/protosw.h>
62#include <sys/domain.h>
63#include <sys/mbuf.h>
64#include <sys/time.h>
65#include <sys/kernel.h>
66#include <sys/systm.h>
91447636 67#include <sys/proc_internal.h>
1c79356b
A
68#include <sys/sysctl.h>
69#include <sys/syslog.h>
70#include <sys/queue.h>
71
91447636
A
72void pffasttimo(void *);
73void pfslowtimo(void *);
1c79356b
A
74
75/*
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)
79 */
80
91447636
A
81lck_grp_t *domain_proto_mtx_grp;
82lck_attr_t *domain_proto_mtx_attr;
83static lck_grp_attr_t *domain_proto_mtx_grp_attr;
84lck_mtx_t *domain_proto_mtx;
85extern int do_reclaim;
1c79356b
A
86
87void init_domain(register struct domain *dp)
88{
89 struct protosw *pr;
90
91447636
A
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... */
94 }
95
1c79356b
A
96 if (dp->dom_init)
97 (*dp->dom_init)();
98
99 /* and then init the currently installed protos in this domain */
100
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!",
104 dp->dom_name,
105 (int)(pr - dp->dom_protosw));
106
107 if (pr->pr_init)
108 (*pr->pr_init)();
109 }
110
111 /* Recompute for new protocol */
112 if (max_linkhdr < 16) /* XXX - Sheesh; everything's ether? */
113 max_linkhdr = 16;
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;
118}
119
120void concat_domain(struct domain *dp)
121{
91447636 122 lck_mtx_assert(domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1c79356b
A
123 dp->dom_next = domains;
124 domains = dp;
125}
126
127void
128net_add_domain(register struct domain *dp)
129{ register struct protosw *pr;
1c79356b
A
130
131 kprintf("Adding domain %s (family %d)\n", dp->dom_name,
132 dp->dom_family);
133 /* First, link in the domain */
1c79356b 134
91447636 135 lck_mtx_lock(domain_proto_mtx);
1c79356b
A
136 concat_domain(dp);
137
138 init_domain(dp);
91447636 139 lck_mtx_unlock(domain_proto_mtx);
1c79356b 140
1c79356b
A
141}
142
143int
144net_del_domain(register struct domain *dp)
145{ register struct domain *dp1, *dp2;
91447636
A
146 register int retval = 0;
147
148 lck_mtx_lock(domain_proto_mtx);
1c79356b 149
91447636
A
150 if (dp->dom_refs) {
151 lck_mtx_unlock(domain_proto_mtx);
1c79356b 152 return(EBUSY);
91447636 153 }
1c79356b
A
154
155 for (dp2 = NULL, dp1 = domains; dp1; dp2 = dp1, dp1 = dp1->dom_next)
156 { if (dp == dp1)
157 break;
158 }
159 if (dp1)
160 { if (dp2)
161 dp2->dom_next = dp1->dom_next;
162 else
163 domains = dp1->dom_next;
164 } else
165 retval = EPFNOSUPPORT;
91447636 166 lck_mtx_unlock(domain_proto_mtx);
1c79356b
A
167
168 return(retval);
169}
170
171/*
172 * net_add_proto - link a protosw into a domain's protosw chain
91447636
A
173 *
174 * note: protocols must use their own domain lock before calling net_add_proto
1c79356b
A
175 */
176int
177net_add_proto(register struct protosw *pp,
178 register struct domain *dp)
179{ register struct protosw *pp1, *pp2;
1c79356b 180
1c79356b
A
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) {
1c79356b
A
184 return(EEXIST);
185 }
186 pp2 = pp1;
187 }
188 if (pp2 == NULL)
189 dp->dom_protosw = pp;
190 else
191 pp2->pr_next = pp;
192 pp->pr_next = NULL;
91447636 193 TAILQ_INIT(&pp->pr_filter_head);
1c79356b
A
194 if (pp->pr_init)
195 (*pp->pr_init)();
196
197 /* Make sure pr_init isn't called again!! */
198 pp->pr_init = 0;
1c79356b
A
199 return(0);
200}
201
202/*
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.
91447636
A
206 *
207 * note: protocols must use their own domain lock before calling net_del_proto
1c79356b
A
208 */
209int
210net_del_proto(register int type,
211 register int protocol,
212 register struct domain *dp)
213{ register struct protosw *pp1, *pp2;
1c79356b 214
1c79356b
A
215 for (pp2 = NULL, pp1 = dp->dom_protosw; pp1; pp1 = pp1->pr_next)
216 { if (pp1->pr_type == type &&
217 pp1->pr_protocol == protocol)
218 break;
219 pp2 = pp1;
220 }
221 if (pp1 == NULL) {
1c79356b
A
222 return(ENXIO);
223 }
224 if (pp2)
225 pp2->pr_next = pp1->pr_next;
226 else
227 dp->dom_protosw = pp1->pr_next;
1c79356b
A
228 return(0);
229}
230
231
232void
233domaininit()
234{ register struct domain *dp;
235 register struct protosw *pr;
236 extern struct domain localdomain, routedomain, ndrvdomain, inetdomain;
237 extern struct domain systemdomain;
238#if NS
239 extern struct domain nsdomain;
240#endif
241#if ISO
242 extern struct domain isodomain;
243#endif
244#if CCITT
245 extern struct domain ccittdomain;
246#endif
247
248#if NETAT
249 extern struct domain atalkdomain;
250#endif
251#if INET6
252 extern struct domain inet6domain;
253#endif
254#if IPSEC
255 extern struct domain keydomain;
256#endif
257
91447636
A
258 /*
259 * allocate lock group attribute and group for domain mutexes
260 */
261 domain_proto_mtx_grp_attr = lck_grp_attr_alloc_init();
91447636
A
262
263 domain_proto_mtx_grp = lck_grp_alloc_init("domain", domain_proto_mtx_grp_attr);
264
265 /*
266 * allocate the lock attribute for per domain mutexes
267 */
268 domain_proto_mtx_attr = lck_attr_alloc_init();
91447636
A
269
270 if ((domain_proto_mtx = lck_mtx_alloc_init(domain_proto_mtx_grp, domain_proto_mtx_attr)) == NULL) {
271 printf("domaininit: can't init domain mtx for domain list\n");
272 return; /* we have a problem... */
273 }
1c79356b
A
274 /*
275 * Add all the static domains to the domains list
276 */
277
91447636
A
278 lck_mtx_lock(domain_proto_mtx);
279
1c79356b
A
280 concat_domain(&localdomain);
281 concat_domain(&routedomain);
282 concat_domain(&inetdomain);
283#if NETAT
284 concat_domain(&atalkdomain);
285#endif
286#if INET6
287 concat_domain(&inet6domain);
288#endif
289#if IPSEC
290 concat_domain(&keydomain);
291#endif
292
293#if NS
294 concat_domain(&nsdomain);
295#endif
296#if ISO
297 concat_domain(&isodomain);
298#endif
299#if CCITT
300 concat_domain(&ccittdomain);
301#endif
302 concat_domain(&ndrvdomain);
303
304 concat_domain(&systemdomain);
305
306 /*
307 * Now ask them all to init (XXX including the routing domain,
308 * see above)
309 */
310 for (dp = domains; dp; dp = dp->dom_next)
311 init_domain(dp);
312
91447636 313 lck_mtx_unlock(domain_proto_mtx);
1c79356b
A
314 timeout(pffasttimo, NULL, 1);
315 timeout(pfslowtimo, NULL, 1);
1c79356b
A
316}
317
318struct protosw *
319pffindtype(family, type)
320 int family, type;
321{
322 register struct domain *dp;
323 register struct protosw *pr;
324
91447636
A
325 lck_mtx_assert(domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
326 lck_mtx_lock(domain_proto_mtx);
1c79356b
A
327 for (dp = domains; dp; dp = dp->dom_next)
328 if (dp->dom_family == family)
329 goto found;
91447636 330 lck_mtx_unlock(domain_proto_mtx);
1c79356b
A
331 return (0);
332found:
333 for (pr = dp->dom_protosw; pr; pr = pr->pr_next)
91447636
A
334 if (pr->pr_type && pr->pr_type == type) {
335 lck_mtx_unlock(domain_proto_mtx);
1c79356b 336 return (pr);
91447636
A
337 }
338 lck_mtx_unlock(domain_proto_mtx);
1c79356b
A
339 return (0);
340}
341
342struct domain *
343pffinddomain(int pf)
344{ struct domain *dp;
345
91447636
A
346 lck_mtx_assert(domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
347 lck_mtx_lock(domain_proto_mtx);
1c79356b
A
348 dp = domains;
349 while (dp)
91447636
A
350 { if (dp->dom_family == pf) {
351 lck_mtx_unlock(domain_proto_mtx);
1c79356b 352 return(dp);
91447636 353 }
1c79356b
A
354 dp = dp->dom_next;
355 }
91447636 356 lck_mtx_unlock(domain_proto_mtx);
1c79356b
A
357 return(NULL);
358}
359
360struct protosw *
361pffindproto(family, protocol, type)
362 int family, protocol, type;
91447636
A
363{
364 register struct protosw *pr;
365 lck_mtx_assert(domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
366 lck_mtx_lock(domain_proto_mtx);
367 pr = pffindproto_locked(family, protocol, type);
368 lck_mtx_unlock(domain_proto_mtx);
369 return (pr);
370}
371
372struct protosw *
373pffindproto_locked(family, protocol, type)
374 int family, protocol, type;
1c79356b
A
375{
376 register struct domain *dp;
377 register struct protosw *pr;
378 struct protosw *maybe = 0;
379
380 if (family == 0)
381 return (0);
382 for (dp = domains; dp; dp = dp->dom_next)
383 if (dp->dom_family == family)
384 goto found;
385 return (0);
386found:
387 for (pr = dp->dom_protosw; pr; pr = pr->pr_next) {
388 if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
389 return (pr);
390
391 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
392 pr->pr_protocol == 0 && maybe == (struct protosw *)0)
393 maybe = pr;
394 }
395 return (maybe);
396}
397
398int
91447636
A
399net_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
400 user_addr_t newp, size_t newlen, struct proc *p)
1c79356b
A
401{
402 register struct domain *dp;
403 register struct protosw *pr;
91447636 404 int family, protocol, error;
1c79356b
A
405
406 /*
407 * All sysctl names at this level are nonterminal;
408 * next two components are protocol family and protocol number,
409 * then at least one addition component.
410 */
411 if (namelen < 3)
412 return (EISDIR); /* overloaded */
413 family = name[0];
414 protocol = name[1];
415
416 if (family == 0)
417 return (0);
91447636 418 lck_mtx_lock(domain_proto_mtx);
1c79356b
A
419 for (dp = domains; dp; dp = dp->dom_next)
420 if (dp->dom_family == family)
421 goto found;
91447636 422 lck_mtx_unlock(domain_proto_mtx);
1c79356b
A
423 return (ENOPROTOOPT);
424found:
425 for (pr = dp->dom_protosw; pr; pr = pr->pr_next)
91447636
A
426 if (pr->pr_protocol == protocol && pr->pr_sysctl) {
427 error = (*pr->pr_sysctl)(name + 2, namelen - 2,
428 oldp, oldlenp, newp, newlen);
429 lck_mtx_unlock(domain_proto_mtx);
430 return (error);
431 }
432 lck_mtx_unlock(domain_proto_mtx);
1c79356b
A
433 return (ENOPROTOOPT);
434}
435
436void
437pfctlinput(cmd, sa)
438 int cmd;
439 struct sockaddr *sa;
440{
9bccf70c
A
441 pfctlinput2(cmd, sa, (void*)0);
442}
443
444void
445pfctlinput2(cmd, sa, ctlparam)
446 int cmd;
447 struct sockaddr *sa;
448 void *ctlparam;
449{
450 struct domain *dp;
451 struct protosw *pr;
1c79356b 452
9bccf70c
A
453 if (!sa)
454 return;
91447636
A
455
456 lck_mtx_lock(domain_proto_mtx);
1c79356b
A
457 for (dp = domains; dp; dp = dp->dom_next)
458 for (pr = dp->dom_protosw; pr; pr = pr->pr_next)
459 if (pr->pr_ctlinput)
9bccf70c 460 (*pr->pr_ctlinput)(cmd, sa, ctlparam);
91447636 461 lck_mtx_unlock(domain_proto_mtx);
1c79356b
A
462}
463
464void
465pfslowtimo(arg)
466 void *arg;
467{
468 register struct domain *dp;
469 register struct protosw *pr;
1c79356b 470
91447636
A
471 lck_mtx_lock(domain_proto_mtx);
472 for (dp = domains; dp; dp = dp->dom_next)
473 for (pr = dp->dom_protosw; pr; pr = pr->pr_next) {
1c79356b
A
474 if (pr->pr_slowtimo)
475 (*pr->pr_slowtimo)();
91447636
A
476 if (do_reclaim && pr->pr_drain)
477 (*pr->pr_drain)();
478 }
479 do_reclaim = 0;
480 lck_mtx_unlock(domain_proto_mtx);
1c79356b
A
481 timeout(pfslowtimo, NULL, hz/2);
482
1c79356b
A
483}
484
485void
486pffasttimo(arg)
487 void *arg;
488{
489 register struct domain *dp;
490 register struct protosw *pr;
1c79356b 491
91447636 492 lck_mtx_lock(domain_proto_mtx);
1c79356b
A
493 for (dp = domains; dp; dp = dp->dom_next)
494 for (pr = dp->dom_protosw; pr; pr = pr->pr_next)
495 if (pr->pr_fasttimo)
496 (*pr->pr_fasttimo)();
91447636 497 lck_mtx_unlock(domain_proto_mtx);
1c79356b 498 timeout(pffasttimo, NULL, hz/5);
1c79356b 499}