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