xref: /openbsd-src/sys/kern/uipc_domain.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: uipc_domain.c,v 1.28 2008/09/16 15:48:12 gollo 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/time.h>
41 #include <sys/kernel.h>
42 #include <sys/systm.h>
43 #include <sys/proc.h>
44 #include <uvm/uvm_extern.h>
45 #include <sys/sysctl.h>
46 #include <sys/timeout.h>
47 
48 #include "bluetooth.h"
49 #include "bpfilter.h"
50 #include "pflow.h"
51 
52 struct	domain *domains;
53 
54 void		pffasttimo(void *);
55 void		pfslowtimo(void *);
56 struct domain *	pffinddomain(int);
57 
58 #if defined (KEY) || defined (IPSEC) || defined (TCP_SIGNATURE)
59 int pfkey_init(void);
60 #endif /* KEY || IPSEC || TCP_SIGNATURE */
61 
62 #define	ADDDOMAIN(x)	{ \
63 	extern struct domain __CONCAT(x,domain); \
64 	__CONCAT(x,domain.dom_next) = domains; \
65 	domains = &__CONCAT(x,domain); \
66 }
67 
68 void
69 domaininit(void)
70 {
71 	struct domain *dp;
72 	struct protosw *pr;
73 	static struct timeout pffast_timeout;
74 	static struct timeout pfslow_timeout;
75 
76 #undef unix
77 	/*
78 	 * KAME NOTE: ADDDOMAIN(route) is moved to the last part so that
79 	 * it will be initialized as the *first* element.  confusing!
80 	 */
81 #ifndef lint
82 	ADDDOMAIN(unix);
83 #ifdef INET
84 	ADDDOMAIN(inet);
85 #endif
86 #ifdef INET6
87 	ADDDOMAIN(inet6);
88 #endif /* INET6 */
89 #if defined (KEY) || defined (IPSEC) || defined (TCP_SIGNATURE)
90 	pfkey_init();
91 #endif /* KEY || IPSEC */
92 #ifdef NETATALK
93 	ADDDOMAIN(atalk);
94 #endif
95 #ifdef MPLS
96        ADDDOMAIN(mpls);
97 #endif
98 #ifdef NATM
99 	ADDDOMAIN(natm);
100 #endif
101 #ifdef IPSEC
102 #ifdef __KAME__
103 	ADDDOMAIN(key);
104 #endif
105 #endif
106 #if NBLUETOOTH > 0
107 	ADDDOMAIN(bt);
108 #endif
109 	ADDDOMAIN(route);
110 #endif
111 
112 	for (dp = domains; dp; dp = dp->dom_next) {
113 		if (dp->dom_init)
114 			(*dp->dom_init)();
115 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
116 			if (pr->pr_init)
117 				(*pr->pr_init)();
118 	}
119 
120 	if (max_linkhdr < 16)		/* XXX */
121 		max_linkhdr = 16;
122 	max_hdr = max_linkhdr + max_protohdr;
123 	max_datalen = MHLEN - max_hdr;
124 	timeout_set(&pffast_timeout, pffasttimo, &pffast_timeout);
125 	timeout_set(&pfslow_timeout, pfslowtimo, &pfslow_timeout);
126 	timeout_add(&pffast_timeout, 1);
127 	timeout_add(&pfslow_timeout, 1);
128 }
129 
130 struct domain *
131 pffinddomain(int family)
132 {
133 	struct domain *dp;
134 
135 	for (dp = domains; dp != NULL; dp = dp->dom_next)
136 		if (dp->dom_family == family)
137 			return (dp);
138 	return (NULL);
139 }
140 
141 struct protosw *
142 pffindtype(int family, int type)
143 {
144 	struct domain *dp;
145 	struct protosw *pr;
146 
147 	dp = pffinddomain(family);
148 	if (dp == NULL)
149 		return (NULL);
150 
151 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
152 		if (pr->pr_type && pr->pr_type == type)
153 			return (pr);
154 	return (NULL);
155 }
156 
157 struct protosw *
158 pffindproto(int family, int protocol, int type)
159 {
160 	struct domain *dp;
161 	struct protosw *pr;
162 	struct protosw *maybe = NULL;
163 
164 	if (family == 0)
165 		return (NULL);
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_protocol == protocol) && (pr->pr_type == type))
173 			return (pr);
174 
175 		if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
176 		    pr->pr_protocol == 0 && maybe == NULL)
177 			maybe = pr;
178 	}
179 	return (maybe);
180 }
181 
182 int
183 net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
184     size_t newlen, struct proc *p)
185 {
186 	struct domain *dp;
187 	struct protosw *pr;
188 	int family, protocol;
189 
190 	/*
191 	 * All sysctl names at this level are nonterminal.
192 	 * Usually: next two components are protocol family and protocol
193 	 *	number, then at least one addition component.
194 	 */
195 	if (namelen < 2)
196 		return (EISDIR);		/* overloaded */
197 	family = name[0];
198 
199 	if (family == 0)
200 		return (0);
201 #if NBPFILTER > 0
202 	if (family == PF_BPF)
203 		return (bpf_sysctl(name + 1, namelen - 1, oldp, oldlenp,
204 		    newp, newlen));
205 #endif
206 #if NPFLOW > 0
207 	if (family == PF_PFLOW)
208 		return (pflow_sysctl(name + 1, namelen - 1, oldp, oldlenp,
209 		    newp, newlen));
210 #endif
211 	dp = pffinddomain(family);
212 	if (dp == NULL)
213 		return (ENOPROTOOPT);
214 #ifdef MPLS
215 	/* XXX WARNING: big fat ugly hack */
216 	/* stupid net.mpls is special as it does not have a protocol */
217 	if (family == PF_MPLS)
218 		return (dp->dom_protosw[0].pr_sysctl(name + 1, namelen - 1,
219 		    oldp, oldlenp, newp, newlen));
220 #endif
221 
222 	if (namelen < 3)
223 		return (EISDIR);		/* overloaded */
224 	protocol = name[1];
225 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
226 		if (pr->pr_protocol == protocol && pr->pr_sysctl)
227 			return ((*pr->pr_sysctl)(name + 2, namelen - 2,
228 			    oldp, oldlenp, newp, newlen));
229 	return (ENOPROTOOPT);
230 }
231 
232 void
233 pfctlinput(int cmd, struct sockaddr *sa)
234 {
235 	struct domain *dp;
236 	struct protosw *pr;
237 
238 	for (dp = domains; dp; dp = dp->dom_next)
239 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
240 			if (pr->pr_ctlinput)
241 				(*pr->pr_ctlinput)(cmd, sa, NULL);
242 }
243 
244 void
245 pfslowtimo(void *arg)
246 {
247 	struct timeout *to = (struct timeout *)arg;
248 	struct domain *dp;
249 	struct protosw *pr;
250 
251 	for (dp = domains; dp; dp = dp->dom_next)
252 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
253 			if (pr->pr_slowtimo)
254 				(*pr->pr_slowtimo)();
255 	timeout_add(to, hz/2);
256 }
257 
258 void
259 pffasttimo(void *arg)
260 {
261 	struct timeout *to = (struct timeout *)arg;
262 	struct domain *dp;
263 	struct protosw *pr;
264 
265 	for (dp = domains; dp; dp = dp->dom_next)
266 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
267 			if (pr->pr_fasttimo)
268 				(*pr->pr_fasttimo)();
269 	timeout_add(to, hz/5);
270 }
271