uipc_domain.c revision 1.49 1 /* $NetBSD: uipc_domain.c,v 1.49 2005/01/23 18:41:56 matt 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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)uipc_domain.c 8.3 (Berkeley) 2/14/95
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.49 2005/01/23 18:41:56 matt Exp $");
36
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/protosw.h>
40 #include <sys/domain.h>
41 #include <sys/mbuf.h>
42 #include <sys/time.h>
43 #include <sys/kernel.h>
44 #include <sys/systm.h>
45 #include <sys/callout.h>
46 #include <sys/queue.h>
47 #include <sys/proc.h>
48 #include <sys/sysctl.h>
49
50 void pffasttimo(void *);
51 void pfslowtimo(void *);
52
53 struct domainhead domains = STAILQ_HEAD_INITIALIZER(domains);
54
55 struct callout pffasttimo_ch, pfslowtimo_ch;
56
57 /*
58 * Current time values for fast and slow timeouts. We can use u_int
59 * relatively safely. The fast timer will roll over in 27 years and
60 * the slow timer in 68 years.
61 */
62 u_int pfslowtimo_now;
63 u_int pffasttimo_now;
64
65 void
66 domaininit()
67 {
68 __link_set_decl(domains, struct domain);
69 struct domain * const * dpp;
70 struct domain *rt_domain = NULL;
71
72 /*
73 * Add all of the domains. Make sure the PF_ROUTE
74 * domain is added last.
75 */
76 __link_set_foreach(dpp, domains) {
77 if ((*dpp)->dom_family == PF_ROUTE)
78 rt_domain = *dpp;
79 else
80 domain_attach(*dpp);
81 }
82 if (rt_domain)
83 domain_attach(rt_domain);
84
85 callout_init(&pffasttimo_ch);
86 callout_init(&pfslowtimo_ch);
87
88 callout_reset(&pffasttimo_ch, 1, pffasttimo, NULL);
89 callout_reset(&pfslowtimo_ch, 1, pfslowtimo, NULL);
90 }
91
92 void
93 domain_attach(struct domain *dp)
94 {
95 const struct protosw *pr;
96
97 STAILQ_INSERT_TAIL(&domains, dp, dom_link);
98
99 if (dp->dom_init)
100 (*dp->dom_init)();
101
102 #ifdef MBUFTRACE
103 if (dp->dom_mowner.mo_name[0] == '\0') {
104 strncpy(dp->dom_mowner.mo_name, dp->dom_name,
105 sizeof(dp->dom_mowner.mo_name));
106 MOWNER_ATTACH(&dp->dom_mowner);
107 }
108 #endif
109 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
110 if (pr->pr_init)
111 (*pr->pr_init)();
112 }
113
114 if (max_linkhdr < 16) /* XXX */
115 max_linkhdr = 16;
116 max_hdr = max_linkhdr + max_protohdr;
117 max_datalen = MHLEN - max_hdr;
118 }
119
120 struct domain *
121 pffinddomain(int family)
122 {
123 struct domain *dp;
124
125 DOMAIN_FOREACH(dp)
126 if (dp->dom_family == family)
127 return (dp);
128 return (NULL);
129 }
130
131 const struct protosw *
132 pffindtype(int family, int type)
133 {
134 struct domain *dp;
135 const struct protosw *pr;
136
137 dp = pffinddomain(family);
138 if (dp == NULL)
139 return (NULL);
140
141 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
142 if (pr->pr_type && pr->pr_type == type)
143 return (pr);
144
145 return (NULL);
146 }
147
148 const struct protosw *
149 pffindproto(int family, int protocol, int type)
150 {
151 struct domain *dp;
152 const struct protosw *pr;
153 const struct protosw *maybe = NULL;
154
155 if (family == 0)
156 return (NULL);
157
158 dp = pffinddomain(family);
159 if (dp == NULL)
160 return (NULL);
161
162 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
163 if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
164 return (pr);
165
166 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
167 pr->pr_protocol == 0 && maybe == NULL)
168 maybe = pr;
169 }
170 return (maybe);
171 }
172
173 SYSCTL_SETUP(sysctl_net_setup, "sysctl net subtree setup")
174 {
175 sysctl_createv(clog, 0, NULL, NULL,
176 CTLFLAG_PERMANENT,
177 CTLTYPE_NODE, "net", NULL,
178 NULL, 0, NULL, 0,
179 CTL_NET, CTL_EOL);
180
181 sysctl_createv(clog, 0, NULL, NULL,
182 CTLFLAG_PERMANENT,
183 CTLTYPE_NODE, "local",
184 SYSCTL_DESCR("PF_LOCAL related settings"),
185 NULL, 0, NULL, 0,
186 CTL_NET, PF_LOCAL, CTL_EOL);
187
188 /*
189 * other protocols are expected to have their own setup
190 * routines that will do everything. we end up not having
191 * anything at all to do.
192 */
193 }
194
195 void
196 pfctlinput(int cmd, struct sockaddr *sa)
197 {
198 struct domain *dp;
199 const struct protosw *pr;
200
201 DOMAIN_FOREACH(dp)
202 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
203 if (pr->pr_ctlinput)
204 (*pr->pr_ctlinput)(cmd, sa, NULL);
205 }
206
207 void
208 pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam)
209 {
210 struct domain *dp;
211 const struct protosw *pr;
212
213 if (!sa)
214 return;
215
216 DOMAIN_FOREACH(dp) {
217 /*
218 * the check must be made by xx_ctlinput() anyways, to
219 * make sure we use data item pointed to by ctlparam in
220 * correct way. the following check is made just for safety.
221 */
222 if (dp->dom_family != sa->sa_family)
223 continue;
224
225 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
226 if (pr->pr_ctlinput)
227 (*pr->pr_ctlinput)(cmd, sa, ctlparam);
228 }
229 }
230
231 void
232 pfslowtimo(void *arg)
233 {
234 struct domain *dp;
235 const struct protosw *pr;
236
237 pfslowtimo_now++;
238
239 DOMAIN_FOREACH(dp) {
240 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
241 if (pr->pr_slowtimo)
242 (*pr->pr_slowtimo)();
243 }
244 callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL);
245 }
246
247 void
248 pffasttimo(void *arg)
249 {
250 struct domain *dp;
251 const struct protosw *pr;
252
253 pffasttimo_now++;
254
255 DOMAIN_FOREACH(dp) {
256 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
257 if (pr->pr_fasttimo)
258 (*pr->pr_fasttimo)();
259 }
260 callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL);
261 }
262