uipc_domain.c revision 1.34.2.2 1 /* $NetBSD: uipc_domain.c,v 1.34.2.2 2002/06/20 03:47:24 nathanw Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)uipc_domain.c 8.3 (Berkeley) 2/14/95
36 */
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.34.2.2 2002/06/20 03:47:24 nathanw Exp $");
40
41 #include "opt_inet.h"
42 #include "opt_ipsec.h"
43 #include "opt_atalk.h"
44 #include "opt_ccitt.h"
45 #include "opt_iso.h"
46 #include "opt_ns.h"
47 #include "opt_natm.h"
48 #include "arp.h"
49
50 #include <sys/param.h>
51 #include <sys/socket.h>
52 #include <sys/protosw.h>
53 #include <sys/domain.h>
54 #include <sys/mbuf.h>
55 #include <sys/time.h>
56 #include <sys/kernel.h>
57 #include <sys/systm.h>
58 #include <sys/callout.h>
59 #include <sys/proc.h>
60 #include <sys/sysctl.h>
61
62 void pffasttimo __P((void *));
63 void pfslowtimo __P((void *));
64
65 struct domain *domains;
66
67 struct callout pffasttimo_ch, pfslowtimo_ch;
68
69 /*
70 * Current time values for fast and slow timeouts. We can use u_int
71 * relatively safely. The fast timer will roll over in 27 years and
72 * the slow timer in 68 years.
73 */
74 u_int pfslowtimo_now;
75 u_int pffasttimo_now;
76
77 #define ADDDOMAIN(x) { \
78 extern struct domain __CONCAT(x,domain); \
79 __CONCAT(x,domain.dom_next) = domains; \
80 domains = &__CONCAT(x,domain); \
81 }
82
83 void
84 domaininit()
85 {
86 struct domain *dp;
87 struct protosw *pr;
88
89 #undef unix
90 /*
91 * KAME NOTE: ADDDOMAIN(route) is moved to the last part so that
92 * it will be initialized as the *first* element. confusing!
93 */
94 #ifndef lint
95 ADDDOMAIN(unix);
96 #ifdef INET
97 ADDDOMAIN(inet);
98 #endif
99 #ifdef INET6
100 ADDDOMAIN(inet6);
101 #endif
102 #ifdef NS
103 ADDDOMAIN(ns);
104 #endif
105 #ifdef ISO
106 ADDDOMAIN(iso);
107 #endif
108 #ifdef CCITT
109 ADDDOMAIN(ccitt);
110 #endif
111 #ifdef NATM
112 ADDDOMAIN(natm);
113 #endif
114 #ifdef NETATALK
115 ADDDOMAIN(atalk);
116 #endif
117 #ifdef IPSEC
118 ADDDOMAIN(key);
119 #endif
120 #ifdef INET
121 #if NARP > 0
122 ADDDOMAIN(arp);
123 #endif
124 #endif
125 ADDDOMAIN(route);
126 #endif /* ! lint */
127
128 for (dp = domains; dp; dp = dp->dom_next) {
129 if (dp->dom_init)
130 (*dp->dom_init)();
131 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
132 if (pr->pr_init)
133 (*pr->pr_init)();
134 }
135
136 if (max_linkhdr < 16) /* XXX */
137 max_linkhdr = 16;
138 max_hdr = max_linkhdr + max_protohdr;
139 max_datalen = MHLEN - max_hdr;
140
141 callout_init(&pffasttimo_ch);
142 callout_init(&pfslowtimo_ch);
143
144 callout_reset(&pffasttimo_ch, 1, pffasttimo, NULL);
145 callout_reset(&pfslowtimo_ch, 1, pfslowtimo, NULL);
146 }
147
148 struct domain *
149 pffinddomain(family)
150 int family;
151 {
152 struct domain *dp;
153
154 for (dp = domains; dp != NULL; dp = dp->dom_next)
155 if (dp->dom_family == family)
156 return (dp);
157 return (NULL);
158 }
159
160 struct protosw *
161 pffindtype(family, type)
162 int family, type;
163 {
164 struct domain *dp;
165 struct protosw *pr;
166
167 dp = pffinddomain(family);
168 if (dp == NULL)
169 return (NULL);
170
171 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
172 if (pr->pr_type && pr->pr_type == type)
173 return (pr);
174
175 return (NULL);
176 }
177
178 struct protosw *
179 pffindproto(family, protocol, type)
180 int family, protocol, type;
181 {
182 struct domain *dp;
183 struct protosw *pr;
184 struct protosw *maybe = NULL;
185
186 if (family == 0)
187 return (NULL);
188
189 dp = pffinddomain(family);
190 if (dp == NULL)
191 return (NULL);
192
193 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
194 if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
195 return (pr);
196
197 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
198 pr->pr_protocol == 0 && maybe == NULL)
199 maybe = pr;
200 }
201 return (maybe);
202 }
203
204 int
205 net_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
206 int *name;
207 u_int namelen;
208 void *oldp;
209 size_t *oldlenp;
210 void *newp;
211 size_t newlen;
212 struct proc *p;
213 {
214 struct domain *dp;
215 struct protosw *pr;
216 int family, protocol;
217
218 /*
219 * All sysctl names at this level are nonterminal.
220 * PF_KEY: next component is protocol family, and then at least one
221 * additional component.
222 * usually: next two components are protocol family and protocol
223 * number, then at least one addition component.
224 */
225 if (namelen < 2)
226 return (EISDIR); /* overloaded */
227 family = name[0];
228
229 if (family == 0)
230 return (0);
231
232 dp = pffinddomain(family);
233 if (dp == NULL)
234 return (ENOPROTOOPT);
235
236 switch (family) {
237 #ifdef IPSEC
238 case PF_KEY:
239 pr = dp->dom_protosw;
240 if (pr->pr_sysctl)
241 return ((*pr->pr_sysctl)(name + 1, namelen - 1,
242 oldp, oldlenp, newp, newlen));
243 return (ENOPROTOOPT);
244 #endif
245 default:
246 break;
247 }
248 if (namelen < 3)
249 return (EISDIR); /* overloaded */
250 protocol = name[1];
251 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
252 if (pr->pr_protocol == protocol && pr->pr_sysctl)
253 return ((*pr->pr_sysctl)(name + 2, namelen - 2,
254 oldp, oldlenp, newp, newlen));
255 return (ENOPROTOOPT);
256 }
257
258 void
259 pfctlinput(cmd, sa)
260 int cmd;
261 struct sockaddr *sa;
262 {
263 struct domain *dp;
264 struct protosw *pr;
265
266 for (dp = domains; dp; dp = dp->dom_next)
267 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
268 if (pr->pr_ctlinput)
269 (*pr->pr_ctlinput)(cmd, sa, NULL);
270 }
271
272 void
273 pfctlinput2(cmd, sa, ctlparam)
274 int cmd;
275 struct sockaddr *sa;
276 void *ctlparam;
277 {
278 struct domain *dp;
279 struct protosw *pr;
280
281 if (!sa)
282 return;
283 for (dp = domains; dp; dp = dp->dom_next) {
284 /*
285 * the check must be made by xx_ctlinput() anyways, to
286 * make sure we use data item pointed to by ctlparam in
287 * correct way. the following check is made just for safety.
288 */
289 if (dp->dom_family != sa->sa_family)
290 continue;
291
292 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
293 if (pr->pr_ctlinput)
294 (*pr->pr_ctlinput)(cmd, sa, ctlparam);
295 }
296 }
297
298 void
299 pfslowtimo(arg)
300 void *arg;
301 {
302 struct domain *dp;
303 struct protosw *pr;
304
305 pfslowtimo_now++;
306
307 for (dp = domains; dp; dp = dp->dom_next)
308 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
309 if (pr->pr_slowtimo)
310 (*pr->pr_slowtimo)();
311 callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL);
312 }
313
314 void
315 pffasttimo(arg)
316 void *arg;
317 {
318 struct domain *dp;
319 struct protosw *pr;
320
321 pffasttimo_now++;
322
323 for (dp = domains; dp; dp = dp->dom_next)
324 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
325 if (pr->pr_fasttimo)
326 (*pr->pr_fasttimo)();
327 callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL);
328 }
329