xref: /netbsd-src/sys/kern/uipc_domain.c (revision 220b5c059a84c51ea44107ea8951a57ffaecdc8c)
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