xref: /freebsd/sys/kern/uipc_domain.c (revision 08aba0aec7b7f676ccc3f7886f59f277d668d5b4)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1982, 1986, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *	@(#)uipc_domain.c	8.2 (Berkeley) 10/18/93
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/protosw.h>
40 #include <sys/domain.h>
41 #include <sys/eventhandler.h>
42 #include <sys/epoch.h>
43 #include <sys/mbuf.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/rmlock.h>
48 #include <sys/socketvar.h>
49 #include <sys/systm.h>
50 #include <sys/stat.h>		/* XXXGL: remove */
51 
52 #include <machine/atomic.h>
53 
54 #include <net/vnet.h>
55 
56 /*
57  * System initialization
58  *
59  * Note: domain initialization takes place on a per domain basis
60  * as a result of traversing a SYSINIT linker set.  Most likely,
61  * each domain would want to call DOMAIN_SET(9) itself, which
62  * would cause the domain to be added just after domaininit()
63  * is called during startup.
64  *
65  * See DOMAIN_SET(9) for details on its use.
66  */
67 
68 static void domaininit(void *);
69 SYSINIT(domain, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY, domaininit, NULL);
70 
71 static void domainfinalize(void *);
72 SYSINIT(domainfin, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, domainfinalize,
73     NULL);
74 
75 struct domain *domains;		/* registered protocol domains */
76 int domain_init_status = 0;
77 static struct mtx dom_mtx;		/* domain list lock */
78 MTX_SYSINIT(domain, &dom_mtx, "domain list", MTX_DEF);
79 
80 static int
81 pr_accept_notsupp(struct socket *so, struct sockaddr **nam)
82 {
83 	return (EOPNOTSUPP);
84 }
85 
86 static int
87 pr_aio_queue_notsupp(struct socket *so, struct kaiocb *job)
88 {
89 	return (EOPNOTSUPP);
90 }
91 
92 static int
93 pr_bind_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
94 {
95 	return (EOPNOTSUPP);
96 }
97 
98 static int
99 pr_bindat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
100     struct thread *td)
101 {
102 	return (EOPNOTSUPP);
103 }
104 
105 static int
106 pr_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
107 {
108 	return (EOPNOTSUPP);
109 }
110 
111 static int
112 pr_connectat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
113     struct thread *td)
114 {
115 	return (EOPNOTSUPP);
116 }
117 
118 static int
119 pr_connect2_notsupp(struct socket *so1, struct socket *so2)
120 {
121 	return (EOPNOTSUPP);
122 }
123 
124 static int
125 pr_control_notsupp(struct socket *so, u_long cmd, void *data,
126     struct ifnet *ifp, struct thread *td)
127 {
128 	return (EOPNOTSUPP);
129 }
130 
131 static int
132 pr_disconnect_notsupp(struct socket *so)
133 {
134 	return (EOPNOTSUPP);
135 }
136 
137 static int
138 pr_listen_notsupp(struct socket *so, int backlog, struct thread *td)
139 {
140 	return (EOPNOTSUPP);
141 }
142 
143 static int
144 pr_peeraddr_notsupp(struct socket *so, struct sockaddr **nam)
145 {
146 	return (EOPNOTSUPP);
147 }
148 
149 static int
150 pr_rcvd_notsupp(struct socket *so, int flags)
151 {
152 	return (EOPNOTSUPP);
153 }
154 
155 static int
156 pr_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags)
157 {
158 	return (EOPNOTSUPP);
159 }
160 
161 static int
162 pr_send_notsupp(struct socket *so, int flags, struct mbuf *m,
163     struct sockaddr *addr, struct mbuf *control, struct thread *td)
164 {
165 	if (control != NULL)
166 		m_freem(control);
167 	if ((flags & PRUS_NOTREADY) == 0)
168 		m_freem(m);
169 	return (EOPNOTSUPP);
170 }
171 
172 static int
173 pr_ready_notsupp(struct socket *so, struct mbuf *m, int count)
174 {
175 	return (EOPNOTSUPP);
176 }
177 
178 /*
179  * This isn't really a ``null'' operation, but it's the default one and
180  * doesn't do anything destructive.
181  */
182 static int
183 pr_sense_notsupp(struct socket *so, struct stat *sb)
184 {
185 	sb->st_blksize = so->so_snd.sb_hiwat;
186 	return (0);
187 }
188 
189 static int
190 pr_shutdown_notsupp(struct socket *so)
191 {
192 	return (EOPNOTSUPP);
193 }
194 
195 static int
196 pr_sockaddr_notsupp(struct socket *so, struct sockaddr **nam)
197 {
198 	return (EOPNOTSUPP);
199 }
200 
201 static int
202 pr_sosend_notsupp(struct socket *so, struct sockaddr *addr, struct uio *uio,
203     struct mbuf *top, struct mbuf *control, int flags, struct thread *td)
204 {
205 	return (EOPNOTSUPP);
206 }
207 
208 static int
209 pr_soreceive_notsupp(struct socket *so, struct sockaddr **paddr,
210     struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
211 {
212 	return (EOPNOTSUPP);
213 }
214 
215 static int
216 pr_sopoll_notsupp(struct socket *so, int events, struct ucred *cred,
217     struct thread *td)
218 {
219 	return (EOPNOTSUPP);
220 }
221 
222 static void
223 pr_init(struct protosw *pr)
224 {
225 
226 	KASSERT(pr->pr_attach != NULL,
227 	    ("%s: protocol doesn't have pr_attach", __func__));
228 
229 #define	DEFAULT(foo, bar)	if (pr->foo == NULL) pr->foo = bar
230 	DEFAULT(pr_sosend, sosend_generic);
231 	DEFAULT(pr_soreceive, soreceive_generic);
232 	DEFAULT(pr_sopoll, sopoll_generic);
233 
234 #define NOTSUPP(foo)	if (pr->foo == NULL)  pr->foo = foo ## _notsupp
235 	NOTSUPP(pr_accept);
236 	NOTSUPP(pr_aio_queue);
237 	NOTSUPP(pr_bind);
238 	NOTSUPP(pr_bindat);
239 	NOTSUPP(pr_connect);
240 	NOTSUPP(pr_connect2);
241 	NOTSUPP(pr_connectat);
242 	NOTSUPP(pr_control);
243 	NOTSUPP(pr_disconnect);
244 	NOTSUPP(pr_listen);
245 	NOTSUPP(pr_peeraddr);
246 	NOTSUPP(pr_rcvd);
247 	NOTSUPP(pr_rcvoob);
248 	NOTSUPP(pr_send);
249 	NOTSUPP(pr_sense);
250 	NOTSUPP(pr_shutdown);
251 	NOTSUPP(pr_sockaddr);
252 	NOTSUPP(pr_sosend);
253 	NOTSUPP(pr_soreceive);
254 	NOTSUPP(pr_sopoll);
255 	NOTSUPP(pr_ready);
256 }
257 
258 /*
259  * Add a new protocol domain to the list of supported domains
260  * Note: you cant unload it again because a socket may be using it.
261  * XXX can't fail at this time.
262  */
263 void
264 domain_init(void *arg)
265 {
266 	struct domain *dp = arg;
267 	struct protosw *pr;
268 	int flags;
269 
270 	MPASS(IS_DEFAULT_VNET(curvnet));
271 
272 	flags = atomic_load_acq_int(&dp->dom_flags);
273 	if ((flags & DOMF_SUPPORTED) == 0)
274 		return;
275 	MPASS((flags & DOMF_INITED) == 0);
276 
277 	for (int i = 0; i < dp->dom_nprotosw; i++)
278 		if ((pr = dp->dom_protosw[i]) != NULL) {
279 			pr->pr_domain = dp;
280 			pr_init(pr);
281 		}
282 
283 	/*
284 	 * update global information about maximums
285 	 */
286 	max_hdr = max_linkhdr + max_protohdr;
287 	max_datalen = MHLEN - max_hdr;
288 	if (max_datalen < 1)
289 		panic("%s: max_datalen < 1", __func__);
290 	atomic_set_rel_int(&dp->dom_flags, DOMF_INITED);
291 }
292 
293 /*
294  * Add a new protocol domain to the list of supported domains
295  * Note: you cant unload it again because a socket may be using it.
296  * XXX can't fail at this time.
297  */
298 void
299 domain_add(void *data)
300 {
301 	struct domain *dp;
302 
303 	dp = (struct domain *)data;
304 	if (dp->dom_probe != NULL && (*dp->dom_probe)() != 0)
305 		return;
306 	atomic_set_rel_int(&dp->dom_flags, DOMF_SUPPORTED);
307 	mtx_lock(&dom_mtx);
308 	dp->dom_next = domains;
309 	domains = dp;
310 
311 	KASSERT(domain_init_status >= 1,
312 	    ("attempt to domain_add(%s) before domaininit()",
313 	    dp->dom_name));
314 #ifndef INVARIANTS
315 	if (domain_init_status < 1)
316 		printf("WARNING: attempt to domain_add(%s) before "
317 		    "domaininit()\n", dp->dom_name);
318 #endif
319 	mtx_unlock(&dom_mtx);
320 }
321 
322 void
323 domain_remove(void *data)
324 {
325 	struct domain *dp = (struct domain *)data;
326 
327 	if ((dp->dom_flags & DOMF_UNLOADABLE) == 0)
328 		return;
329 
330 	mtx_lock(&dom_mtx);
331 	if (domains == dp) {
332 		domains = dp->dom_next;
333 	} else {
334 		struct domain *curr;
335 		for (curr = domains; curr != NULL; curr = curr->dom_next) {
336 			if (curr->dom_next == dp) {
337 				curr->dom_next = dp->dom_next;
338 				break;
339 			}
340 		}
341 	}
342 	mtx_unlock(&dom_mtx);
343 }
344 
345 /* ARGSUSED*/
346 static void
347 domaininit(void *dummy)
348 {
349 
350 	if (max_linkhdr < 16)		/* XXX */
351 		max_linkhdr = 16;
352 
353 	mtx_lock(&dom_mtx);
354 	KASSERT(domain_init_status == 0, ("domaininit called too late!"));
355 	domain_init_status = 1;
356 	mtx_unlock(&dom_mtx);
357 }
358 
359 /* ARGSUSED*/
360 static void
361 domainfinalize(void *dummy)
362 {
363 
364 	mtx_lock(&dom_mtx);
365 	KASSERT(domain_init_status == 1, ("domainfinalize called too late!"));
366 	domain_init_status = 2;
367 	mtx_unlock(&dom_mtx);
368 }
369 
370 struct domain *
371 pffinddomain(int family)
372 {
373 	struct domain *dp;
374 
375 	for (dp = domains; dp != NULL; dp = dp->dom_next)
376 		if (dp->dom_family == family)
377 			return (dp);
378 	return (NULL);
379 }
380 
381 struct protosw *
382 pffindtype(int family, int type)
383 {
384 	struct domain *dp;
385 	struct protosw *pr;
386 
387 	dp = pffinddomain(family);
388 	if (dp == NULL)
389 		return (NULL);
390 
391 	for (int i = 0; i < dp->dom_nprotosw; i++)
392 		if ((pr = dp->dom_protosw[i]) != NULL && pr->pr_type == type)
393 			return (pr);
394 
395 	return (NULL);
396 }
397 
398 struct protosw *
399 pffindproto(int family, int protocol, int type)
400 {
401 	struct domain *dp;
402 	struct protosw *pr;
403 	struct protosw *maybe;
404 
405 	dp = pffinddomain(family);
406 	if (dp == NULL)
407 		return (NULL);
408 
409 	maybe = NULL;
410 	for (int i = 0; i < dp->dom_nprotosw; i++) {
411 		if ((pr = dp->dom_protosw[i]) == NULL)
412 			continue;
413 		if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
414 			return (pr);
415 
416 		/* XXX: raw catches all. Why? */
417 		if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
418 		    pr->pr_protocol == 0 && maybe == NULL)
419 			maybe = pr;
420 	}
421 	return (maybe);
422 }
423 
424 /*
425  * The caller must make sure that the new protocol is fully set up and ready to
426  * accept requests before it is registered.
427  */
428 int
429 protosw_register(struct domain *dp, struct protosw *npr)
430 {
431 	struct protosw **prp;
432 
433 	MPASS(dp);
434 	MPASS(npr && npr->pr_type > 0 && npr->pr_protocol > 0);
435 
436 	prp = NULL;
437 	/*
438 	 * Protect us against races when two protocol registrations for
439 	 * the same protocol happen at the same time.
440 	 */
441 	mtx_lock(&dom_mtx);
442 	for (int i = 0; i < dp->dom_nprotosw; i++) {
443 		if (dp->dom_protosw[i] == NULL) {
444 			/* Remember the first free spacer. */
445 			if (prp == NULL)
446 				prp = &dp->dom_protosw[i];
447 		} else {
448 			/*
449 			 * The new protocol must not yet exist.
450 			 * XXXAO: Check only protocol?
451 			 * XXXGL: Maybe assert that it doesn't exist?
452 			 */
453 			if ((dp->dom_protosw[i]->pr_type == npr->pr_type) &&
454 			    (dp->dom_protosw[i]->pr_protocol ==
455 			    npr->pr_protocol)) {
456 				mtx_unlock(&dom_mtx);
457 				return (EEXIST);
458 			}
459 
460 		}
461 	}
462 
463 	/* If no free spacer is found we can't add the new protocol. */
464 	if (prp == NULL) {
465 		mtx_unlock(&dom_mtx);
466 		return (ENOMEM);
467 	}
468 
469 	npr->pr_domain = dp;
470 	pr_init(npr);
471 	*prp = npr;
472 	mtx_unlock(&dom_mtx);
473 
474 	return (0);
475 }
476 
477 /*
478  * The caller must make sure the protocol and its functions correctly shut down
479  * all sockets and release all locks and memory references.
480  */
481 int
482 protosw_unregister(struct protosw *pr)
483 {
484 	struct domain *dp;
485 	struct protosw **prp;
486 
487 	dp = pr->pr_domain;
488 	prp = NULL;
489 
490 	mtx_lock(&dom_mtx);
491 	/* The protocol must exist and only once. */
492 	for (int i = 0; i < dp->dom_nprotosw; i++) {
493 		if (dp->dom_protosw[i] == pr) {
494 			KASSERT(prp == NULL,
495 			    ("%s: domain %p protocol %p registered twice\n",
496 			    __func__, dp, pr));
497 			prp = &dp->dom_protosw[i];
498 		}
499 	}
500 
501 	/* Protocol does not exist.  XXXGL: assert that it does? */
502 	if (prp == NULL) {
503 		mtx_unlock(&dom_mtx);
504 		return (EPROTONOSUPPORT);
505 	}
506 
507 	/* De-orbit the protocol and make the slot available again. */
508 	*prp = NULL;
509 	mtx_unlock(&dom_mtx);
510 
511 	return (0);
512 }
513