1 /* $OpenBSD: uipc_domain.c,v 1.68 2024/08/16 09:20:34 mvs 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_flags(&pffast_timeout, pffasttimo, &pffast_timeout,
94 KCLOCK_NONE, TIMEOUT_PROC | TIMEOUT_MPSAFE);
95 timeout_set_flags(&pfslow_timeout, pfslowtimo, &pfslow_timeout,
96 KCLOCK_NONE, TIMEOUT_PROC | TIMEOUT_MPSAFE);
97 timeout_add(&pffast_timeout, 1);
98 timeout_add(&pfslow_timeout, 1);
99 }
100
101 const struct domain *
pffinddomain(int family)102 pffinddomain(int family)
103 {
104 const struct domain *dp;
105 int i;
106
107 for (i = 0; (dp = domains[i]) != NULL; i++) {
108 if (dp->dom_family == family)
109 return (dp);
110 }
111 return (NULL);
112 }
113
114 const struct protosw *
pffindtype(int family,int type)115 pffindtype(int family, int type)
116 {
117 const struct domain *dp;
118 const struct protosw *pr;
119
120 dp = pffinddomain(family);
121 if (dp == NULL)
122 return (NULL);
123
124 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
125 if (pr->pr_type && pr->pr_type == type)
126 return (pr);
127 return (NULL);
128 }
129
130 const struct protosw *
pffindproto(int family,int protocol,int type)131 pffindproto(int family, int protocol, int type)
132 {
133 const struct domain *dp;
134 const struct protosw *pr;
135 const struct protosw *maybe = NULL;
136
137 if (family == PF_UNSPEC)
138 return (NULL);
139
140 dp = pffinddomain(family);
141 if (dp == NULL)
142 return (NULL);
143
144 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
145 if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
146 return (pr);
147
148 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
149 pr->pr_protocol == 0 && maybe == NULL)
150 maybe = pr;
151 }
152 return (maybe);
153 }
154
155 static int
net_link_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)156 net_link_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
157 void *newp, size_t newlen)
158 {
159 int node;
160 int error;
161
162 /*
163 * All sysctl names at this level are nonterminal.
164 */
165 if (namelen < 2)
166 return (EISDIR); /* overloaded */
167 node = name[0];
168
169 namelen--;
170 name++;
171
172 switch (node) {
173 case NET_LINK_IFRXQ:
174 error = net_ifiq_sysctl(name, namelen, oldp, oldlenp,
175 newp, newlen);
176 break;
177
178 default:
179 error = ENOPROTOOPT;
180 break;
181 }
182
183 return (error);
184 }
185
186 int
net_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)187 net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
188 size_t newlen, struct proc *p)
189 {
190 const struct domain *dp;
191 const struct protosw *pr;
192 int family, protocol;
193
194 /*
195 * All sysctl names at this level are nonterminal.
196 * Usually: next two components are protocol family and protocol
197 * number, then at least one addition component.
198 */
199 if (namelen < 2)
200 return (EISDIR); /* overloaded */
201 family = name[0];
202
203 if (family == PF_UNSPEC)
204 return (0);
205 if (family == PF_LINK)
206 return (net_link_sysctl(name + 1, namelen - 1, oldp, oldlenp,
207 newp, newlen));
208 if (family == PF_UNIX)
209 return (uipc_sysctl(name + 1, namelen - 1, oldp, oldlenp,
210 newp, newlen));
211 #if NBPFILTER > 0
212 if (family == PF_BPF)
213 return (bpf_sysctl(name + 1, namelen - 1, oldp, oldlenp,
214 newp, newlen));
215 #endif
216 #if NPFLOW > 0
217 if (family == PF_PFLOW)
218 return (pflow_sysctl(name + 1, namelen - 1, oldp, oldlenp,
219 newp, newlen));
220 #endif
221 #ifdef PIPEX
222 if (family == PF_PIPEX)
223 return (pipex_sysctl(name + 1, namelen - 1, oldp, oldlenp,
224 newp, newlen));
225 #endif
226 #ifdef MPLS
227 if (family == PF_MPLS)
228 return (mpls_sysctl(name + 1, namelen - 1, oldp, oldlenp,
229 newp, newlen));
230 #endif
231 dp = pffinddomain(family);
232 if (dp == NULL)
233 return (ENOPROTOOPT);
234
235 if (namelen < 3)
236 return (EISDIR); /* overloaded */
237 protocol = name[1];
238 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
239 if (pr->pr_protocol == protocol && pr->pr_sysctl) {
240 size_t savelen;
241 int error;
242
243 if ((pr->pr_flags & PR_MPSYSCTL) == 0) {
244 savelen = *oldlenp;
245 if ((error = sysctl_vslock(oldp, savelen)))
246 return (error);
247 }
248 error = (*pr->pr_sysctl)(name + 2, namelen - 2,
249 oldp, oldlenp, newp, newlen);
250 if ((pr->pr_flags & PR_MPSYSCTL) == 0)
251 sysctl_vsunlock(oldp, savelen);
252
253 return (error);
254 }
255 return (ENOPROTOOPT);
256 }
257
258 void
pfctlinput(int cmd,struct sockaddr * sa)259 pfctlinput(int cmd, struct sockaddr *sa)
260 {
261 const struct domain *dp;
262 const struct protosw *pr;
263 int i;
264
265 NET_ASSERT_LOCKED();
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_ctlinput)
270 (*pr->pr_ctlinput)(cmd, sa, 0, NULL);
271 }
272 }
273
274 void
pfslowtimo(void * arg)275 pfslowtimo(void *arg)
276 {
277 struct timeout *to = (struct timeout *)arg;
278 const struct domain *dp;
279 const struct protosw *pr;
280 int i;
281
282 for (i = 0; (dp = domains[i]) != NULL; i++) {
283 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
284 if (pr->pr_slowtimo)
285 (*pr->pr_slowtimo)();
286 }
287 timeout_add_msec(to, 500);
288 }
289
290 void
pffasttimo(void * arg)291 pffasttimo(void *arg)
292 {
293 struct timeout *to = (struct timeout *)arg;
294 const struct domain *dp;
295 const struct protosw *pr;
296 int i;
297
298 for (i = 0; (dp = domains[i]) != NULL; i++) {
299 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
300 if (pr->pr_fasttimo)
301 (*pr->pr_fasttimo)();
302 }
303 timeout_add_msec(to, 200);
304 }
305