]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/uipc_domain.c
xnu-6153.121.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 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 #if INET6
688 extern struct domain inet6domain_s;
689 #endif
690 #if IPSEC
691 extern struct domain keydomain_s;
692 #endif
693
694 extern struct domain routedomain_s, ndrvdomain_s, inetdomain_s;
695 extern struct domain systemdomain_s, localdomain_s;
696
697 #if MULTIPATH
698 extern struct domain mpdomain_s;
699 #endif /* MULTIPATH */
700
701 static void
702 domain_timeout(void *arg)
703 {
704 #pragma unused(arg)
705 struct protosw *pp;
706 struct domain *dp;
707 domain_guard_t guard;
708
709 lck_mtx_lock(&domain_timeout_mtx);
710 if (domain_draining) {
711 domain_draining = FALSE;
712 lck_mtx_unlock(&domain_timeout_mtx);
713
714 guard = domain_guard_deploy();
715 TAILQ_FOREACH(dp, &domains, dom_entry) {
716 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
717 if (pp->pr_drain != NULL) {
718 (*pp->pr_drain)();
719 }
720 }
721 }
722 domain_guard_release(guard);
723
724 lck_mtx_lock(&domain_timeout_mtx);
725 }
726
727 /* re-arm the timer if there's work to do */
728 domain_timeout_run = FALSE;
729 domain_sched_timeout();
730 lck_mtx_unlock(&domain_timeout_mtx);
731 }
732
733 void
734 domaininit(void)
735 {
736 struct domain *dp;
737 domain_guard_t guard;
738
739 eventhandler_lists_ctxt_init(&protoctl_evhdlr_ctxt);
740 /*
741 * allocate lock group attribute and group for domain mutexes
742 */
743 domain_proto_mtx_grp_attr = lck_grp_attr_alloc_init();
744
745 domain_proto_mtx_grp = lck_grp_alloc_init("domain",
746 domain_proto_mtx_grp_attr);
747
748 /*
749 * allocate the lock attribute for per domain mutexes
750 */
751 domain_proto_mtx_attr = lck_attr_alloc_init();
752
753 lck_mtx_init(&domain_proto_mtx, domain_proto_mtx_grp,
754 domain_proto_mtx_attr);
755 lck_mtx_init(&domain_timeout_mtx, domain_proto_mtx_grp,
756 domain_proto_mtx_attr);
757
758 guard = domain_guard_deploy();
759 /*
760 * Add all the static domains to the domains list. route domain
761 * gets added and initialized last, since we need it to attach
762 * rt_tables[] to everything that's already there. This also
763 * means that domains added after this point won't get their
764 * dom_rtattach() called on rt_tables[].
765 */
766 attach_domain(&inetdomain_s);
767 #if INET6
768 attach_domain(&inet6domain_s);
769 #endif /* INET6 */
770 #if MULTIPATH
771 attach_domain(&mpdomain_s);
772 #endif /* MULTIPATH */
773 attach_domain(&systemdomain_s);
774 attach_domain(&localdomain_s);
775 #if IPSEC
776 attach_domain(&keydomain_s);
777 #endif /* IPSEC */
778 attach_domain(&ndrvdomain_s);
779 attach_domain(&routedomain_s); /* must be last domain */
780
781 /*
782 * Now ask them all to init (XXX including the routing domain,
783 * see above)
784 */
785 TAILQ_FOREACH(dp, &domains, dom_entry)
786 init_domain(dp);
787
788 domain_guard_release(guard);
789 }
790
791 static __inline__ struct domain *
792 pffinddomain_locked(int pf)
793 {
794 struct domain *dp;
795
796 domain_proto_mtx_lock_assert_held();
797
798 TAILQ_FOREACH(dp, &domains, dom_entry) {
799 if (dp->dom_family == pf) {
800 break;
801 }
802 }
803 return dp;
804 }
805
806 struct protosw *
807 pffindtype(int family, int type)
808 {
809 struct protosw *pp = NULL;
810 struct domain *dp;
811 domain_guard_t guard;
812
813 guard = domain_guard_deploy();
814 if ((dp = pffinddomain_locked(family)) == NULL) {
815 goto done;
816 }
817
818 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
819 if (pp->pr_type != 0 && pp->pr_type == type) {
820 goto done;
821 }
822 }
823 done:
824 domain_guard_release(guard);
825 return pp;
826 }
827
828 /*
829 * Internal routine, not exported.
830 */
831 struct domain *
832 pffinddomain(int pf)
833 {
834 struct domain *dp;
835 domain_guard_t guard;
836
837 guard = domain_guard_deploy();
838 dp = pffinddomain_locked(pf);
839 domain_guard_release(guard);
840 return dp;
841 }
842
843 /*
844 * Exported (private) routine, indirection of pffinddomain.
845 */
846 struct domain_old *
847 pffinddomain_old(int pf)
848 {
849 struct domain_old *odp = NULL;
850 struct domain *dp;
851 domain_guard_t guard;
852
853 guard = domain_guard_deploy();
854 if ((dp = pffinddomain_locked(pf)) != NULL && (dp->dom_flags & DOM_OLD)) {
855 odp = dp->dom_old;
856 }
857 domain_guard_release(guard);
858 return odp;
859 }
860
861 /*
862 * Internal routine, not exported.
863 */
864 struct protosw *
865 pffindproto(int family, int protocol, int type)
866 {
867 struct protosw *pp;
868 domain_guard_t guard;
869
870 guard = domain_guard_deploy();
871 pp = pffindproto_locked(family, protocol, type);
872 domain_guard_release(guard);
873 return pp;
874 }
875
876 struct protosw *
877 pffindproto_locked(int family, int protocol, int type)
878 {
879 struct protosw *maybe = NULL;
880 struct protosw *pp;
881 struct domain *dp;
882
883 domain_proto_mtx_lock_assert_held();
884
885 if (family == 0) {
886 return 0;
887 }
888
889 dp = pffinddomain_locked(family);
890 if (dp == NULL) {
891 return NULL;
892 }
893
894 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
895 if ((pp->pr_protocol == protocol) && (pp->pr_type == type)) {
896 return pp;
897 }
898
899 if (type == SOCK_RAW && pp->pr_type == SOCK_RAW &&
900 pp->pr_protocol == 0 && maybe == NULL) {
901 maybe = pp;
902 }
903 }
904 return maybe;
905 }
906
907 /*
908 * Exported (private) routine, indirection of pffindproto.
909 */
910 struct protosw_old *
911 pffindproto_old(int family, int protocol, int type)
912 {
913 struct protosw_old *opr = NULL;
914 struct protosw *pp;
915 domain_guard_t guard;
916
917 guard = domain_guard_deploy();
918 if ((pp = pffindproto_locked(family, protocol, type)) != NULL &&
919 (pp->pr_flags & PR_OLD)) {
920 opr = pp->pr_old;
921 }
922 domain_guard_release(guard);
923 return opr;
924 }
925
926 static struct protosw *
927 pffindprotonotype_locked(int family, int protocol, int type)
928 {
929 #pragma unused(type)
930 struct domain *dp;
931 struct protosw *pp;
932
933 domain_proto_mtx_lock_assert_held();
934
935 if (family == 0) {
936 return 0;
937 }
938
939 dp = pffinddomain_locked(family);
940 if (dp == NULL) {
941 return NULL;
942 }
943
944 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
945 if (pp->pr_protocol == protocol) {
946 return pp;
947 }
948 }
949 return NULL;
950 }
951
952 struct protosw *
953 pffindprotonotype(int family, int protocol)
954 {
955 struct protosw *pp;
956 domain_guard_t guard;
957
958 if (protocol == 0) {
959 return NULL;
960 }
961
962 guard = domain_guard_deploy();
963 pp = pffindprotonotype_locked(family, protocol, 0);
964 domain_guard_release(guard);
965 return pp;
966 }
967
968 void
969 pfctlinput(int cmd, struct sockaddr *sa)
970 {
971 pfctlinput2(cmd, sa, NULL);
972 }
973
974 void
975 pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam)
976 {
977 struct domain *dp;
978 struct protosw *pp;
979 domain_guard_t guard;
980
981 if (sa == NULL) {
982 return;
983 }
984
985 guard = domain_guard_deploy();
986 TAILQ_FOREACH(dp, &domains, dom_entry) {
987 TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
988 if (pp->pr_ctlinput != NULL) {
989 (*pp->pr_ctlinput)(cmd, sa, ctlparam, NULL);
990 }
991 }
992 }
993 domain_guard_release(guard);
994 }
995
996 void
997 net_update_uptime_with_time(const struct timeval *tvp)
998 {
999 _net_uptime = tvp->tv_sec;
1000 /*
1001 * Round up the timer to the nearest integer value because otherwise
1002 * we might setup networking timers that are off by almost 1 second.
1003 */
1004 if (tvp->tv_usec > 500000) {
1005 _net_uptime++;
1006 }
1007
1008 /* update milliseconds variant */
1009 _net_uptime_ms = (((u_int64_t)tvp->tv_sec * 1000) +
1010 ((u_int64_t)tvp->tv_usec / 1000));
1011 }
1012
1013 void
1014 net_update_uptime(void)
1015 {
1016 struct timeval tv;
1017
1018 microuptime(&tv);
1019
1020 net_update_uptime_with_time(&tv);
1021 }
1022
1023 /*
1024 * Convert our uin64_t net_uptime to a struct timeval.
1025 */
1026 void
1027 net_uptime2timeval(struct timeval *tv)
1028 {
1029 if (tv == NULL) {
1030 return;
1031 }
1032
1033 tv->tv_usec = 0;
1034 tv->tv_sec = net_uptime();
1035 }
1036
1037 /*
1038 * An alternative way to obtain the coarse-grained uptime (in seconds)
1039 * for networking code which do not require high-precision timestamp,
1040 * as this is significantly cheaper than microuptime().
1041 */
1042 u_int64_t
1043 net_uptime(void)
1044 {
1045 if (_net_uptime == 0) {
1046 net_update_uptime();
1047 }
1048
1049 return _net_uptime;
1050 }
1051
1052 u_int64_t
1053 net_uptime_ms(void)
1054 {
1055 if (_net_uptime_ms == 0) {
1056 net_update_uptime();
1057 }
1058
1059 return _net_uptime_ms;
1060 }
1061
1062 void
1063 domain_proto_mtx_lock_assert_held(void)
1064 {
1065 LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1066 }
1067
1068 void
1069 domain_proto_mtx_lock_assert_notheld(void)
1070 {
1071 LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1072 }
1073
1074 domain_guard_t
1075 domain_guard_deploy(void)
1076 {
1077 net_thread_marks_t marks;
1078
1079 marks = net_thread_marks_push(NET_THREAD_HELD_DOMAIN);
1080 if (marks != net_thread_marks_none) {
1081 LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1082 lck_mtx_lock(&domain_proto_mtx);
1083 } else {
1084 LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1085 }
1086
1087 return (domain_guard_t)(const void*)marks;
1088 }
1089
1090 void
1091 domain_guard_release(domain_guard_t guard)
1092 {
1093 net_thread_marks_t marks = (net_thread_marks_t)(const void*)guard;
1094
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 net_thread_marks_pop(marks);
1099 } else {
1100 LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1101 }
1102 }
1103
1104 domain_unguard_t
1105 domain_unguard_deploy(void)
1106 {
1107 net_thread_marks_t marks;
1108
1109 marks = net_thread_unmarks_push(NET_THREAD_HELD_DOMAIN);
1110 if (marks != net_thread_marks_none) {
1111 LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1112 lck_mtx_unlock(&domain_proto_mtx);
1113 } else {
1114 LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1115 }
1116
1117 return (domain_unguard_t)(const void*)marks;
1118 }
1119
1120 void
1121 domain_unguard_release(domain_unguard_t unguard)
1122 {
1123 net_thread_marks_t marks = (net_thread_marks_t)(const void*)unguard;
1124
1125 if (marks != net_thread_marks_none) {
1126 LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1127 lck_mtx_lock(&domain_proto_mtx);
1128 net_thread_unmarks_pop(marks);
1129 } else {
1130 LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1131 }
1132 }
1133
1134
1135 #if (DEVELOPMENT || DEBUG)
1136
1137 static int
1138 sysctl_do_drain_domains SYSCTL_HANDLER_ARGS
1139 {
1140 #pragma unused(arg1, arg2)
1141 int error;
1142 int dummy = 0;
1143
1144 error = sysctl_handle_int(oidp, &dummy, 0, req);
1145 if (error || req->newptr == USER_ADDR_NULL) {
1146 return error;
1147 }
1148
1149 net_drain_domains();
1150
1151 return 0;
1152 }
1153
1154 #endif /* DEVELOPMENT || DEBUG */