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