]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/uipc_domain.c
xnu-2422.1.72.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 extern sysctlfn net_sysctl;
106
107 static u_int64_t _net_uptime;
108
109 static void
110 pr_init_old(struct protosw *pp, struct domain *dp)
111 {
112 #pragma unused(dp)
113 VERIFY(pp->pr_flags & PR_OLD);
114 VERIFY(pp->pr_old != NULL);
115
116 if (pp->pr_old->pr_init != NULL)
117 pp->pr_old->pr_init();
118 }
119
120 static void
121 init_proto(struct protosw *pp, struct domain *dp)
122 {
123 VERIFY(pp->pr_flags & PR_ATTACHED);
124
125 if (!(pp->pr_flags & PR_INITIALIZED)) {
126 TAILQ_INIT(&pp->pr_filter_head);
127 if (pp->pr_init != NULL)
128 pp->pr_init(pp, dp);
129 pp->pr_flags |= PR_INITIALIZED;
130 }
131 }
132
133 static void
134 attach_proto(struct protosw *pp, struct domain *dp)
135 {
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);
140
141 TAILQ_INSERT_TAIL(&dp->dom_protosw, pp, pr_entry);
142 pp->pr_flags |= PR_ATTACHED;
143 pp->pr_domain = dp;
144 pp->pr_protosw = pp;
145
146 /* do some cleaning up on user request callbacks */
147 pru_sanitize(pp->pr_usrreqs);
148 }
149
150 static void
151 detach_proto(struct protosw *pp, struct domain *dp)
152 {
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);
157
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;
162 }
163
164 static void
165 dom_init_old(struct domain *dp)
166 {
167 VERIFY(dp->dom_flags & DOM_OLD);
168 VERIFY(dp->dom_old != NULL);
169
170 if (dp->dom_old->dom_init != NULL)
171 dp->dom_old->dom_init();
172 }
173
174 static void
175 init_domain(struct domain *dp)
176 {
177 VERIFY(dp->dom_flags & DOM_ATTACHED);
178
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)
185 dp->dom_init(dp);
186 dp->dom_flags |= DOM_INITIALIZED;
187 }
188
189 /* Recompute for new protocol */
190 if (_max_linkhdr < 16) /* XXX - Sheesh; everything's ether? */
191 _max_linkhdr = 16;
192 _max_linkhdr = max_linkhdr; /* round it up */
193
194 if (dp->dom_protohdrlen > _max_protohdr)
195 _max_protohdr = dp->dom_protohdrlen;
196 _max_protohdr = max_protohdr; /* round it up */
197
198 max_hdr = max_linkhdr + max_protohdr;
199 max_datalen = MHLEN - max_hdr;
200 }
201
202 static void
203 attach_domain(struct domain *dp)
204 {
205 domain_proto_mtx_lock_assert_held();
206 VERIFY(!(dp->dom_flags & DOM_ATTACHED));
207
208 TAILQ_INSERT_TAIL(&domains, dp, dom_entry);
209 dp->dom_flags |= DOM_ATTACHED;
210 }
211
212 static void
213 detach_domain(struct domain *dp)
214 {
215 domain_proto_mtx_lock_assert_held();
216 VERIFY(dp->dom_flags & DOM_ATTACHED);
217
218 TAILQ_REMOVE(&domains, dp, dom_entry);
219 dp->dom_flags &= ~DOM_ATTACHED;
220
221 if (dp->dom_flags & DOM_OLD) {
222 struct domain_old *odp = dp->dom_old;
223
224 VERIFY(odp != NULL);
225 odp->dom_next = NULL;
226 odp->dom_mtx = NULL;
227 }
228 }
229
230 /*
231 * Exported (private) routine, indirection of net_add_domain.
232 */
233 void
234 net_add_domain_old(struct domain_old *odp)
235 {
236 struct domain *dp;
237 domain_guard_t guard;
238
239 VERIFY(odp != NULL);
240
241 guard = domain_guard_deploy();
242 if ((dp = pffinddomain_locked(odp->dom_family)) != NULL) {
243 /*
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.
247 */
248 panic("%s: domain (%d,%s) already exists for %s\n", __func__,
249 dp->dom_family, dp->dom_name, odp->dom_name);
250 /* NOTREACHED */
251 }
252
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);
260 /* NOTREACHED */
261 }
262 }
263
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,
267 odp->dom_name);
268 /* NOTREACHED */
269 }
270
271 dp = _MALLOC(sizeof (*dp), M_TEMP, M_WAITOK | M_ZERO);
272 if (dp == NULL) {
273 /*
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.
277 */
278 panic("%s: unable to allocate memory for domain family "
279 "%d (%s)\n", __func__, odp->dom_family, odp->dom_name);
280 /* NOTREACHED */
281 }
282
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;
294 dp->dom_old = odp;
295
296 attach_domain(dp);
297 init_domain(dp);
298
299 /* Point the mutex back to the internal structure's */
300 odp->dom_mtx = dp->dom_mtx;
301 domain_guard_release(guard);
302 }
303
304 /*
305 * Exported (private) routine, indirection of net_del_domain.
306 */
307 int
308 net_del_domain_old(struct domain_old *odp)
309 {
310 struct domain *dp1, *dp2;
311 int error = 0;
312 domain_guard_t guard;
313
314 VERIFY(odp != NULL);
315
316 guard = domain_guard_deploy();
317 if (odp->dom_refs != 0) {
318 error = EBUSY;
319 goto done;
320 }
321
322 TAILQ_FOREACH_SAFE(dp1, &domains, dom_entry, dp2) {
323 if (!(dp1->dom_flags & DOM_OLD))
324 continue;
325 VERIFY(dp1->dom_old != NULL);
326 if (odp == dp1->dom_old)
327 break;
328 }
329 if (dp1 != NULL) {
330 struct protosw *pp1, *pp2;
331
332 VERIFY(dp1->dom_flags & DOM_OLD);
333 VERIFY(dp1->dom_old == odp);
334
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)
341 FREE(pp1, M_TEMP);
342 }
343
344 detach_domain(dp1);
345 FREE(dp1, M_TEMP);
346 } else {
347 error = EPFNOSUPPORT;
348 }
349 done:
350 domain_guard_release(guard);
351 return (error);
352 }
353
354 /*
355 * Internal routine, not exported.
356 *
357 * net_add_proto - link a protosw into a domain's protosw chain
358 *
359 * NOTE: Caller must have acquired domain_proto_mtx
360 */
361 int
362 net_add_proto(struct protosw *pp, struct domain *dp, int doinit)
363 {
364 struct protosw *pp1;
365
366 /*
367 * This could be called as part of initializing the domain,
368 * and thus DOM_INITIALIZED may not be set (yet).
369 */
370 domain_proto_mtx_lock_assert_held();
371 VERIFY(!(pp->pr_flags & PR_ATTACHED));
372
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);
377 /* NOTREACHED */
378 }
379
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);
383 /* NOTREACHED */
384 }
385
386 TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) {
387 if (pp1->pr_type == pp->pr_type &&
388 pp1->pr_protocol == pp->pr_protocol)
389 return (EEXIST);
390 }
391
392 attach_proto(pp, dp);
393 if (doinit)
394 net_init_proto(pp, dp);
395
396 return (0);
397 }
398
399 void
400 net_init_proto(struct protosw *pp, struct domain *dp)
401 {
402 /*
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.
406 */
407 domain_proto_mtx_lock_assert_held();
408 VERIFY(pp->pr_flags & PR_ATTACHED);
409
410 init_proto(pp, dp);
411 }
412
413 /*
414 * Exported (private) routine, indirection of net_add_proto.
415 */
416 int
417 net_add_proto_old(struct protosw_old *opp, struct domain_old *odp)
418 {
419 struct pr_usrreqs_old *opru;
420 struct pr_usrreqs *pru = NULL;
421 struct protosw *pp = NULL, *pp1;
422 int error = 0;
423 struct domain *dp;
424 domain_guard_t guard;
425
426 /*
427 * This could be called as part of initializing the domain,
428 * and thus DOM_INITIALIZED may not be set (yet).
429 */
430 guard = domain_guard_deploy();
431
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))
435 continue;
436 if (dp->dom_old == odp)
437 break;
438 }
439 if (dp == NULL) {
440 error = EINVAL;
441 goto done;
442 }
443
444 TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) {
445 if (pp1->pr_type == opp->pr_type &&
446 pp1->pr_protocol == opp->pr_protocol) {
447 error = EEXIST;
448 goto done;
449 }
450 }
451
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);
455 /* NOTREACHED */
456 }
457
458 pru = _MALLOC(sizeof (*pru), M_TEMP, M_WAITOK | M_ZERO);
459 if (pru == NULL) {
460 error = ENOMEM;
461 goto done;
462 }
463
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;
485
486 pp = _MALLOC(sizeof (*pp), M_TEMP, M_WAITOK | M_ZERO);
487 if (pp == NULL) {
488 error = ENOMEM;
489 goto done;
490 }
491
492 /*
493 * Protocol fast and slow timers are now deprecated.
494 */
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);
499 }
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);
504 }
505
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;
521 pp->pr_old = opp;
522
523 /* attach as well as initialize */
524 attach_proto(pp, dp);
525 net_init_proto(pp, dp);
526 done:
527 if (error != 0) {
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);
531
532 if (pru != NULL)
533 FREE(pru, M_TEMP);
534 if (pp != NULL)
535 FREE(pp, M_TEMP);
536 }
537
538 domain_guard_release(guard);
539 return (error);
540 }
541
542 /*
543 * Internal routine, not exported.
544 *
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.
548 *
549 * NOTE: Caller must have acquired domain_proto_mtx
550 */
551 int
552 net_del_proto(int type, int protocol, struct domain *dp)
553 {
554 struct protosw *pp;
555
556 /*
557 * This could be called as part of initializing the domain,
558 * and thus DOM_INITIALIZED may not be set (yet).
559 */
560 domain_proto_mtx_lock_assert_held();
561
562 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
563 if (pp->pr_type == type && pp->pr_protocol == protocol)
564 break;
565 }
566 if (pp == NULL)
567 return (ENXIO);
568
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)
573 FREE(pp, M_TEMP);
574
575 return (0);
576 }
577
578 /*
579 * Exported (private) routine, indirection of net_del_proto.
580 */
581 int
582 net_del_proto_old(int type, int protocol, struct domain_old *odp)
583 {
584 int error = 0;
585 struct protosw *pp;
586 struct domain *dp;
587 domain_guard_t guard;
588
589 /*
590 * This could be called as part of initializing the domain,
591 * and thus DOM_INITIALIZED may not be set (yet).
592 */
593 guard = domain_guard_deploy();
594
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))
598 continue;
599 if (dp->dom_old == odp)
600 break;
601 }
602 if (dp == NULL) {
603 error = ENXIO;
604 goto done;
605 }
606
607 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
608 if (pp->pr_type == type && pp->pr_protocol == protocol)
609 break;
610 }
611 if (pp == NULL) {
612 error = ENXIO;
613 goto done;
614 }
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)
619 FREE(pp, M_TEMP);
620
621 done:
622 domain_guard_release(guard);
623 return (error);
624 }
625
626 static void
627 domain_sched_timeout(void)
628 {
629 lck_mtx_assert(&domain_timeout_mtx, LCK_MTX_ASSERT_OWNED);
630
631 if (!domain_timeout_run && domain_draining) {
632 domain_timeout_run = TRUE;
633 timeout(domain_timeout, NULL, hz);
634 }
635 }
636
637 void
638 net_drain_domains(void)
639 {
640 lck_mtx_lock(&domain_timeout_mtx);
641 domain_draining = TRUE;
642 domain_sched_timeout();
643 lck_mtx_unlock(&domain_timeout_mtx);
644 }
645
646 #if INET6
647 extern struct domain inet6domain_s;
648 #endif
649 #if IPSEC
650 extern struct domain keydomain_s;
651 #endif
652
653 extern struct domain routedomain_s, ndrvdomain_s, inetdomain_s;
654 extern struct domain systemdomain_s, localdomain_s;
655
656 #if MULTIPATH
657 extern struct domain mpdomain_s;
658 #endif /* MULTIPATH */
659
660 static void
661 domain_timeout(void *arg)
662 {
663 #pragma unused(arg)
664 struct protosw *pp;
665 struct domain *dp;
666 domain_guard_t guard;
667
668 lck_mtx_lock(&domain_timeout_mtx);
669 if (domain_draining) {
670 domain_draining = FALSE;
671 lck_mtx_unlock(&domain_timeout_mtx);
672
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)
677 (*pp->pr_drain)();
678 }
679 }
680 domain_guard_release(guard);
681
682 lck_mtx_lock(&domain_timeout_mtx);
683 }
684
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);
689 }
690
691 void
692 domaininit(void)
693 {
694 struct domain *dp;
695 domain_guard_t guard;
696
697 /*
698 * allocate lock group attribute and group for domain mutexes
699 */
700 domain_proto_mtx_grp_attr = lck_grp_attr_alloc_init();
701
702 domain_proto_mtx_grp = lck_grp_alloc_init("domain",
703 domain_proto_mtx_grp_attr);
704
705 /*
706 * allocate the lock attribute for per domain mutexes
707 */
708 domain_proto_mtx_attr = lck_attr_alloc_init();
709
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);
714
715 guard = domain_guard_deploy();
716 /*
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[].
722 */
723 attach_domain(&inetdomain_s);
724 #if INET6
725 attach_domain(&inet6domain_s);
726 #endif /* INET6 */
727 #if MULTIPATH
728 attach_domain(&mpdomain_s);
729 #endif /* MULTIPATH */
730 attach_domain(&systemdomain_s);
731 attach_domain(&localdomain_s);
732 #if IPSEC
733 attach_domain(&keydomain_s);
734 #endif /* IPSEC */
735 attach_domain(&ndrvdomain_s);
736 attach_domain(&routedomain_s); /* must be last domain */
737
738 /*
739 * Now ask them all to init (XXX including the routing domain,
740 * see above)
741 */
742 TAILQ_FOREACH(dp, &domains, dom_entry)
743 init_domain(dp);
744
745 domain_guard_release(guard);
746 }
747
748 static __inline__ struct domain *
749 pffinddomain_locked(int pf)
750 {
751 struct domain *dp;
752
753 domain_proto_mtx_lock_assert_held();
754
755 TAILQ_FOREACH(dp, &domains, dom_entry) {
756 if (dp->dom_family == pf)
757 break;
758 }
759 return (dp);
760 }
761
762 struct protosw *
763 pffindtype(int family, int type)
764 {
765 struct protosw *pp = NULL;
766 struct domain *dp;
767 domain_guard_t guard;
768
769 guard = domain_guard_deploy();
770 if ((dp = pffinddomain_locked(family)) == NULL)
771 goto done;
772
773 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
774 if (pp->pr_type != 0 && pp->pr_type == type)
775 goto done;
776 }
777 done:
778 domain_guard_release(guard);
779 return (pp);
780 }
781
782 /*
783 * Internal routine, not exported.
784 */
785 struct domain *
786 pffinddomain(int pf)
787 {
788 struct domain *dp;
789 domain_guard_t guard;
790
791 guard = domain_guard_deploy();
792 dp = pffinddomain_locked(pf);
793 domain_guard_release(guard);
794 return (dp);
795 }
796
797 /*
798 * Exported (private) routine, indirection of pffinddomain.
799 */
800 struct domain_old *
801 pffinddomain_old(int pf)
802 {
803 struct domain_old *odp = NULL;
804 struct domain *dp;
805 domain_guard_t guard;
806
807 guard = domain_guard_deploy();
808 if ((dp = pffinddomain_locked(pf)) != NULL && (dp->dom_flags & DOM_OLD))
809 odp = dp->dom_old;
810 domain_guard_release(guard);
811 return (odp);
812 }
813
814 /*
815 * Internal routine, not exported.
816 */
817 struct protosw *
818 pffindproto(int family, int protocol, int type)
819 {
820 struct protosw *pp;
821 domain_guard_t guard;
822
823 guard = domain_guard_deploy();
824 pp = pffindproto_locked(family, protocol, type);
825 domain_guard_release(guard);
826 return (pp);
827 }
828
829 struct protosw *
830 pffindproto_locked(int family, int protocol, int type)
831 {
832 struct protosw *maybe = NULL;
833 struct protosw *pp;
834 struct domain *dp;
835
836 domain_proto_mtx_lock_assert_held();
837
838 if (family == 0)
839 return (0);
840
841 dp = pffinddomain_locked(family);
842 if (dp == NULL)
843 return (NULL);
844
845 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
846 if ((pp->pr_protocol == protocol) && (pp->pr_type == type))
847 return (pp);
848
849 if (type == SOCK_RAW && pp->pr_type == SOCK_RAW &&
850 pp->pr_protocol == 0 && maybe == NULL)
851 maybe = pp;
852 }
853 return (maybe);
854 }
855
856 /*
857 * Exported (private) routine, indirection of pffindproto.
858 */
859 struct protosw_old *
860 pffindproto_old(int family, int protocol, int type)
861 {
862 struct protosw_old *opr = NULL;
863 struct protosw *pp;
864 domain_guard_t guard;
865
866 guard = domain_guard_deploy();
867 if ((pp = pffindproto_locked(family, protocol, type)) != NULL &&
868 (pp->pr_flags & PR_OLD))
869 opr = pp->pr_old;
870 domain_guard_release(guard);
871 return (opr);
872 }
873
874 static struct protosw *
875 pffindprotonotype_locked(int family, int protocol, int type)
876 {
877 #pragma unused(type)
878 struct domain *dp;
879 struct protosw *pp;
880
881 domain_proto_mtx_lock_assert_held();
882
883 if (family == 0)
884 return (0);
885
886 dp = pffinddomain_locked(family);
887 if (dp == NULL)
888 return (NULL);
889
890 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
891 if (pp->pr_protocol == protocol)
892 return (pp);
893 }
894 return (NULL);
895 }
896
897 struct protosw *
898 pffindprotonotype(int family, int protocol)
899 {
900 struct protosw *pp;
901 domain_guard_t guard;
902
903 if (protocol == 0)
904 return (NULL);
905
906 guard = domain_guard_deploy();
907 pp = pffindprotonotype_locked(family, protocol, 0);
908 domain_guard_release(guard);
909 return (pp);
910 }
911
912 int
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)
915 {
916 #pragma unused(p)
917 int family, protocol, error = 0;
918 struct domain *dp;
919 struct protosw *pp;
920 domain_guard_t guard;
921
922 /*
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.
926 */
927 if (namelen < 3)
928 return (EISDIR); /* overloaded */
929 family = name[0];
930 protocol = name[1];
931
932 if (family == 0)
933 return (0);
934
935 guard = domain_guard_deploy();
936 TAILQ_FOREACH(dp, &domains, dom_entry) {
937 if (dp->dom_family == family)
938 break;
939 }
940 if (dp == NULL) {
941 error = ENOPROTOOPT;
942 goto done;
943 }
944
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);
950 goto done;
951 }
952 }
953 error = ENOPROTOOPT;
954 done:
955 domain_guard_release(guard);
956 return (error);
957 }
958
959 void
960 pfctlinput(int cmd, struct sockaddr *sa)
961 {
962 pfctlinput2(cmd, sa, NULL);
963 }
964
965 void
966 pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam)
967 {
968 struct domain *dp;
969 struct protosw *pp;
970 domain_guard_t guard;
971
972 if (sa == NULL)
973 return;
974
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);
980 }
981 }
982 domain_guard_release(guard);
983 }
984
985 void
986 net_update_uptime(void)
987 {
988 struct timeval tv;
989
990 microuptime(&tv);
991 _net_uptime = tv.tv_sec;
992 /*
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.
995 */
996 if (tv.tv_usec > 500000)
997 _net_uptime++;
998 }
999
1000 void
1001 net_update_uptime_secs(uint64_t secs)
1002 {
1003 _net_uptime = secs;
1004 }
1005
1006 /*
1007 * Convert our uin64_t net_uptime to a struct timeval.
1008 */
1009 void
1010 net_uptime2timeval(struct timeval *tv)
1011 {
1012 if (tv == NULL)
1013 return;
1014
1015 tv->tv_usec = 0;
1016 tv->tv_sec = net_uptime();
1017 }
1018
1019 /*
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().
1023 */
1024 u_int64_t
1025 net_uptime(void)
1026 {
1027 if (_net_uptime == 0)
1028 net_update_uptime();
1029
1030 return (_net_uptime);
1031 }
1032
1033 void
1034 domain_proto_mtx_lock_assert_held(void)
1035 {
1036 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1037 }
1038
1039 void
1040 domain_proto_mtx_lock_assert_notheld(void)
1041 {
1042 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1043 }
1044
1045 domain_guard_t
1046 domain_guard_deploy(void)
1047 {
1048 net_thread_marks_t marks;
1049
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);
1054 }
1055 else
1056 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1057
1058 return ((domain_guard_t)(const void*)marks);
1059 }
1060
1061 void
1062 domain_guard_release(domain_guard_t guard)
1063 {
1064 net_thread_marks_t marks = (net_thread_marks_t)(const void*)guard;
1065
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);
1070 }
1071 else
1072 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1073 }
1074
1075 domain_unguard_t
1076 domain_unguard_deploy(void)
1077 {
1078 net_thread_marks_t marks;
1079
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);
1084 }
1085 else
1086 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1087
1088 return ((domain_unguard_t)(const void*)marks);
1089 }
1090
1091 void
1092 domain_unguard_release(domain_unguard_t unguard)
1093 {
1094 net_thread_marks_t marks = (net_thread_marks_t)(const void*)unguard;
1095
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);
1100 }
1101 else
1102 lck_mtx_assert(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1103 }