]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/uipc_domain.c
xnu-2782.30.5.tar.gz
[apple/xnu.git] / bsd / kern / uipc_domain.c
1 /*
2 * Copyright (c) 1998-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29 /*
30 * Copyright (c) 1982, 1986, 1993
31 * The Regents of the University of California. All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
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.
48 *
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
59 * SUCH DAMAGE.
60 *
61 * @(#)uipc_domain.c 8.3 (Berkeley) 2/14/95
62 */
63
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>
69 #include <sys/mbuf.h>
70 #include <sys/time.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>
77
78 #include <net/dlil.h>
79
80 #include <mach/boolean.h>
81 #include <pexpert/pexpert.h>
82
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);
93
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 *);
98
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);
104
105 static u_int64_t _net_uptime;
106
107 static void
108 pr_init_old(struct protosw *pp, struct domain *dp)
109 {
110 #pragma unused(dp)
111 VERIFY(pp->pr_flags & PR_OLD);
112 VERIFY(pp->pr_old != NULL);
113
114 if (pp->pr_old->pr_init != NULL)
115 pp->pr_old->pr_init();
116 }
117
118 static void
119 init_proto(struct protosw *pp, struct domain *dp)
120 {
121 VERIFY(pp->pr_flags & PR_ATTACHED);
122
123 if (!(pp->pr_flags & PR_INITIALIZED)) {
124 TAILQ_INIT(&pp->pr_filter_head);
125 if (pp->pr_init != NULL)
126 pp->pr_init(pp, dp);
127 pp->pr_flags |= PR_INITIALIZED;
128 }
129 }
130
131 static void
132 attach_proto(struct protosw *pp, struct domain *dp)
133 {
134 domain_proto_mtx_lock_assert_held();
135 VERIFY(!(pp->pr_flags & PR_ATTACHED));
136 VERIFY(pp->pr_domain == NULL);
137 VERIFY(pp->pr_protosw == NULL);
138
139 TAILQ_INSERT_TAIL(&dp->dom_protosw, pp, pr_entry);
140 pp->pr_flags |= PR_ATTACHED;
141 pp->pr_domain = dp;
142 pp->pr_protosw = pp;
143
144 /* do some cleaning up on user request callbacks */
145 pru_sanitize(pp->pr_usrreqs);
146 }
147
148 static void
149 detach_proto(struct protosw *pp, struct domain *dp)
150 {
151 domain_proto_mtx_lock_assert_held();
152 VERIFY(pp->pr_flags & PR_ATTACHED);
153 VERIFY(pp->pr_domain == dp);
154 VERIFY(pp->pr_protosw == pp);
155
156 TAILQ_REMOVE(&dp->dom_protosw, pp, pr_entry);
157 pp->pr_flags &= ~PR_ATTACHED;
158 pp->pr_domain = NULL;
159 pp->pr_protosw = NULL;
160 }
161
162 static void
163 dom_init_old(struct domain *dp)
164 {
165 VERIFY(dp->dom_flags & DOM_OLD);
166 VERIFY(dp->dom_old != NULL);
167
168 if (dp->dom_old->dom_init != NULL)
169 dp->dom_old->dom_init();
170 }
171
172 static void
173 init_domain(struct domain *dp)
174 {
175 VERIFY(dp->dom_flags & DOM_ATTACHED);
176
177 if (!(dp->dom_flags & DOM_INITIALIZED)) {
178 lck_mtx_init(&dp->dom_mtx_s, domain_proto_mtx_grp,
179 domain_proto_mtx_attr);
180 dp->dom_mtx = &dp->dom_mtx_s;
181 TAILQ_INIT(&dp->dom_protosw);
182 if (dp->dom_init != NULL)
183 dp->dom_init(dp);
184 dp->dom_flags |= DOM_INITIALIZED;
185 }
186
187 /* Recompute for new protocol */
188 if (_max_linkhdr < 16) /* XXX - Sheesh; everything's ether? */
189 _max_linkhdr = 16;
190 _max_linkhdr = max_linkhdr; /* round it up */
191
192 if (dp->dom_protohdrlen > _max_protohdr)
193 _max_protohdr = dp->dom_protohdrlen;
194 _max_protohdr = max_protohdr; /* round it up */
195
196 max_hdr = max_linkhdr + max_protohdr;
197 max_datalen = MHLEN - max_hdr;
198 }
199
200 static void
201 attach_domain(struct domain *dp)
202 {
203 domain_proto_mtx_lock_assert_held();
204 VERIFY(!(dp->dom_flags & DOM_ATTACHED));
205
206 TAILQ_INSERT_TAIL(&domains, dp, dom_entry);
207 dp->dom_flags |= DOM_ATTACHED;
208 }
209
210 static void
211 detach_domain(struct domain *dp)
212 {
213 domain_proto_mtx_lock_assert_held();
214 VERIFY(dp->dom_flags & DOM_ATTACHED);
215
216 TAILQ_REMOVE(&domains, dp, dom_entry);
217 dp->dom_flags &= ~DOM_ATTACHED;
218
219 if (dp->dom_flags & DOM_OLD) {
220 struct domain_old *odp = dp->dom_old;
221
222 VERIFY(odp != NULL);
223 odp->dom_next = NULL;
224 odp->dom_mtx = NULL;
225 }
226 }
227
228 /*
229 * Exported (private) routine, indirection of net_add_domain.
230 */
231 void
232 net_add_domain_old(struct domain_old *odp)
233 {
234 struct domain *dp;
235 domain_guard_t guard;
236
237 VERIFY(odp != NULL);
238
239 guard = domain_guard_deploy();
240 if ((dp = pffinddomain_locked(odp->dom_family)) != NULL) {
241 /*
242 * There is really nothing better than to panic here,
243 * as the caller would not have been able to handle
244 * any failures otherwise.
245 */
246 panic("%s: domain (%d,%s) already exists for %s\n", __func__,
247 dp->dom_family, dp->dom_name, odp->dom_name);
248 /* NOTREACHED */
249 }
250
251 /* Make sure nothing is currently pointing to the odp. */
252 TAILQ_FOREACH(dp, &domains, dom_entry) {
253 if (dp->dom_old == odp) {
254 panic("%s: domain %p (%d,%s) is already "
255 "associated with %p (%d,%s)\n", __func__,
256 odp, odp->dom_family, odp->dom_name, dp,
257 dp->dom_family, dp->dom_name);
258 /* NOTREACHED */
259 }
260 }
261
262 if (odp->dom_protosw != NULL) {
263 panic("%s: domain (%d,%s) protocols need to added "
264 "via net_add_proto\n", __func__, odp->dom_family,
265 odp->dom_name);
266 /* NOTREACHED */
267 }
268
269 dp = _MALLOC(sizeof (*dp), M_TEMP, M_WAITOK | M_ZERO);
270 if (dp == NULL) {
271 /*
272 * There is really nothing better than to panic here,
273 * as the caller would not have been able to handle
274 * any failures otherwise.
275 */
276 panic("%s: unable to allocate memory for domain family "
277 "%d (%s)\n", __func__, odp->dom_family, odp->dom_name);
278 /* NOTREACHED */
279 }
280
281 /* Copy everything but dom_init, dom_mtx, dom_next and dom_refs */
282 dp->dom_family = odp->dom_family;
283 dp->dom_flags = (odp->dom_flags & DOMF_USERFLAGS) | DOM_OLD;
284 dp->dom_name = odp->dom_name;
285 dp->dom_init = dom_init_old;
286 dp->dom_externalize = odp->dom_externalize;
287 dp->dom_dispose = odp->dom_dispose;
288 dp->dom_rtattach = odp->dom_rtattach;
289 dp->dom_rtoffset = odp->dom_rtoffset;
290 dp->dom_maxrtkey = odp->dom_maxrtkey;
291 dp->dom_protohdrlen = odp->dom_protohdrlen;
292 dp->dom_old = odp;
293
294 attach_domain(dp);
295 init_domain(dp);
296
297 /* Point the mutex back to the internal structure's */
298 odp->dom_mtx = dp->dom_mtx;
299 domain_guard_release(guard);
300 }
301
302 /*
303 * Exported (private) routine, indirection of net_del_domain.
304 */
305 int
306 net_del_domain_old(struct domain_old *odp)
307 {
308 struct domain *dp1, *dp2;
309 int error = 0;
310 domain_guard_t guard;
311
312 VERIFY(odp != NULL);
313
314 guard = domain_guard_deploy();
315 if (odp->dom_refs != 0) {
316 error = EBUSY;
317 goto done;
318 }
319
320 TAILQ_FOREACH_SAFE(dp1, &domains, dom_entry, dp2) {
321 if (!(dp1->dom_flags & DOM_OLD))
322 continue;
323 VERIFY(dp1->dom_old != NULL);
324 if (odp == dp1->dom_old)
325 break;
326 }
327 if (dp1 != NULL) {
328 struct protosw *pp1, *pp2;
329
330 VERIFY(dp1->dom_flags & DOM_OLD);
331 VERIFY(dp1->dom_old == odp);
332
333 /* Remove all protocols attached to this domain */
334 TAILQ_FOREACH_SAFE(pp1, &dp1->dom_protosw, pr_entry, pp2) {
335 detach_proto(pp1, dp1);
336 if (pp1->pr_usrreqs->pru_flags & PRUF_OLD)
337 FREE(pp1->pr_usrreqs, M_TEMP);
338 if (pp1->pr_flags & PR_OLD)
339 FREE(pp1, M_TEMP);
340 }
341
342 detach_domain(dp1);
343 FREE(dp1, M_TEMP);
344 } else {
345 error = EPFNOSUPPORT;
346 }
347 done:
348 domain_guard_release(guard);
349 return (error);
350 }
351
352 /*
353 * Internal routine, not exported.
354 *
355 * net_add_proto - link a protosw into a domain's protosw chain
356 *
357 * NOTE: Caller must have acquired domain_proto_mtx
358 */
359 int
360 net_add_proto(struct protosw *pp, struct domain *dp, int doinit)
361 {
362 struct protosw *pp1;
363
364 /*
365 * This could be called as part of initializing the domain,
366 * and thus DOM_INITIALIZED may not be set (yet).
367 */
368 domain_proto_mtx_lock_assert_held();
369 VERIFY(!(pp->pr_flags & PR_ATTACHED));
370
371 /* pr_domain is set only after the protocol is attached */
372 if (pp->pr_domain != NULL) {
373 panic("%s: domain (%d,%s), proto %d has non-NULL pr_domain!\n",
374 __func__, dp->dom_family, dp->dom_name, pp->pr_protocol);
375 /* NOTREACHED */
376 }
377
378 if (pp->pr_usrreqs == NULL) {
379 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
380 __func__, dp->dom_family, dp->dom_name, pp->pr_protocol);
381 /* NOTREACHED */
382 }
383
384 TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) {
385 if (pp1->pr_type == pp->pr_type &&
386 pp1->pr_protocol == pp->pr_protocol)
387 return (EEXIST);
388 }
389
390 attach_proto(pp, dp);
391 if (doinit)
392 net_init_proto(pp, dp);
393
394 return (0);
395 }
396
397 void
398 net_init_proto(struct protosw *pp, struct domain *dp)
399 {
400 /*
401 * This could be called as part of initializing the domain,
402 * and thus DOM_INITIALIZED may not be set (yet). The protocol
403 * must have been attached via net_addr_protosw() by now.
404 */
405 domain_proto_mtx_lock_assert_held();
406 VERIFY(pp->pr_flags & PR_ATTACHED);
407
408 init_proto(pp, dp);
409 }
410
411 /*
412 * Exported (private) routine, indirection of net_add_proto.
413 */
414 int
415 net_add_proto_old(struct protosw_old *opp, struct domain_old *odp)
416 {
417 struct pr_usrreqs_old *opru;
418 struct pr_usrreqs *pru = NULL;
419 struct protosw *pp = NULL, *pp1;
420 int error = 0;
421 struct domain *dp;
422 domain_guard_t guard;
423
424 /*
425 * This could be called as part of initializing the domain,
426 * and thus DOM_INITIALIZED may not be set (yet).
427 */
428 guard = domain_guard_deploy();
429
430 /* Make sure the domain has been added via net_add_domain */
431 TAILQ_FOREACH(dp, &domains, dom_entry) {
432 if (!(dp->dom_flags & DOM_OLD))
433 continue;
434 if (dp->dom_old == odp)
435 break;
436 }
437 if (dp == NULL) {
438 error = EINVAL;
439 goto done;
440 }
441
442 TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) {
443 if (pp1->pr_type == opp->pr_type &&
444 pp1->pr_protocol == opp->pr_protocol) {
445 error = EEXIST;
446 goto done;
447 }
448 }
449
450 if ((opru = opp->pr_usrreqs) == NULL) {
451 panic("%s: domain (%d,%s), proto %d has no usrreqs!\n",
452 __func__, odp->dom_family, odp->dom_name, opp->pr_protocol);
453 /* NOTREACHED */
454 }
455
456 pru = _MALLOC(sizeof (*pru), M_TEMP, M_WAITOK | M_ZERO);
457 if (pru == NULL) {
458 error = ENOMEM;
459 goto done;
460 }
461
462 pru->pru_flags = PRUF_OLD;
463 pru->pru_abort = opru->pru_abort;
464 pru->pru_accept = opru->pru_accept;
465 pru->pru_attach = opru->pru_attach;
466 pru->pru_bind = opru->pru_bind;
467 pru->pru_connect = opru->pru_connect;
468 pru->pru_connect2 = opru->pru_connect2;
469 pru->pru_control = opru->pru_control;
470 pru->pru_detach = opru->pru_detach;
471 pru->pru_disconnect = opru->pru_disconnect;
472 pru->pru_listen = opru->pru_listen;
473 pru->pru_peeraddr = opru->pru_peeraddr;
474 pru->pru_rcvd = opru->pru_rcvd;
475 pru->pru_rcvoob = opru->pru_rcvoob;
476 pru->pru_send = opru->pru_send;
477 pru->pru_sense = opru->pru_sense;
478 pru->pru_shutdown = opru->pru_shutdown;
479 pru->pru_sockaddr = opru->pru_sockaddr;
480 pru->pru_sosend = opru->pru_sosend;
481 pru->pru_soreceive = opru->pru_soreceive;
482 pru->pru_sopoll = opru->pru_sopoll;
483
484 pp = _MALLOC(sizeof (*pp), M_TEMP, M_WAITOK | M_ZERO);
485 if (pp == NULL) {
486 error = ENOMEM;
487 goto done;
488 }
489
490 /*
491 * Protocol fast and slow timers are now deprecated.
492 */
493 if (opp->pr_unused != NULL) {
494 printf("%s: domain (%d,%s), proto %d: pr_fasttimo is "
495 "deprecated and won't be called\n", __func__,
496 odp->dom_family, odp->dom_name, opp->pr_protocol);
497 }
498 if (opp->pr_unused2 != NULL) {
499 printf("%s: domain (%d,%s), proto %d: pr_slowtimo is "
500 "deprecated and won't be called\n", __func__,
501 odp->dom_family, odp->dom_name, opp->pr_protocol);
502 }
503
504 /* Copy everything but pr_init, pr_next, pr_domain, pr_protosw */
505 pp->pr_type = opp->pr_type;
506 pp->pr_protocol = opp->pr_protocol;
507 pp->pr_flags = (opp->pr_flags & PRF_USERFLAGS) | PR_OLD;
508 pp->pr_input = opp->pr_input;
509 pp->pr_output = opp->pr_output;
510 pp->pr_ctlinput = opp->pr_ctlinput;
511 pp->pr_ctloutput = opp->pr_ctloutput;
512 pp->pr_usrreqs = pru;
513 pp->pr_init = pr_init_old;
514 pp->pr_drain = opp->pr_drain;
515 pp->pr_sysctl = opp->pr_sysctl;
516 pp->pr_lock = opp->pr_lock;
517 pp->pr_unlock = opp->pr_unlock;
518 pp->pr_getlock = opp->pr_getlock;
519 pp->pr_old = opp;
520
521 /* attach as well as initialize */
522 attach_proto(pp, dp);
523 net_init_proto(pp, dp);
524 done:
525 if (error != 0) {
526 printf("%s: domain (%d,%s), proto %d: failed to attach, "
527 "error %d\n", __func__, odp->dom_family,
528 odp->dom_name, opp->pr_protocol, error);
529
530 if (pru != NULL)
531 FREE(pru, M_TEMP);
532 if (pp != NULL)
533 FREE(pp, M_TEMP);
534 }
535
536 domain_guard_release(guard);
537 return (error);
538 }
539
540 /*
541 * Internal routine, not exported.
542 *
543 * net_del_proto - remove a protosw from a domain's protosw chain.
544 * Search the protosw chain for the element with matching data.
545 * Then unlink and return.
546 *
547 * NOTE: Caller must have acquired domain_proto_mtx
548 */
549 int
550 net_del_proto(int type, int protocol, struct domain *dp)
551 {
552 struct protosw *pp;
553
554 /*
555 * This could be called as part of initializing the domain,
556 * and thus DOM_INITIALIZED may not be set (yet).
557 */
558 domain_proto_mtx_lock_assert_held();
559
560 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
561 if (pp->pr_type == type && pp->pr_protocol == protocol)
562 break;
563 }
564 if (pp == NULL)
565 return (ENXIO);
566
567 detach_proto(pp, dp);
568 if (pp->pr_usrreqs->pru_flags & PRUF_OLD)
569 FREE(pp->pr_usrreqs, M_TEMP);
570 if (pp->pr_flags & PR_OLD)
571 FREE(pp, M_TEMP);
572
573 return (0);
574 }
575
576 /*
577 * Exported (private) routine, indirection of net_del_proto.
578 */
579 int
580 net_del_proto_old(int type, int protocol, struct domain_old *odp)
581 {
582 int error = 0;
583 struct protosw *pp;
584 struct domain *dp;
585 domain_guard_t guard;
586
587 /*
588 * This could be called as part of initializing the domain,
589 * and thus DOM_INITIALIZED may not be set (yet).
590 */
591 guard = domain_guard_deploy();
592
593 /* Make sure the domain has been added via net_add_domain */
594 TAILQ_FOREACH(dp, &domains, dom_entry) {
595 if (!(dp->dom_flags & DOM_OLD))
596 continue;
597 if (dp->dom_old == odp)
598 break;
599 }
600 if (dp == NULL) {
601 error = ENXIO;
602 goto done;
603 }
604
605 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
606 if (pp->pr_type == type && pp->pr_protocol == protocol)
607 break;
608 }
609 if (pp == NULL) {
610 error = ENXIO;
611 goto done;
612 }
613 detach_proto(pp, dp);
614 if (pp->pr_usrreqs->pru_flags & PRUF_OLD)
615 FREE(pp->pr_usrreqs, M_TEMP);
616 if (pp->pr_flags & PR_OLD)
617 FREE(pp, M_TEMP);
618
619 done:
620 domain_guard_release(guard);
621 return (error);
622 }
623
624 static void
625 domain_sched_timeout(void)
626 {
627 lck_mtx_assert(&domain_timeout_mtx, LCK_MTX_ASSERT_OWNED);
628
629 if (!domain_timeout_run && domain_draining) {
630 domain_timeout_run = TRUE;
631 timeout(domain_timeout, NULL, hz);
632 }
633 }
634
635 void
636 net_drain_domains(void)
637 {
638 lck_mtx_lock(&domain_timeout_mtx);
639 domain_draining = TRUE;
640 domain_sched_timeout();
641 lck_mtx_unlock(&domain_timeout_mtx);
642 }
643
644 #if INET6
645 extern struct domain inet6domain_s;
646 #endif
647 #if IPSEC
648 extern struct domain keydomain_s;
649 #endif
650
651 extern struct domain routedomain_s, ndrvdomain_s, inetdomain_s;
652 extern struct domain systemdomain_s, localdomain_s;
653
654 #if MULTIPATH
655 extern struct domain mpdomain_s;
656 #endif /* MULTIPATH */
657
658 static void
659 domain_timeout(void *arg)
660 {
661 #pragma unused(arg)
662 struct protosw *pp;
663 struct domain *dp;
664 domain_guard_t guard;
665
666 lck_mtx_lock(&domain_timeout_mtx);
667 if (domain_draining) {
668 domain_draining = FALSE;
669 lck_mtx_unlock(&domain_timeout_mtx);
670
671 guard = domain_guard_deploy();
672 TAILQ_FOREACH(dp, &domains, dom_entry) {
673 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
674 if (pp->pr_drain != NULL)
675 (*pp->pr_drain)();
676 }
677 }
678 domain_guard_release(guard);
679
680 lck_mtx_lock(&domain_timeout_mtx);
681 }
682
683 /* re-arm the timer if there's work to do */
684 domain_timeout_run = FALSE;
685 domain_sched_timeout();
686 lck_mtx_unlock(&domain_timeout_mtx);
687 }
688
689 void
690 domaininit(void)
691 {
692 struct domain *dp;
693 domain_guard_t guard;
694
695 /*
696 * allocate lock group attribute and group for domain mutexes
697 */
698 domain_proto_mtx_grp_attr = lck_grp_attr_alloc_init();
699
700 domain_proto_mtx_grp = lck_grp_alloc_init("domain",
701 domain_proto_mtx_grp_attr);
702
703 /*
704 * allocate the lock attribute for per domain mutexes
705 */
706 domain_proto_mtx_attr = lck_attr_alloc_init();
707
708 lck_mtx_init(&domain_proto_mtx, domain_proto_mtx_grp,
709 domain_proto_mtx_attr);
710 lck_mtx_init(&domain_timeout_mtx, domain_proto_mtx_grp,
711 domain_proto_mtx_attr);
712
713 guard = domain_guard_deploy();
714 /*
715 * Add all the static domains to the domains list. route domain
716 * gets added and initialized last, since we need it to attach
717 * rt_tables[] to everything that's already there. This also
718 * means that domains added after this point won't get their
719 * dom_rtattach() called on rt_tables[].
720 */
721 attach_domain(&inetdomain_s);
722 #if INET6
723 attach_domain(&inet6domain_s);
724 #endif /* INET6 */
725 #if MULTIPATH
726 attach_domain(&mpdomain_s);
727 #endif /* MULTIPATH */
728 attach_domain(&systemdomain_s);
729 attach_domain(&localdomain_s);
730 #if IPSEC
731 attach_domain(&keydomain_s);
732 #endif /* IPSEC */
733 attach_domain(&ndrvdomain_s);
734 attach_domain(&routedomain_s); /* must be last domain */
735
736 /*
737 * Now ask them all to init (XXX including the routing domain,
738 * see above)
739 */
740 TAILQ_FOREACH(dp, &domains, dom_entry)
741 init_domain(dp);
742
743 domain_guard_release(guard);
744 }
745
746 static __inline__ struct domain *
747 pffinddomain_locked(int pf)
748 {
749 struct domain *dp;
750
751 domain_proto_mtx_lock_assert_held();
752
753 TAILQ_FOREACH(dp, &domains, dom_entry) {
754 if (dp->dom_family == pf)
755 break;
756 }
757 return (dp);
758 }
759
760 struct protosw *
761 pffindtype(int family, int type)
762 {
763 struct protosw *pp = NULL;
764 struct domain *dp;
765 domain_guard_t guard;
766
767 guard = domain_guard_deploy();
768 if ((dp = pffinddomain_locked(family)) == NULL)
769 goto done;
770
771 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
772 if (pp->pr_type != 0 && pp->pr_type == type)
773 goto done;
774 }
775 done:
776 domain_guard_release(guard);
777 return (pp);
778 }
779
780 /*
781 * Internal routine, not exported.
782 */
783 struct domain *
784 pffinddomain(int pf)
785 {
786 struct domain *dp;
787 domain_guard_t guard;
788
789 guard = domain_guard_deploy();
790 dp = pffinddomain_locked(pf);
791 domain_guard_release(guard);
792 return (dp);
793 }
794
795 /*
796 * Exported (private) routine, indirection of pffinddomain.
797 */
798 struct domain_old *
799 pffinddomain_old(int pf)
800 {
801 struct domain_old *odp = NULL;
802 struct domain *dp;
803 domain_guard_t guard;
804
805 guard = domain_guard_deploy();
806 if ((dp = pffinddomain_locked(pf)) != NULL && (dp->dom_flags & DOM_OLD))
807 odp = dp->dom_old;
808 domain_guard_release(guard);
809 return (odp);
810 }
811
812 /*
813 * Internal routine, not exported.
814 */
815 struct protosw *
816 pffindproto(int family, int protocol, int type)
817 {
818 struct protosw *pp;
819 domain_guard_t guard;
820
821 guard = domain_guard_deploy();
822 pp = pffindproto_locked(family, protocol, type);
823 domain_guard_release(guard);
824 return (pp);
825 }
826
827 struct protosw *
828 pffindproto_locked(int family, int protocol, int type)
829 {
830 struct protosw *maybe = NULL;
831 struct protosw *pp;
832 struct domain *dp;
833
834 domain_proto_mtx_lock_assert_held();
835
836 if (family == 0)
837 return (0);
838
839 dp = pffinddomain_locked(family);
840 if (dp == NULL)
841 return (NULL);
842
843 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
844 if ((pp->pr_protocol == protocol) && (pp->pr_type == type))
845 return (pp);
846
847 if (type == SOCK_RAW && pp->pr_type == SOCK_RAW &&
848 pp->pr_protocol == 0 && maybe == NULL)
849 maybe = pp;
850 }
851 return (maybe);
852 }
853
854 /*
855 * Exported (private) routine, indirection of pffindproto.
856 */
857 struct protosw_old *
858 pffindproto_old(int family, int protocol, int type)
859 {
860 struct protosw_old *opr = NULL;
861 struct protosw *pp;
862 domain_guard_t guard;
863
864 guard = domain_guard_deploy();
865 if ((pp = pffindproto_locked(family, protocol, type)) != NULL &&
866 (pp->pr_flags & PR_OLD))
867 opr = pp->pr_old;
868 domain_guard_release(guard);
869 return (opr);
870 }
871
872 static struct protosw *
873 pffindprotonotype_locked(int family, int protocol, int type)
874 {
875 #pragma unused(type)
876 struct domain *dp;
877 struct protosw *pp;
878
879 domain_proto_mtx_lock_assert_held();
880
881 if (family == 0)
882 return (0);
883
884 dp = pffinddomain_locked(family);
885 if (dp == NULL)
886 return (NULL);
887
888 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
889 if (pp->pr_protocol == protocol)
890 return (pp);
891 }
892 return (NULL);
893 }
894
895 struct protosw *
896 pffindprotonotype(int family, int protocol)
897 {
898 struct protosw *pp;
899 domain_guard_t guard;
900
901 if (protocol == 0)
902 return (NULL);
903
904 guard = domain_guard_deploy();
905 pp = pffindprotonotype_locked(family, protocol, 0);
906 domain_guard_release(guard);
907 return (pp);
908 }
909
910 void
911 pfctlinput(int cmd, struct sockaddr *sa)
912 {
913 pfctlinput2(cmd, sa, NULL);
914 }
915
916 void
917 pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam)
918 {
919 struct domain *dp;
920 struct protosw *pp;
921 domain_guard_t guard;
922
923 if (sa == NULL)
924 return;
925
926 guard = domain_guard_deploy();
927 TAILQ_FOREACH(dp, &domains, dom_entry) {
928 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
929 if (pp->pr_ctlinput != NULL)
930 (*pp->pr_ctlinput)(cmd, sa, ctlparam);
931 }
932 }
933 domain_guard_release(guard);
934 }
935
936 void
937 net_update_uptime(void)
938 {
939 struct timeval tv;
940
941 microuptime(&tv);
942 _net_uptime = tv.tv_sec;
943 /*
944 * Round up the timer to the nearest integer value because otherwise
945 * we might setup networking timers that are off by almost 1 second.
946 */
947 if (tv.tv_usec > 500000)
948 _net_uptime++;
949 }
950
951 void
952 net_update_uptime_secs(uint64_t secs)
953 {
954 _net_uptime = secs;
955 }
956
957 /*
958 * Convert our uin64_t net_uptime to a struct timeval.
959 */
960 void
961 net_uptime2timeval(struct timeval *tv)
962 {
963 if (tv == NULL)
964 return;
965
966 tv->tv_usec = 0;
967 tv->tv_sec = net_uptime();
968 }
969
970 /*
971 * An alternative way to obtain the coarse-grained uptime (in seconds)
972 * for networking code which do not require high-precision timestamp,
973 * as this is significantly cheaper than microuptime().
974 */
975 u_int64_t
976 net_uptime(void)
977 {
978 if (_net_uptime == 0)
979 net_update_uptime();
980
981 return (_net_uptime);
982 }
983
984 void
985 domain_proto_mtx_lock_assert_held(void)
986 {
987 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
988 }
989
990 void
991 domain_proto_mtx_lock_assert_notheld(void)
992 {
993 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
994 }
995
996 domain_guard_t
997 domain_guard_deploy(void)
998 {
999 net_thread_marks_t marks;
1000
1001 marks = net_thread_marks_push(NET_THREAD_HELD_DOMAIN);
1002 if (marks != net_thread_marks_none) {
1003 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1004 lck_mtx_lock(&domain_proto_mtx);
1005 }
1006 else
1007 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1008
1009 return ((domain_guard_t)(const void*)marks);
1010 }
1011
1012 void
1013 domain_guard_release(domain_guard_t guard)
1014 {
1015 net_thread_marks_t marks = (net_thread_marks_t)(const void*)guard;
1016
1017 if (marks != net_thread_marks_none) {
1018 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1019 lck_mtx_unlock(&domain_proto_mtx);
1020 net_thread_marks_pop(marks);
1021 }
1022 else
1023 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1024 }
1025
1026 domain_unguard_t
1027 domain_unguard_deploy(void)
1028 {
1029 net_thread_marks_t marks;
1030
1031 marks = net_thread_unmarks_push(NET_THREAD_HELD_DOMAIN);
1032 if (marks != net_thread_marks_none) {
1033 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1034 lck_mtx_unlock(&domain_proto_mtx);
1035 }
1036 else
1037 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1038
1039 return ((domain_unguard_t)(const void*)marks);
1040 }
1041
1042 void
1043 domain_unguard_release(domain_unguard_t unguard)
1044 {
1045 net_thread_marks_t marks = (net_thread_marks_t)(const void*)unguard;
1046
1047 if (marks != net_thread_marks_none) {
1048 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1049 lck_mtx_lock(&domain_proto_mtx);
1050 net_thread_unmarks_pop(marks);
1051 }
1052 else
1053 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1054 }