xref: /openbsd/sys/kern/uipc_domain.c (revision 66bd633e)
1 /*	$OpenBSD: uipc_domain.c,v 1.65 2024/01/11 14:15:11 bluhm 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 
66 void
domaininit(void)67 domaininit(void)
68 {
69 	const struct domain *dp;
70 	const struct protosw *pr;
71 	static struct timeout pffast_timeout;
72 	static struct timeout pfslow_timeout;
73 	int i;
74 
75 	for (i = 0; (dp = domains[i]) != NULL; i++) {
76 		if (dp->dom_init)
77 			(*dp->dom_init)();
78 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
79 			if (pr->pr_init)
80 				(*pr->pr_init)();
81 	}
82 
83 	/*
84 	 * max_linkhdr of 64 was chosen to encompass tunnelling
85 	 * traffic in IP payloads, eg, by etherip(4) or gif(4),
86 	 * without needing to prepend an mbuf to fit those
87 	 * headers.
88 	 */
89 	if (max_linkhdr < 64)
90 		max_linkhdr = 64;
91 
92 	max_hdr = max_linkhdr + max_protohdr;
93 	timeout_set_proc(&pffast_timeout, pffasttimo, &pffast_timeout);
94 	timeout_set_proc(&pfslow_timeout, pfslowtimo, &pfslow_timeout);
95 	timeout_add(&pffast_timeout, 1);
96 	timeout_add(&pfslow_timeout, 1);
97 }
98 
99 const struct domain *
pffinddomain(int family)100 pffinddomain(int family)
101 {
102 	const struct domain *dp;
103 	int i;
104 
105 	for (i = 0; (dp = domains[i]) != NULL; i++) {
106 		if (dp->dom_family == family)
107 			return (dp);
108 	}
109 	return (NULL);
110 }
111 
112 const struct protosw *
pffindtype(int family,int type)113 pffindtype(int family, int type)
114 {
115 	const struct domain *dp;
116 	const struct protosw *pr;
117 
118 	dp = pffinddomain(family);
119 	if (dp == NULL)
120 		return (NULL);
121 
122 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
123 		if (pr->pr_type && pr->pr_type == type)
124 			return (pr);
125 	return (NULL);
126 }
127 
128 const struct protosw *
pffindproto(int family,int protocol,int type)129 pffindproto(int family, int protocol, int type)
130 {
131 	const struct domain *dp;
132 	const struct protosw *pr;
133 	const struct protosw *maybe = NULL;
134 
135 	if (family == PF_UNSPEC)
136 		return (NULL);
137 
138 	dp = pffinddomain(family);
139 	if (dp == NULL)
140 		return (NULL);
141 
142 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
143 		if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
144 			return (pr);
145 
146 		if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
147 		    pr->pr_protocol == 0 && maybe == NULL)
148 			maybe = pr;
149 	}
150 	return (maybe);
151 }
152 
153 static int
net_link_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)154 net_link_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
155     void *newp, size_t newlen)
156 {
157 	int node;
158 	int error;
159 
160 	/*
161 	 * All sysctl names at this level are nonterminal.
162 	 */
163 	if (namelen < 2)
164 		return (EISDIR);		/* overloaded */
165 	node = name[0];
166 
167 	namelen--;
168 	name++;
169 
170 	switch (node) {
171 	case NET_LINK_IFRXQ:
172 		error = net_ifiq_sysctl(name, namelen, oldp, oldlenp,
173 		    newp, newlen);
174 		break;
175 
176 	default:
177 		error = ENOPROTOOPT;
178 		break;
179 	}
180 
181 	return (error);
182 }
183 
184 int
net_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)185 net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
186     size_t newlen, struct proc *p)
187 {
188 	const struct domain *dp;
189 	const struct protosw *pr;
190 	int family, protocol;
191 
192 	/*
193 	 * All sysctl names at this level are nonterminal.
194 	 * Usually: next two components are protocol family and protocol
195 	 *	number, then at least one addition component.
196 	 */
197 	if (namelen < 2)
198 		return (EISDIR);		/* overloaded */
199 	family = name[0];
200 
201 	if (family == PF_UNSPEC)
202 		return (0);
203 	if (family == PF_LINK)
204 		return (net_link_sysctl(name + 1, namelen - 1, oldp, oldlenp,
205 		    newp, newlen));
206 	if (family == PF_UNIX)
207 		return (uipc_sysctl(name + 1, namelen - 1, oldp, oldlenp,
208 		    newp, newlen));
209 #if NBPFILTER > 0
210 	if (family == PF_BPF)
211 		return (bpf_sysctl(name + 1, namelen - 1, oldp, oldlenp,
212 		    newp, newlen));
213 #endif
214 #if NPFLOW > 0
215 	if (family == PF_PFLOW)
216 		return (pflow_sysctl(name + 1, namelen - 1, oldp, oldlenp,
217 		    newp, newlen));
218 #endif
219 #ifdef PIPEX
220 	if (family == PF_PIPEX)
221 		return (pipex_sysctl(name + 1, namelen - 1, oldp, oldlenp,
222 		    newp, newlen));
223 #endif
224 #ifdef MPLS
225 	if (family == PF_MPLS)
226 		return (mpls_sysctl(name + 1, namelen - 1, oldp, oldlenp,
227 		    newp, newlen));
228 #endif
229 	dp = pffinddomain(family);
230 	if (dp == NULL)
231 		return (ENOPROTOOPT);
232 
233 	if (namelen < 3)
234 		return (EISDIR);		/* overloaded */
235 	protocol = name[1];
236 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
237 		if (pr->pr_protocol == protocol && pr->pr_sysctl)
238 			return ((*pr->pr_sysctl)(name + 2, namelen - 2,
239 			    oldp, oldlenp, newp, newlen));
240 	return (ENOPROTOOPT);
241 }
242 
243 void
pfctlinput(int cmd,struct sockaddr * sa)244 pfctlinput(int cmd, struct sockaddr *sa)
245 {
246 	const struct domain *dp;
247 	const struct protosw *pr;
248 	int i;
249 
250 	NET_ASSERT_LOCKED();
251 
252 	for (i = 0; (dp = domains[i]) != NULL; i++) {
253 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
254 			if (pr->pr_ctlinput)
255 				(*pr->pr_ctlinput)(cmd, sa, 0, NULL);
256 	}
257 }
258 
259 void
pfslowtimo(void * arg)260 pfslowtimo(void *arg)
261 {
262 	struct timeout *to = (struct timeout *)arg;
263 	const struct domain *dp;
264 	const struct protosw *pr;
265 	int i;
266 
267 	for (i = 0; (dp = domains[i]) != NULL; i++) {
268 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
269 			if (pr->pr_slowtimo)
270 				(*pr->pr_slowtimo)();
271 	}
272 	timeout_add_msec(to, 500);
273 }
274 
275 void
pffasttimo(void * arg)276 pffasttimo(void *arg)
277 {
278 	struct timeout *to = (struct timeout *)arg;
279 	const struct domain *dp;
280 	const struct protosw *pr;
281 	int i;
282 
283 	for (i = 0; (dp = domains[i]) != NULL; i++) {
284 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
285 			if (pr->pr_fasttimo)
286 				(*pr->pr_fasttimo)();
287 	}
288 	timeout_add_msec(to, 200);
289 }
290