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