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