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