xref: /openbsd-src/sys/kern/uipc_domain.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /*	$OpenBSD: uipc_domain.c,v 1.60 2022/08/14 01:58:28 jsg Exp $	*/
2 /*	$NetBSD: uipc_domain.c,v 1.14 1996/02/09 19:00:44 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1982, 1986, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *	@(#)uipc_domain.c	8.2 (Berkeley) 10/18/93
33  */
34 
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/protosw.h>
38 #include <sys/domain.h>
39 #include <sys/mbuf.h>
40 #include <sys/systm.h>
41 #include <sys/sysctl.h>
42 #include <sys/timeout.h>
43 
44 #include "bpfilter.h"
45 #include "pflow.h"
46 
47 const struct domain *const domains[] = {
48 #ifdef MPLS
49 	&mplsdomain,
50 #endif
51 #if defined (IPSEC) || defined (TCP_SIGNATURE)
52 	&pfkeydomain,
53 #endif
54 #ifdef INET6
55 	&inet6domain,
56 #endif /* INET6 */
57 	&inetdomain,
58 	&unixdomain,
59 	&routedomain,
60 	NULL
61 };
62 
63 void		pffasttimo(void *);
64 void		pfslowtimo(void *);
65 const struct domain *	pffinddomain(int);
66 
67 void
68 domaininit(void)
69 {
70 	const struct domain *dp;
71 	const struct protosw *pr;
72 	static struct timeout pffast_timeout;
73 	static struct timeout pfslow_timeout;
74 	int i;
75 
76 	for (i = 0; (dp = domains[i]) != NULL; i++) {
77 		if (dp->dom_init)
78 			(*dp->dom_init)();
79 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
80 			if (pr->pr_init)
81 				(*pr->pr_init)();
82 	}
83 
84 	/*
85 	 * max_linkhdr of 64 was chosen to encompass tunnelling
86 	 * traffic in IP payloads, eg, by etherip(4) or gif(4),
87 	 * without needing to prepend an mbuf to fit those
88 	 * headers.
89 	 */
90 	if (max_linkhdr < 64)
91 		max_linkhdr = 64;
92 
93 	max_hdr = max_linkhdr + max_protohdr;
94 	timeout_set_proc(&pffast_timeout, pffasttimo, &pffast_timeout);
95 	timeout_set_proc(&pfslow_timeout, pfslowtimo, &pfslow_timeout);
96 	timeout_add(&pffast_timeout, 1);
97 	timeout_add(&pfslow_timeout, 1);
98 }
99 
100 const struct domain *
101 pffinddomain(int family)
102 {
103 	const struct domain *dp;
104 	int i;
105 
106 	for (i = 0; (dp = domains[i]) != NULL; i++) {
107 		if (dp->dom_family == family)
108 			return (dp);
109 	}
110 	return (NULL);
111 }
112 
113 const struct protosw *
114 pffindtype(int family, int type)
115 {
116 	const struct domain *dp;
117 	const struct protosw *pr;
118 
119 	dp = pffinddomain(family);
120 	if (dp == NULL)
121 		return (NULL);
122 
123 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
124 		if (pr->pr_type && pr->pr_type == type)
125 			return (pr);
126 	return (NULL);
127 }
128 
129 const struct protosw *
130 pffindproto(int family, int protocol, int type)
131 {
132 	const struct domain *dp;
133 	const struct protosw *pr;
134 	const struct protosw *maybe = NULL;
135 
136 	if (family == PF_UNSPEC)
137 		return (NULL);
138 
139 	dp = pffinddomain(family);
140 	if (dp == NULL)
141 		return (NULL);
142 
143 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
144 		if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
145 			return (pr);
146 
147 		if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
148 		    pr->pr_protocol == 0 && maybe == NULL)
149 			maybe = pr;
150 	}
151 	return (maybe);
152 }
153 
154 static int
155 net_link_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
156     void *newp, size_t newlen)
157 {
158 	int node;
159 	int error;
160 
161 	/*
162 	 * All sysctl names at this level are nonterminal.
163 	 */
164 	if (namelen < 2)
165 		return (EISDIR);		/* overloaded */
166 	node = name[0];
167 
168 	namelen--;
169 	name++;
170 
171 	switch (node) {
172 	case NET_LINK_IFRXQ:
173 		error = net_ifiq_sysctl(name, namelen, oldp, oldlenp,
174 		    newp, newlen);
175 		break;
176 
177 	default:
178 		error = ENOPROTOOPT;
179 		break;
180 	}
181 
182 	return (error);
183 }
184 
185 int
186 net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
187     size_t newlen, struct proc *p)
188 {
189 	const struct domain *dp;
190 	const struct protosw *pr;
191 	int error, family, protocol;
192 
193 	/*
194 	 * All sysctl names at this level are nonterminal.
195 	 * Usually: next two components are protocol family and protocol
196 	 *	number, then at least one addition component.
197 	 */
198 	if (namelen < 2)
199 		return (EISDIR);		/* overloaded */
200 	family = name[0];
201 
202 	if (family == PF_UNSPEC)
203 		return (0);
204 	if (family == PF_LINK)
205 		return (net_link_sysctl(name + 1, namelen - 1, oldp, oldlenp,
206 		    newp, newlen));
207 	if (family == PF_UNIX)
208 		return (uipc_sysctl(name + 1, namelen - 1, oldp, oldlenp,
209 		    newp, newlen));
210 #if NBPFILTER > 0
211 	if (family == PF_BPF)
212 		return (bpf_sysctl(name + 1, namelen - 1, oldp, oldlenp,
213 		    newp, newlen));
214 #endif
215 #if NPFLOW > 0
216 	if (family == PF_PFLOW)
217 		return (pflow_sysctl(name + 1, namelen - 1, oldp, oldlenp,
218 		    newp, newlen));
219 #endif
220 #ifdef PIPEX
221 	if (family == PF_PIPEX)
222 		return (pipex_sysctl(name + 1, namelen - 1, oldp, oldlenp,
223 		    newp, newlen));
224 #endif
225 #ifdef MPLS
226 	if (family == PF_MPLS)
227 		return (mpls_sysctl(name + 1, namelen - 1, oldp, oldlenp,
228 		    newp, newlen));
229 #endif
230 	dp = pffinddomain(family);
231 	if (dp == NULL)
232 		return (ENOPROTOOPT);
233 
234 	if (namelen < 3)
235 		return (EISDIR);		/* overloaded */
236 	protocol = name[1];
237 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
238 		if (pr->pr_protocol == protocol && pr->pr_sysctl) {
239 			error = (*pr->pr_sysctl)(name + 2, namelen - 2,
240 			    oldp, oldlenp, newp, newlen);
241 			return (error);
242 		}
243 	return (ENOPROTOOPT);
244 }
245 
246 void
247 pfctlinput(int cmd, struct sockaddr *sa)
248 {
249 	const struct domain *dp;
250 	const struct protosw *pr;
251 	int i;
252 
253 	NET_ASSERT_LOCKED();
254 
255 	for (i = 0; (dp = domains[i]) != NULL; i++) {
256 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
257 			if (pr->pr_ctlinput)
258 				(*pr->pr_ctlinput)(cmd, sa, 0, NULL);
259 	}
260 }
261 
262 void
263 pfslowtimo(void *arg)
264 {
265 	struct timeout *to = (struct timeout *)arg;
266 	const struct domain *dp;
267 	const struct protosw *pr;
268 	int i;
269 
270 	for (i = 0; (dp = domains[i]) != NULL; i++) {
271 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
272 			if (pr->pr_slowtimo)
273 				(*pr->pr_slowtimo)();
274 	}
275 	timeout_add_msec(to, 500);
276 }
277 
278 void
279 pffasttimo(void *arg)
280 {
281 	struct timeout *to = (struct timeout *)arg;
282 	const struct domain *dp;
283 	const struct protosw *pr;
284 	int i;
285 
286 	for (i = 0; (dp = domains[i]) != NULL; i++) {
287 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
288 			if (pr->pr_fasttimo)
289 				(*pr->pr_fasttimo)();
290 	}
291 	timeout_add_msec(to, 200);
292 }
293