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