uipc_domain.c revision 1.36 1 /* $NetBSD: uipc_domain.c,v 1.36 2001/11/12 15:25:30 lukem 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.36 2001/11/12 15:25:30 lukem 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 callout pffasttimo_ch, pfslowtimo_ch;
66
67 /*
68 * Current time values for fast and slow timeouts. We can use u_int
69 * relatively safely. The fast timer will roll over in 27 years and
70 * the slow timer in 68 years.
71 */
72 u_int pfslowtimo_now;
73 u_int pffasttimo_now;
74
75 #define ADDDOMAIN(x) { \
76 extern struct domain __CONCAT(x,domain); \
77 __CONCAT(x,domain.dom_next) = domains; \
78 domains = &__CONCAT(x,domain); \
79 }
80
81 void
82 domaininit()
83 {
84 struct domain *dp;
85 struct protosw *pr;
86
87 #undef unix
88 /*
89 * KAME NOTE: ADDDOMAIN(route) is moved to the last part so that
90 * it will be initialized as the *first* element. confusing!
91 */
92 #ifndef lint
93 ADDDOMAIN(unix);
94 #ifdef INET
95 ADDDOMAIN(inet);
96 #endif
97 #ifdef INET6
98 ADDDOMAIN(inet6);
99 #endif
100 #ifdef NS
101 ADDDOMAIN(ns);
102 #endif
103 #ifdef ISO
104 ADDDOMAIN(iso);
105 #endif
106 #ifdef CCITT
107 ADDDOMAIN(ccitt);
108 #endif
109 #ifdef NATM
110 ADDDOMAIN(natm);
111 #endif
112 #ifdef NETATALK
113 ADDDOMAIN(atalk);
114 #endif
115 #ifdef IPSEC
116 ADDDOMAIN(key);
117 #endif
118 #ifdef INET
119 #if NARP > 0
120 ADDDOMAIN(arp);
121 #endif
122 #endif
123 ADDDOMAIN(route);
124 #endif /* ! lint */
125
126 for (dp = domains; dp; dp = dp->dom_next) {
127 if (dp->dom_init)
128 (*dp->dom_init)();
129 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
130 if (pr->pr_init)
131 (*pr->pr_init)();
132 }
133
134 if (max_linkhdr < 16) /* XXX */
135 max_linkhdr = 16;
136 max_hdr = max_linkhdr + max_protohdr;
137 max_datalen = MHLEN - max_hdr;
138
139 callout_init(&pffasttimo_ch);
140 callout_init(&pfslowtimo_ch);
141
142 callout_reset(&pffasttimo_ch, 1, pffasttimo, NULL);
143 callout_reset(&pfslowtimo_ch, 1, pfslowtimo, NULL);
144 }
145
146 struct domain *
147 pffinddomain(family)
148 int family;
149 {
150 struct domain *dp;
151
152 for (dp = domains; dp != NULL; dp = dp->dom_next)
153 if (dp->dom_family == family)
154 return (dp);
155 return (NULL);
156 }
157
158 struct protosw *
159 pffindtype(family, type)
160 int family, type;
161 {
162 struct domain *dp;
163 struct protosw *pr;
164
165 dp = pffinddomain(family);
166 if (dp == NULL)
167 return (NULL);
168
169 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
170 if (pr->pr_type && pr->pr_type == type)
171 return (pr);
172
173 return (NULL);
174 }
175
176 struct protosw *
177 pffindproto(family, protocol, type)
178 int family, protocol, type;
179 {
180 struct domain *dp;
181 struct protosw *pr;
182 struct protosw *maybe = NULL;
183
184 if (family == 0)
185 return (NULL);
186
187 dp = pffinddomain(family);
188 if (dp == NULL)
189 return (NULL);
190
191 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
192 if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
193 return (pr);
194
195 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
196 pr->pr_protocol == 0 && maybe == NULL)
197 maybe = pr;
198 }
199 return (maybe);
200 }
201
202 int
203 net_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
204 int *name;
205 u_int namelen;
206 void *oldp;
207 size_t *oldlenp;
208 void *newp;
209 size_t newlen;
210 struct proc *p;
211 {
212 struct domain *dp;
213 struct protosw *pr;
214 int family, protocol;
215
216 /*
217 * All sysctl names at this level are nonterminal.
218 * PF_KEY: next component is protocol family, and then at least one
219 * additional component.
220 * usually: next two components are protocol family and protocol
221 * number, then at least one addition component.
222 */
223 if (namelen < 2)
224 return (EISDIR); /* overloaded */
225 family = name[0];
226
227 if (family == 0)
228 return (0);
229
230 dp = pffinddomain(family);
231 if (dp == NULL)
232 return (ENOPROTOOPT);
233
234 switch (family) {
235 #ifdef IPSEC
236 case PF_KEY:
237 pr = dp->dom_protosw;
238 if (pr->pr_sysctl)
239 return ((*pr->pr_sysctl)(name + 1, namelen - 1,
240 oldp, oldlenp, newp, newlen));
241 return (ENOPROTOOPT);
242 #endif
243 default:
244 break;
245 }
246 if (namelen < 3)
247 return (EISDIR); /* overloaded */
248 protocol = name[1];
249 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
250 if (pr->pr_protocol == protocol && pr->pr_sysctl)
251 return ((*pr->pr_sysctl)(name + 2, namelen - 2,
252 oldp, oldlenp, newp, newlen));
253 return (ENOPROTOOPT);
254 }
255
256 void
257 pfctlinput(cmd, sa)
258 int cmd;
259 struct sockaddr *sa;
260 {
261 struct domain *dp;
262 struct protosw *pr;
263
264 for (dp = domains; dp; dp = dp->dom_next)
265 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
266 if (pr->pr_ctlinput)
267 (*pr->pr_ctlinput)(cmd, sa, NULL);
268 }
269
270 void
271 pfctlinput2(cmd, sa, ctlparam)
272 int cmd;
273 struct sockaddr *sa;
274 void *ctlparam;
275 {
276 struct domain *dp;
277 struct protosw *pr;
278
279 if (!sa)
280 return;
281 for (dp = domains; dp; dp = dp->dom_next) {
282 /*
283 * the check must be made by xx_ctlinput() anyways, to
284 * make sure we use data item pointed to by ctlparam in
285 * correct way. the following check is made just for safety.
286 */
287 if (dp->dom_family != sa->sa_family)
288 continue;
289
290 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
291 if (pr->pr_ctlinput)
292 (*pr->pr_ctlinput)(cmd, sa, ctlparam);
293 }
294 }
295
296 void
297 pfslowtimo(arg)
298 void *arg;
299 {
300 struct domain *dp;
301 struct protosw *pr;
302
303 pfslowtimo_now++;
304
305 for (dp = domains; dp; dp = dp->dom_next)
306 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
307 if (pr->pr_slowtimo)
308 (*pr->pr_slowtimo)();
309 callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL);
310 }
311
312 void
313 pffasttimo(arg)
314 void *arg;
315 {
316 struct domain *dp;
317 struct protosw *pr;
318
319 pffasttimo_now++;
320
321 for (dp = domains; dp; dp = dp->dom_next)
322 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
323 if (pr->pr_fasttimo)
324 (*pr->pr_fasttimo)();
325 callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL);
326 }
327