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