xref: /xnu-8796.101.5/bsd/kern/uipc_domain.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1 /*
2  * Copyright (c) 1998-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29 /*
30  * Copyright (c) 1982, 1986, 1993
31  *	The Regents of the University of California.  All rights reserved.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  *    notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  * 3. All advertising materials mentioning features or use of this software
42  *    must display the following acknowledgement:
43  *	This product includes software developed by the University of
44  *	California, Berkeley and its contributors.
45  * 4. Neither the name of the University nor the names of its contributors
46  *    may be used to endorse or promote products derived from this software
47  *    without specific prior written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59  * SUCH DAMAGE.
60  *
61  *	@(#)uipc_domain.c	8.3 (Berkeley) 2/14/95
62  */
63 
64 #include <sys/param.h>
65 #include <sys/socket.h>
66 #include <sys/protosw.h>
67 #include <sys/domain.h>
68 #include <sys/mcache.h>
69 #include <sys/mbuf.h>
70 #include <sys/time.h>
71 #include <sys/kernel.h>
72 #include <sys/systm.h>
73 #include <sys/proc_internal.h>
74 #include <sys/sysctl.h>
75 #include <sys/syslog.h>
76 #include <sys/queue.h>
77 
78 #include <net/dlil.h>
79 #include <net/nwk_wq.h>
80 
81 #include <mach/boolean.h>
82 #include <pexpert/pexpert.h>
83 
84 /* Eventhandler context for protocol events */
85 struct eventhandler_lists_ctxt protoctl_evhdlr_ctxt;
86 
87 static void pr_init_old(struct protosw *, struct domain *);
88 static void init_proto(struct protosw *, struct domain *);
89 static void attach_proto(struct protosw *, struct domain *);
90 static void detach_proto(struct protosw *, struct domain *);
91 static void dom_init_old(struct domain *);
92 static void init_domain(struct domain *);
93 static void attach_domain(struct domain *);
94 static void detach_domain(struct domain *);
95 static struct protosw *pffindprotonotype_locked(int, int, int);
96 static struct domain *pffinddomain_locked(int);
97 
98 static boolean_t domain_timeout_run;    /* domain timer is scheduled to run */
99 static boolean_t domain_draining;
100 static void domain_sched_timeout(void);
101 static void domain_timeout(void *);
102 
103 static LCK_GRP_DECLARE(domain_proto_mtx_grp, "domain");
104 static LCK_ATTR_DECLARE(domain_proto_mtx_attr, 0, 0);
105 static LCK_MTX_DECLARE_ATTR(domain_proto_mtx,
106     &domain_proto_mtx_grp, &domain_proto_mtx_attr);
107 static LCK_MTX_DECLARE_ATTR(domain_timeout_mtx,
108     &domain_proto_mtx_grp, &domain_proto_mtx_attr);
109 
110 u_int64_t _net_uptime;
111 u_int64_t _net_uptime_ms;
112 
113 #if (DEVELOPMENT || DEBUG)
114 
115 SYSCTL_DECL(_kern_ipc);
116 
117 static int sysctl_do_drain_domains SYSCTL_HANDLER_ARGS;
118 
119 SYSCTL_PROC(_kern_ipc, OID_AUTO, do_drain_domains,
120     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
121     0, 0,
122     sysctl_do_drain_domains, "I", "force manual drain domains");
123 
124 #endif /* DEVELOPMENT || DEBUG */
125 
126 static void
pr_init_old(struct protosw * pp,struct domain * dp)127 pr_init_old(struct protosw *pp, struct domain *dp)
128 {
129 #pragma unused(dp)
130 	VERIFY(pp->pr_flags & PR_OLD);
131 	VERIFY(pp->pr_old != NULL);
132 
133 	if (pp->pr_old->pr_init != NULL) {
134 		pp->pr_old->pr_init();
135 	}
136 }
137 
138 static void
init_proto(struct protosw * pp,struct domain * dp)139 init_proto(struct protosw *pp, struct domain *dp)
140 {
141 	VERIFY(pp->pr_flags & PR_ATTACHED);
142 
143 	if (!(pp->pr_flags & PR_INITIALIZED)) {
144 		TAILQ_INIT(&pp->pr_filter_head);
145 		if (pp->pr_init != NULL) {
146 			pp->pr_init(pp, dp);
147 		}
148 		pp->pr_flags |= PR_INITIALIZED;
149 	}
150 }
151 
152 static void
attach_proto(struct protosw * pp,struct domain * dp)153 attach_proto(struct protosw *pp, struct domain *dp)
154 {
155 	domain_proto_mtx_lock_assert_held();
156 	VERIFY(!(pp->pr_flags & PR_ATTACHED));
157 	VERIFY(pp->pr_domain == NULL);
158 	VERIFY(pp->pr_protosw == NULL);
159 
160 	TAILQ_INSERT_TAIL(&dp->dom_protosw, pp, pr_entry);
161 	pp->pr_flags |= PR_ATTACHED;
162 	pp->pr_domain = dp;
163 	pp->pr_protosw = pp;
164 
165 	/* do some cleaning up on user request callbacks */
166 	pru_sanitize(pp->pr_usrreqs);
167 }
168 
169 static void
detach_proto(struct protosw * pp,struct domain * dp)170 detach_proto(struct protosw *pp, struct domain *dp)
171 {
172 	domain_proto_mtx_lock_assert_held();
173 	VERIFY(pp->pr_flags & PR_ATTACHED);
174 	VERIFY(pp->pr_domain == dp);
175 	VERIFY(pp->pr_protosw == pp);
176 
177 	TAILQ_REMOVE(&dp->dom_protosw, pp, pr_entry);
178 	pp->pr_flags &= ~PR_ATTACHED;
179 	pp->pr_domain = NULL;
180 	pp->pr_protosw = NULL;
181 }
182 
183 static void
dom_init_old(struct domain * dp)184 dom_init_old(struct domain *dp)
185 {
186 	VERIFY(dp->dom_flags & DOM_OLD);
187 	VERIFY(dp->dom_old != NULL);
188 
189 	if (dp->dom_old->dom_init != NULL) {
190 		dp->dom_old->dom_init();
191 	}
192 }
193 
194 static void
init_domain(struct domain * dp)195 init_domain(struct domain *dp)
196 {
197 	VERIFY(dp->dom_flags & DOM_ATTACHED);
198 
199 	if (!(dp->dom_flags & DOM_INITIALIZED)) {
200 		lck_mtx_init(&dp->dom_mtx_s, &domain_proto_mtx_grp,
201 		    &domain_proto_mtx_attr);
202 		dp->dom_mtx = &dp->dom_mtx_s;
203 		TAILQ_INIT(&dp->dom_protosw);
204 		if (dp->dom_init != NULL) {
205 			dp->dom_init(dp);
206 		}
207 		dp->dom_flags |= DOM_INITIALIZED;
208 	}
209 
210 	/* Recompute for new protocol */
211 	if (max_linkhdr < 16) {        /* XXX - Sheesh; everything's ether? */
212 		max_linkhdr = 16;
213 	}
214 	max_linkhdr = (int)P2ROUNDUP(max_linkhdr, sizeof(uint32_t));
215 
216 	if (dp->dom_protohdrlen > max_protohdr) {
217 		max_protohdr = dp->dom_protohdrlen;
218 	}
219 	max_protohdr = (int)P2ROUNDUP(max_protohdr, sizeof(uint32_t));
220 
221 	max_hdr = max_linkhdr + max_protohdr;
222 	max_datalen = MHLEN - max_hdr;
223 }
224 
225 static void
attach_domain(struct domain * dp)226 attach_domain(struct domain *dp)
227 {
228 	domain_proto_mtx_lock_assert_held();
229 	VERIFY(!(dp->dom_flags & DOM_ATTACHED));
230 
231 	TAILQ_INSERT_TAIL(&domains, dp, dom_entry);
232 	dp->dom_flags |= DOM_ATTACHED;
233 }
234 
235 static void
detach_domain(struct domain * dp)236 detach_domain(struct domain *dp)
237 {
238 	domain_proto_mtx_lock_assert_held();
239 	VERIFY(dp->dom_flags & DOM_ATTACHED);
240 
241 	TAILQ_REMOVE(&domains, dp, dom_entry);
242 	dp->dom_flags &= ~DOM_ATTACHED;
243 
244 	if (dp->dom_flags & DOM_OLD) {
245 		struct domain_old *odp = dp->dom_old;
246 
247 		VERIFY(odp != NULL);
248 		odp->dom_next = NULL;
249 		odp->dom_mtx = NULL;
250 	}
251 }
252 
253 /*
254  * Exported (private) routine, indirection of net_add_domain.
255  */
256 void
net_add_domain_old(struct domain_old * odp)257 net_add_domain_old(struct domain_old *odp)
258 {
259 	struct domain *dp;
260 	domain_guard_t guard;
261 
262 	VERIFY(odp != NULL);
263 
264 	guard = domain_guard_deploy();
265 	if ((dp = pffinddomain_locked(odp->dom_family)) != NULL) {
266 		/*
267 		 * There is really nothing better than to panic here,
268 		 * as the caller would not have been able to handle
269 		 * any failures otherwise.
270 		 */
271 		panic("%s: domain (%d,%s) already exists for %s", __func__,
272 		    dp->dom_family, dp->dom_name, odp->dom_name);
273 		/* NOTREACHED */
274 	}
275 
276 	/* Make sure nothing is currently pointing to the odp. */
277 	TAILQ_FOREACH(dp, &domains, dom_entry) {
278 		if (dp->dom_old == odp) {
279 			panic("%s: domain %p (%d,%s) is already "
280 			    "associated with %p (%d,%s)\n", __func__,
281 			    odp, odp->dom_family, odp->dom_name, dp,
282 			    dp->dom_family, dp->dom_name);
283 			/* NOTREACHED */
284 		}
285 	}
286 
287 	if (odp->dom_protosw != NULL) {
288 		panic("%s: domain (%d,%s) protocols need to added "
289 		    "via net_add_proto\n", __func__, odp->dom_family,
290 		    odp->dom_name);
291 		/* NOTREACHED */
292 	}
293 
294 	dp = kalloc_type(struct domain, Z_WAITOK | Z_ZERO | Z_NOFAIL);
295 
296 	/* Copy everything but dom_init, dom_mtx, dom_next and dom_refs */
297 	dp->dom_family          = odp->dom_family;
298 	dp->dom_flags           = (odp->dom_flags & DOMF_USERFLAGS) | DOM_OLD;
299 	dp->dom_name            = odp->dom_name;
300 	dp->dom_init            = dom_init_old;
301 	dp->dom_externalize     = odp->dom_externalize;
302 	dp->dom_dispose         = odp->dom_dispose;
303 	dp->dom_rtattach        = odp->dom_rtattach;
304 	dp->dom_rtoffset        = odp->dom_rtoffset;
305 	dp->dom_maxrtkey        = odp->dom_maxrtkey;
306 	dp->dom_protohdrlen     = odp->dom_protohdrlen;
307 	dp->dom_old             = odp;
308 
309 	attach_domain(dp);
310 	init_domain(dp);
311 
312 	/* Point the mutex back to the internal structure's */
313 	odp->dom_mtx            = dp->dom_mtx;
314 	domain_guard_release(guard);
315 }
316 
317 /*
318  * Exported (private) routine, indirection of net_del_domain.
319  */
320 int
net_del_domain_old(struct domain_old * odp)321 net_del_domain_old(struct domain_old *odp)
322 {
323 	struct domain *dp1, *dp2;
324 	int error = 0;
325 	domain_guard_t guard;
326 
327 	VERIFY(odp != NULL);
328 
329 	guard = domain_guard_deploy();
330 	if (odp->dom_refs != 0) {
331 		error = EBUSY;
332 		goto done;
333 	}
334 
335 	TAILQ_FOREACH_SAFE(dp1, &domains, dom_entry, dp2) {
336 		if (!(dp1->dom_flags & DOM_OLD)) {
337 			continue;
338 		}
339 		VERIFY(dp1->dom_old != NULL);
340 		if (odp == dp1->dom_old) {
341 			break;
342 		}
343 	}
344 	if (dp1 != NULL) {
345 		struct protosw *pp1, *pp2;
346 
347 		VERIFY(dp1->dom_flags & DOM_OLD);
348 		VERIFY(dp1->dom_old == odp);
349 
350 		/* Remove all protocols attached to this domain */
351 		TAILQ_FOREACH_SAFE(pp1, &dp1->dom_protosw, pr_entry, pp2) {
352 			detach_proto(pp1, dp1);
353 			if (pp1->pr_usrreqs->pru_flags & PRUF_OLD) {
354 				kfree_type(struct pr_usrreqs, pp1->pr_usrreqs);
355 			}
356 			if (pp1->pr_flags & PR_OLD) {
357 				kfree_type(struct protosw, pp1);
358 			}
359 		}
360 
361 		detach_domain(dp1);
362 		kfree_type(struct domain, dp1);
363 	} else {
364 		error = EPFNOSUPPORT;
365 	}
366 done:
367 	domain_guard_release(guard);
368 	return error;
369 }
370 
371 /*
372  * Internal routine, not exported.
373  *
374  * net_add_proto - link a protosw into a domain's protosw chain
375  *
376  * NOTE: Caller must have acquired domain_proto_mtx
377  */
378 int
net_add_proto(struct protosw * pp,struct domain * dp,int doinit)379 net_add_proto(struct protosw *pp, struct domain *dp, int doinit)
380 {
381 	struct protosw *pp1;
382 
383 	/*
384 	 * This could be called as part of initializing the domain,
385 	 * and thus DOM_INITIALIZED may not be set (yet).
386 	 */
387 	domain_proto_mtx_lock_assert_held();
388 	VERIFY(!(pp->pr_flags & PR_ATTACHED));
389 
390 	/* pr_domain is set only after the protocol is attached */
391 	if (pp->pr_domain != NULL) {
392 		panic("%s: domain (%d,%s), proto %d has non-NULL pr_domain!",
393 		    __func__, dp->dom_family, dp->dom_name, pp->pr_protocol);
394 		/* NOTREACHED */
395 	}
396 
397 	if (pp->pr_usrreqs == NULL) {
398 		panic("%s: domain (%d,%s), proto %d has no usrreqs!",
399 		    __func__, dp->dom_family, dp->dom_name, pp->pr_protocol);
400 		/* NOTREACHED */
401 	}
402 
403 	TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) {
404 		if (pp1->pr_type == pp->pr_type &&
405 		    pp1->pr_protocol == pp->pr_protocol) {
406 			return EEXIST;
407 		}
408 	}
409 
410 	attach_proto(pp, dp);
411 	if (doinit) {
412 		net_init_proto(pp, dp);
413 	}
414 
415 	return 0;
416 }
417 
418 void
net_init_proto(struct protosw * pp,struct domain * dp)419 net_init_proto(struct protosw *pp, struct domain *dp)
420 {
421 	/*
422 	 * This could be called as part of initializing the domain,
423 	 * and thus DOM_INITIALIZED may not be set (yet).  The protocol
424 	 * must have been attached via net_addr_protosw() by now.
425 	 */
426 	domain_proto_mtx_lock_assert_held();
427 	VERIFY(pp->pr_flags & PR_ATTACHED);
428 
429 	init_proto(pp, dp);
430 }
431 
432 /*
433  * Exported (private) routine, indirection of net_add_proto.
434  */
435 int
net_add_proto_old(struct protosw_old * opp,struct domain_old * odp)436 net_add_proto_old(struct protosw_old *opp, struct domain_old *odp)
437 {
438 	struct pr_usrreqs_old *opru;
439 	struct pr_usrreqs *pru = NULL;
440 	struct protosw *pp = NULL, *pp1;
441 	int error = 0;
442 	struct domain *dp;
443 	domain_guard_t guard;
444 
445 	/*
446 	 * This could be called as part of initializing the domain,
447 	 * and thus DOM_INITIALIZED may not be set (yet).
448 	 */
449 	guard = domain_guard_deploy();
450 
451 	/* Make sure the domain has been added via net_add_domain */
452 	TAILQ_FOREACH(dp, &domains, dom_entry) {
453 		if (!(dp->dom_flags & DOM_OLD)) {
454 			continue;
455 		}
456 		if (dp->dom_old == odp) {
457 			break;
458 		}
459 	}
460 	if (dp == NULL) {
461 		error = EINVAL;
462 		goto done;
463 	}
464 
465 	TAILQ_FOREACH(pp1, &dp->dom_protosw, pr_entry) {
466 		if (pp1->pr_type == opp->pr_type &&
467 		    pp1->pr_protocol == opp->pr_protocol) {
468 			error = EEXIST;
469 			goto done;
470 		}
471 	}
472 
473 	if ((opru = opp->pr_usrreqs) == NULL) {
474 		panic("%s: domain (%d,%s), proto %d has no usrreqs!",
475 		    __func__, odp->dom_family, odp->dom_name, opp->pr_protocol);
476 		/* NOTREACHED */
477 	}
478 
479 	pru = kalloc_type(struct pr_usrreqs, Z_WAITOK | Z_ZERO | Z_NOFAIL);
480 
481 	pru->pru_flags          = PRUF_OLD;
482 	pru->pru_abort          = opru->pru_abort;
483 	pru->pru_accept         = opru->pru_accept;
484 	pru->pru_attach         = opru->pru_attach;
485 	pru->pru_bind           = opru->pru_bind;
486 	pru->pru_connect        = opru->pru_connect;
487 	pru->pru_connect2       = opru->pru_connect2;
488 	pru->pru_control        = opru->pru_control;
489 	pru->pru_detach         = opru->pru_detach;
490 	pru->pru_disconnect     = opru->pru_disconnect;
491 	pru->pru_listen         = opru->pru_listen;
492 	pru->pru_peeraddr       = opru->pru_peeraddr;
493 	pru->pru_rcvd           = opru->pru_rcvd;
494 	pru->pru_rcvoob         = opru->pru_rcvoob;
495 	pru->pru_send           = opru->pru_send;
496 	pru->pru_sense          = opru->pru_sense;
497 	pru->pru_shutdown       = opru->pru_shutdown;
498 	pru->pru_sockaddr       = opru->pru_sockaddr;
499 	pru->pru_sosend         = opru->pru_sosend;
500 	pru->pru_soreceive      = opru->pru_soreceive;
501 	pru->pru_sopoll         = opru->pru_sopoll;
502 
503 	pp = kalloc_type(struct protosw, Z_WAITOK | Z_ZERO | Z_NOFAIL);
504 
505 	/*
506 	 * Protocol fast and slow timers are now deprecated.
507 	 */
508 	if (opp->pr_unused != NULL) {
509 		printf("%s: domain (%d,%s), proto %d: pr_fasttimo is "
510 		    "deprecated and won't be called\n", __func__,
511 		    odp->dom_family, odp->dom_name, opp->pr_protocol);
512 	}
513 	if (opp->pr_unused2 != NULL) {
514 		printf("%s: domain (%d,%s), proto %d: pr_slowtimo is "
515 		    "deprecated and won't be called\n", __func__,
516 		    odp->dom_family, odp->dom_name, opp->pr_protocol);
517 	}
518 
519 	/* Copy everything but pr_init, pr_next, pr_domain, pr_protosw */
520 	pp->pr_type             = opp->pr_type;
521 	pp->pr_protocol         = opp->pr_protocol;
522 	pp->pr_flags            = (opp->pr_flags & PRF_USERFLAGS) | PR_OLD;
523 	pp->pr_input            = opp->pr_input;
524 	pp->pr_output           = opp->pr_output;
525 	pp->pr_ctlinput         = opp->pr_ctlinput;
526 	pp->pr_ctloutput        = opp->pr_ctloutput;
527 	pp->pr_usrreqs          = pru;
528 	pp->pr_init             = pr_init_old;
529 	pp->pr_drain            = opp->pr_drain;
530 	pp->pr_sysctl           = opp->pr_sysctl;
531 	pp->pr_lock             = opp->pr_lock;
532 	pp->pr_unlock           = opp->pr_unlock;
533 	pp->pr_getlock          = opp->pr_getlock;
534 	pp->pr_old              = opp;
535 
536 	/* attach as well as initialize */
537 	attach_proto(pp, dp);
538 	net_init_proto(pp, dp);
539 done:
540 	if (error != 0) {
541 		printf("%s: domain (%d,%s), proto %d: failed to attach, "
542 		    "error %d\n", __func__, odp->dom_family,
543 		    odp->dom_name, opp->pr_protocol, error);
544 
545 		kfree_type(struct pr_usrreqs, pru);
546 		kfree_type(struct protosw, pp);
547 	}
548 
549 	domain_guard_release(guard);
550 	return error;
551 }
552 
553 /*
554  * Internal routine, not exported.
555  *
556  * net_del_proto - remove a protosw from a domain's protosw chain.
557  * Search the protosw chain for the element with matching data.
558  * Then unlink and return.
559  *
560  * NOTE: Caller must have acquired domain_proto_mtx
561  */
562 int
net_del_proto(int type,int protocol,struct domain * dp)563 net_del_proto(int type, int protocol, struct domain *dp)
564 {
565 	struct protosw *pp;
566 
567 	/*
568 	 * This could be called as part of initializing the domain,
569 	 * and thus DOM_INITIALIZED may not be set (yet).
570 	 */
571 	domain_proto_mtx_lock_assert_held();
572 
573 	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
574 		if (pp->pr_type == type && pp->pr_protocol == protocol) {
575 			break;
576 		}
577 	}
578 	if (pp == NULL) {
579 		return ENXIO;
580 	}
581 
582 	detach_proto(pp, dp);
583 	if (pp->pr_usrreqs->pru_flags & PRUF_OLD) {
584 		kfree_type(struct pr_usrreqs, pp->pr_usrreqs);
585 	}
586 	if (pp->pr_flags & PR_OLD) {
587 		kfree_type(struct protosw, pp);
588 	}
589 
590 	return 0;
591 }
592 
593 /*
594  * Exported (private) routine, indirection of net_del_proto.
595  */
596 int
net_del_proto_old(int type,int protocol,struct domain_old * odp)597 net_del_proto_old(int type, int protocol, struct domain_old *odp)
598 {
599 	int error = 0;
600 	struct protosw *pp;
601 	struct domain *dp;
602 	domain_guard_t guard;
603 
604 	/*
605 	 * This could be called as part of initializing the domain,
606 	 * and thus DOM_INITIALIZED may not be set (yet).
607 	 */
608 	guard = domain_guard_deploy();
609 
610 	/* Make sure the domain has been added via net_add_domain */
611 	TAILQ_FOREACH(dp, &domains, dom_entry) {
612 		if (!(dp->dom_flags & DOM_OLD)) {
613 			continue;
614 		}
615 		if (dp->dom_old == odp) {
616 			break;
617 		}
618 	}
619 	if (dp == NULL) {
620 		error = ENXIO;
621 		goto done;
622 	}
623 
624 	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
625 		if (pp->pr_type == type && pp->pr_protocol == protocol) {
626 			break;
627 		}
628 	}
629 	if (pp == NULL) {
630 		error = ENXIO;
631 		goto done;
632 	}
633 	detach_proto(pp, dp);
634 	if (pp->pr_usrreqs->pru_flags & PRUF_OLD) {
635 		kfree_type(struct pr_usrreqs, pp->pr_usrreqs);
636 	}
637 	if (pp->pr_flags & PR_OLD) {
638 		kfree_type(struct protosw, pp);
639 	}
640 
641 done:
642 	domain_guard_release(guard);
643 	return error;
644 }
645 
646 static void
domain_sched_timeout(void)647 domain_sched_timeout(void)
648 {
649 	LCK_MTX_ASSERT(&domain_timeout_mtx, LCK_MTX_ASSERT_OWNED);
650 
651 	if (!domain_timeout_run && domain_draining) {
652 		domain_timeout_run = TRUE;
653 		timeout(domain_timeout, NULL, hz);
654 	}
655 }
656 
657 void
net_drain_domains(void)658 net_drain_domains(void)
659 {
660 	lck_mtx_lock(&domain_timeout_mtx);
661 	domain_draining = TRUE;
662 	domain_sched_timeout();
663 	lck_mtx_unlock(&domain_timeout_mtx);
664 }
665 
666 extern struct domain inet6domain_s;
667 #if IPSEC
668 extern struct domain keydomain_s;
669 #endif
670 
671 extern struct domain routedomain_s, ndrvdomain_s, inetdomain_s;
672 extern struct domain systemdomain_s, localdomain_s;
673 extern struct domain vsockdomain_s;
674 
675 #if MULTIPATH
676 extern struct domain mpdomain_s;
677 #endif /* MULTIPATH */
678 
679 static void
domain_timeout(void * arg)680 domain_timeout(void *arg)
681 {
682 #pragma unused(arg)
683 	struct protosw *pp;
684 	struct domain *dp;
685 	domain_guard_t guard;
686 
687 	lck_mtx_lock(&domain_timeout_mtx);
688 	if (domain_draining) {
689 		domain_draining = FALSE;
690 		lck_mtx_unlock(&domain_timeout_mtx);
691 
692 		guard = domain_guard_deploy();
693 		TAILQ_FOREACH(dp, &domains, dom_entry) {
694 			TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
695 				if (pp->pr_drain != NULL) {
696 					(*pp->pr_drain)();
697 				}
698 			}
699 		}
700 		domain_guard_release(guard);
701 
702 		lck_mtx_lock(&domain_timeout_mtx);
703 	}
704 
705 	/* re-arm the timer if there's work to do */
706 	domain_timeout_run = FALSE;
707 	domain_sched_timeout();
708 	lck_mtx_unlock(&domain_timeout_mtx);
709 }
710 
711 void
domaininit(void)712 domaininit(void)
713 {
714 	struct domain *dp;
715 	domain_guard_t guard;
716 
717 	eventhandler_lists_ctxt_init(&protoctl_evhdlr_ctxt);
718 
719 	guard = domain_guard_deploy();
720 	/*
721 	 * Add all the static domains to the domains list.  route domain
722 	 * gets added and initialized last, since we need it to attach
723 	 * rt_tables[] to everything that's already there.  This also
724 	 * means that domains added after this point won't get their
725 	 * dom_rtattach() called on rt_tables[].
726 	 */
727 	attach_domain(&inetdomain_s);
728 	attach_domain(&inet6domain_s);
729 #if MULTIPATH
730 	attach_domain(&mpdomain_s);
731 #endif /* MULTIPATH */
732 	attach_domain(&systemdomain_s);
733 	attach_domain(&localdomain_s);
734 #if IPSEC
735 	attach_domain(&keydomain_s);
736 #endif /* IPSEC */
737 	attach_domain(&ndrvdomain_s);
738 	attach_domain(&vsockdomain_s);
739 	attach_domain(&routedomain_s);  /* must be last domain */
740 
741 	/*
742 	 * Now ask them all to init (XXX including the routing domain,
743 	 * see above)
744 	 */
745 	TAILQ_FOREACH(dp, &domains, dom_entry)
746 	init_domain(dp);
747 
748 	domain_guard_release(guard);
749 }
750 
751 static __inline__ struct domain *
pffinddomain_locked(int pf)752 pffinddomain_locked(int pf)
753 {
754 	struct domain *dp;
755 
756 	domain_proto_mtx_lock_assert_held();
757 
758 	TAILQ_FOREACH(dp, &domains, dom_entry) {
759 		if (dp->dom_family == pf) {
760 			break;
761 		}
762 	}
763 	return dp;
764 }
765 
766 struct protosw *
pffindtype(int family,int type)767 pffindtype(int family, int type)
768 {
769 	struct protosw *pp = NULL;
770 	struct domain *dp;
771 	domain_guard_t guard;
772 
773 	guard = domain_guard_deploy();
774 	if ((dp = pffinddomain_locked(family)) == NULL) {
775 		goto done;
776 	}
777 
778 	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
779 		if (pp->pr_type != 0 && pp->pr_type == type) {
780 			goto done;
781 		}
782 	}
783 done:
784 	domain_guard_release(guard);
785 	return pp;
786 }
787 
788 /*
789  * Internal routine, not exported.
790  */
791 struct domain *
pffinddomain(int pf)792 pffinddomain(int pf)
793 {
794 	struct domain *dp;
795 	domain_guard_t guard;
796 
797 	guard = domain_guard_deploy();
798 	dp = pffinddomain_locked(pf);
799 	domain_guard_release(guard);
800 	return dp;
801 }
802 
803 /*
804  * Exported (private) routine, indirection of pffinddomain.
805  */
806 struct domain_old *
pffinddomain_old(int pf)807 pffinddomain_old(int pf)
808 {
809 	struct domain_old *odp = NULL;
810 	struct domain *dp;
811 	domain_guard_t guard;
812 
813 	guard = domain_guard_deploy();
814 	if ((dp = pffinddomain_locked(pf)) != NULL && (dp->dom_flags & DOM_OLD)) {
815 		odp = dp->dom_old;
816 	}
817 	domain_guard_release(guard);
818 	return odp;
819 }
820 
821 /*
822  * Internal routine, not exported.
823  */
824 struct protosw *
pffindproto(int family,int protocol,int type)825 pffindproto(int family, int protocol, int type)
826 {
827 	struct protosw *pp;
828 	domain_guard_t guard;
829 
830 	guard = domain_guard_deploy();
831 	pp = pffindproto_locked(family, protocol, type);
832 	domain_guard_release(guard);
833 	return pp;
834 }
835 
836 struct protosw *
pffindproto_locked(int family,int protocol,int type)837 pffindproto_locked(int family, int protocol, int type)
838 {
839 	struct protosw *maybe = NULL;
840 	struct protosw *pp;
841 	struct domain *dp;
842 
843 	domain_proto_mtx_lock_assert_held();
844 
845 	if (family == 0) {
846 		return 0;
847 	}
848 
849 	dp = pffinddomain_locked(family);
850 	if (dp == NULL) {
851 		return NULL;
852 	}
853 
854 	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
855 		if ((pp->pr_protocol == protocol) && (pp->pr_type == type)) {
856 			return pp;
857 		}
858 
859 		if (type == SOCK_RAW && pp->pr_type == SOCK_RAW &&
860 		    pp->pr_protocol == 0 && maybe == NULL) {
861 			maybe = pp;
862 		}
863 	}
864 	return maybe;
865 }
866 
867 /*
868  * Exported (private) routine, indirection of pffindproto.
869  */
870 struct protosw_old *
pffindproto_old(int family,int protocol,int type)871 pffindproto_old(int family, int protocol, int type)
872 {
873 	struct protosw_old *opr = NULL;
874 	struct protosw *pp;
875 	domain_guard_t guard;
876 
877 	guard = domain_guard_deploy();
878 	if ((pp = pffindproto_locked(family, protocol, type)) != NULL &&
879 	    (pp->pr_flags & PR_OLD)) {
880 		opr = pp->pr_old;
881 	}
882 	domain_guard_release(guard);
883 	return opr;
884 }
885 
886 static struct protosw *
pffindprotonotype_locked(int family,int protocol,int type)887 pffindprotonotype_locked(int family, int protocol, int type)
888 {
889 #pragma unused(type)
890 	struct domain *dp;
891 	struct protosw *pp;
892 
893 	domain_proto_mtx_lock_assert_held();
894 
895 	if (family == 0) {
896 		return 0;
897 	}
898 
899 	dp = pffinddomain_locked(family);
900 	if (dp == NULL) {
901 		return NULL;
902 	}
903 
904 	TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
905 		if (pp->pr_protocol == protocol) {
906 			return pp;
907 		}
908 	}
909 	return NULL;
910 }
911 
912 struct protosw *
pffindprotonotype(int family,int protocol)913 pffindprotonotype(int family, int protocol)
914 {
915 	struct protosw *pp;
916 	domain_guard_t guard;
917 
918 	if (protocol == 0) {
919 		return NULL;
920 	}
921 
922 	guard = domain_guard_deploy();
923 	pp = pffindprotonotype_locked(family, protocol, 0);
924 	domain_guard_release(guard);
925 	return pp;
926 }
927 
928 void
pfctlinput(int cmd,struct sockaddr * sa)929 pfctlinput(int cmd, struct sockaddr *sa)
930 {
931 	pfctlinput2(cmd, sa, NULL);
932 }
933 
934 void
pfctlinput2(int cmd,struct sockaddr * sa,void * ctlparam)935 pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam)
936 {
937 	struct domain *dp;
938 	struct protosw *pp;
939 	domain_guard_t guard;
940 
941 	if (sa == NULL) {
942 		return;
943 	}
944 
945 	guard = domain_guard_deploy();
946 	TAILQ_FOREACH(dp, &domains, dom_entry) {
947 		TAILQ_FOREACH(pp, &dp->dom_protosw, pr_entry) {
948 			if (pp->pr_ctlinput != NULL) {
949 				(*pp->pr_ctlinput)(cmd, sa, ctlparam, NULL);
950 			}
951 		}
952 	}
953 	domain_guard_release(guard);
954 }
955 
956 void
net_update_uptime_with_time(const struct timeval * tvp)957 net_update_uptime_with_time(const struct timeval *tvp)
958 {
959 	_net_uptime = tvp->tv_sec;
960 	/*
961 	 * Round up the timer to the nearest integer value because otherwise
962 	 * we might setup networking timers that are off by almost 1 second.
963 	 */
964 	if (tvp->tv_usec > 500000) {
965 		_net_uptime++;
966 	}
967 
968 	/* update milliseconds variant */
969 	_net_uptime_ms = (((u_int64_t)tvp->tv_sec * 1000) +
970 	    ((u_int64_t)tvp->tv_usec / 1000));
971 }
972 
973 void
net_update_uptime(void)974 net_update_uptime(void)
975 {
976 	struct timeval tv;
977 
978 	microuptime(&tv);
979 
980 	net_update_uptime_with_time(&tv);
981 }
982 
983 /*
984  * Convert our uin64_t net_uptime to a struct timeval.
985  */
986 void
net_uptime2timeval(struct timeval * tv)987 net_uptime2timeval(struct timeval *tv)
988 {
989 	if (tv == NULL) {
990 		return;
991 	}
992 
993 	tv->tv_usec = 0;
994 	tv->tv_sec = (time_t)net_uptime();
995 }
996 
997 /*
998  * An alternative way to obtain the coarse-grained uptime (in seconds)
999  * for networking code which do not require high-precision timestamp,
1000  * as this is significantly cheaper than microuptime().
1001  */
1002 u_int64_t
net_uptime(void)1003 net_uptime(void)
1004 {
1005 	if (_net_uptime == 0) {
1006 		net_update_uptime();
1007 	}
1008 
1009 	return _net_uptime;
1010 }
1011 
1012 u_int64_t
net_uptime_ms(void)1013 net_uptime_ms(void)
1014 {
1015 	if (_net_uptime_ms == 0) {
1016 		net_update_uptime();
1017 	}
1018 
1019 	return _net_uptime_ms;
1020 }
1021 
1022 void
domain_proto_mtx_lock_assert_held(void)1023 domain_proto_mtx_lock_assert_held(void)
1024 {
1025 	LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1026 }
1027 
1028 void
domain_proto_mtx_lock_assert_notheld(void)1029 domain_proto_mtx_lock_assert_notheld(void)
1030 {
1031 	LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1032 }
1033 
1034 domain_guard_t
domain_guard_deploy(void)1035 domain_guard_deploy(void)
1036 {
1037 	net_thread_marks_t marks;
1038 
1039 	marks = net_thread_marks_push(NET_THREAD_HELD_DOMAIN);
1040 	if (marks != net_thread_marks_none) {
1041 		LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1042 		lck_mtx_lock(&domain_proto_mtx);
1043 	} else {
1044 		LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1045 	}
1046 
1047 	return (domain_guard_t)(const void*)marks;
1048 }
1049 
1050 void
domain_guard_release(domain_guard_t guard)1051 domain_guard_release(domain_guard_t guard)
1052 {
1053 	net_thread_marks_t marks = (net_thread_marks_t)(const void*)guard;
1054 
1055 	if (marks != net_thread_marks_none) {
1056 		LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1057 		lck_mtx_unlock(&domain_proto_mtx);
1058 		net_thread_marks_pop(marks);
1059 	} else {
1060 		LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1061 	}
1062 }
1063 
1064 domain_unguard_t
domain_unguard_deploy(void)1065 domain_unguard_deploy(void)
1066 {
1067 	net_thread_marks_t marks;
1068 
1069 	marks = net_thread_unmarks_push(NET_THREAD_HELD_DOMAIN);
1070 	if (marks != net_thread_marks_none) {
1071 		LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1072 		lck_mtx_unlock(&domain_proto_mtx);
1073 	} else {
1074 		LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1075 	}
1076 
1077 	return (domain_unguard_t)(const void*)marks;
1078 }
1079 
1080 void
domain_unguard_release(domain_unguard_t unguard)1081 domain_unguard_release(domain_unguard_t unguard)
1082 {
1083 	net_thread_marks_t marks = (net_thread_marks_t)(const void*)unguard;
1084 
1085 	if (marks != net_thread_marks_none) {
1086 		LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
1087 		lck_mtx_lock(&domain_proto_mtx);
1088 		net_thread_unmarks_pop(marks);
1089 	} else {
1090 		LCK_MTX_ASSERT(&domain_proto_mtx, LCK_MTX_ASSERT_OWNED);
1091 	}
1092 }
1093 
1094 #if SKYWALK
1095 /* The following is used to enqueue work items for interface events */
1096 struct protoctl_event {
1097 	struct ifnet *ifp;
1098 	union sockaddr_in_4_6 laddr;
1099 	union sockaddr_in_4_6 raddr;
1100 	uint32_t protoctl_event_code;
1101 	struct protoctl_ev_val val;
1102 	uint16_t lport;
1103 	uint16_t rport;
1104 	uint8_t protocol;
1105 };
1106 
1107 struct protoctl_event_nwk_wq_entry {
1108 	struct nwk_wq_entry nwk_wqe;
1109 	struct protoctl_event protoctl_ev_arg;
1110 };
1111 
1112 static void
protoctl_event_callback(struct nwk_wq_entry * nwk_item)1113 protoctl_event_callback(struct nwk_wq_entry *nwk_item)
1114 {
1115 	struct protoctl_event_nwk_wq_entry *p_ev = NULL;
1116 
1117 	p_ev = __container_of(nwk_item, struct protoctl_event_nwk_wq_entry, nwk_wqe);
1118 
1119 	/* Call this before we walk the tree */
1120 	EVENTHANDLER_INVOKE(&protoctl_evhdlr_ctxt, protoctl_event,
1121 	    p_ev->protoctl_ev_arg.ifp, (struct sockaddr *)&(p_ev->protoctl_ev_arg.laddr),
1122 	    (struct sockaddr *)&(p_ev->protoctl_ev_arg.raddr),
1123 	    p_ev->protoctl_ev_arg.lport, p_ev->protoctl_ev_arg.rport,
1124 	    p_ev->protoctl_ev_arg.protocol, p_ev->protoctl_ev_arg.protoctl_event_code,
1125 	    &p_ev->protoctl_ev_arg.val);
1126 
1127 	kfree_type(struct protoctl_event_nwk_wq_entry, p_ev);
1128 }
1129 
1130 /* XXX Some PRC events needs extra verification like sequence number checking */
1131 void
protoctl_event_enqueue_nwk_wq_entry(struct ifnet * ifp,struct sockaddr * p_laddr,struct sockaddr * p_raddr,uint16_t lport,uint16_t rport,uint8_t protocol,uint32_t protoctl_event_code,struct protoctl_ev_val * p_protoctl_ev_val)1132 protoctl_event_enqueue_nwk_wq_entry(struct ifnet *ifp, struct sockaddr *p_laddr,
1133     struct sockaddr *p_raddr, uint16_t lport, uint16_t rport, uint8_t protocol,
1134     uint32_t protoctl_event_code, struct protoctl_ev_val *p_protoctl_ev_val)
1135 {
1136 	struct protoctl_event_nwk_wq_entry *p_protoctl_ev = NULL;
1137 
1138 	p_protoctl_ev = kalloc_type(struct protoctl_event_nwk_wq_entry,
1139 	    Z_WAITOK | Z_ZERO | Z_NOFAIL);
1140 
1141 	p_protoctl_ev->protoctl_ev_arg.ifp = ifp;
1142 	if (p_laddr != NULL) {
1143 		VERIFY(p_laddr->sa_len <= sizeof(p_protoctl_ev->protoctl_ev_arg.laddr));
1144 		bcopy(p_laddr, &(p_protoctl_ev->protoctl_ev_arg.laddr), p_laddr->sa_len);
1145 	}
1146 
1147 	if (p_raddr != NULL) {
1148 		VERIFY(p_raddr->sa_len <= sizeof(p_protoctl_ev->protoctl_ev_arg.raddr));
1149 		bcopy(p_raddr, &(p_protoctl_ev->protoctl_ev_arg.raddr), p_raddr->sa_len);
1150 	}
1151 	p_protoctl_ev->protoctl_ev_arg.lport = lport;
1152 	p_protoctl_ev->protoctl_ev_arg.rport = rport;
1153 	p_protoctl_ev->protoctl_ev_arg.protocol = protocol;
1154 	p_protoctl_ev->protoctl_ev_arg.protoctl_event_code = protoctl_event_code;
1155 
1156 	if (p_protoctl_ev_val != NULL) {
1157 		bcopy(p_protoctl_ev_val, &(p_protoctl_ev->protoctl_ev_arg.val),
1158 		    sizeof(*p_protoctl_ev_val));
1159 	}
1160 	p_protoctl_ev->nwk_wqe.func = protoctl_event_callback;
1161 
1162 	nwk_wq_enqueue(&p_protoctl_ev->nwk_wqe);
1163 }
1164 #endif /* SKYWALK */
1165 
1166 #if (DEVELOPMENT || DEBUG)
1167 
1168 static int
1169 sysctl_do_drain_domains SYSCTL_HANDLER_ARGS
1170 {
1171 #pragma unused(arg1, arg2)
1172 	int error;
1173 	int dummy = 0;
1174 
1175 	error = sysctl_handle_int(oidp, &dummy, 0, req);
1176 	if (error || req->newptr == USER_ADDR_NULL) {
1177 		return error;
1178 	}
1179 
1180 	net_drain_domains();
1181 
1182 	return 0;
1183 }
1184 
1185 #endif /* DEVELOPMENT || DEBUG */
1186