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