raw_usrreq.c revision 1.16 1 /* $NetBSD: raw_usrreq.c,v 1.16 2001/11/05 18:02:16 matt Exp $ */
2
3 /*
4 * Copyright (c) 1980, 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 * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93
36 */
37
38 #include <sys/param.h>
39 #include <sys/mbuf.h>
40 #include <sys/domain.h>
41 #include <sys/protosw.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/errno.h>
45 #include <sys/systm.h>
46 #include <sys/proc.h>
47
48 #include <net/if.h>
49 #include <net/route.h>
50 #include <net/netisr.h>
51 #include <net/raw_cb.h>
52
53 #include <machine/stdarg.h>
54 /*
55 * Initialize raw connection block q.
56 */
57 void
58 raw_init()
59 {
60
61 LIST_INIT(&rawcb);
62 }
63
64
65 /*
66 * Raw protocol input routine. Find the socket
67 * associated with the packet(s) and move them over. If
68 * nothing exists for this packet, drop it.
69 */
70 /*
71 * Raw protocol interface.
72 */
73 void
74 #if __STDC__
75 raw_input(struct mbuf *m0, ...)
76 #else
77 raw_input(m0, va_alist)
78 struct mbuf *m0;
79 va_dcl
80 #endif
81 {
82 struct rawcb *rp;
83 struct mbuf *m = m0;
84 int sockets = 0;
85 struct socket *last;
86 va_list ap;
87 struct sockproto *proto;
88 struct sockaddr *src, *dst;
89
90 va_start(ap, m0);
91 proto = va_arg(ap, struct sockproto *);
92 src = va_arg(ap, struct sockaddr *);
93 dst = va_arg(ap, struct sockaddr *);
94 va_end(ap);
95
96 last = 0;
97 LIST_FOREACH(rp, &rawcb, rcb_list) {
98 if (rp->rcb_proto.sp_family != proto->sp_family)
99 continue;
100 if (rp->rcb_proto.sp_protocol &&
101 rp->rcb_proto.sp_protocol != proto->sp_protocol)
102 continue;
103 /*
104 * We assume the lower level routines have
105 * placed the address in a canonical format
106 * suitable for a structure comparison.
107 *
108 * Note that if the lengths are not the same
109 * the comparison will fail at the first byte.
110 */
111 #define equal(a1, a2) \
112 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
113 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
114 continue;
115 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
116 continue;
117 if (last) {
118 struct mbuf *n;
119 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
120 if (sbappendaddr(&last->so_rcv, src,
121 n, (struct mbuf *)0) == 0)
122 /* should notify about lost packet */
123 m_freem(n);
124 else {
125 sorwakeup(last);
126 sockets++;
127 }
128 }
129 }
130 last = rp->rcb_socket;
131 }
132 if (last) {
133 if (sbappendaddr(&last->so_rcv, src,
134 m, (struct mbuf *)0) == 0)
135 m_freem(m);
136 else {
137 sorwakeup(last);
138 sockets++;
139 }
140 } else
141 m_freem(m);
142 }
143
144 /*ARGSUSED*/
145 void *
146 raw_ctlinput(cmd, arg, d)
147 int cmd;
148 struct sockaddr *arg;
149 void *d;
150 {
151
152 if (cmd < 0 || cmd > PRC_NCMDS)
153 return NULL;
154 return NULL;
155 /* INCOMPLETE */
156 }
157
158 void
159 raw_setsockaddr(rp, nam)
160 struct rawcb *rp;
161 struct mbuf *nam;
162 {
163
164 nam->m_len = rp->rcb_laddr->sa_len;
165 bcopy(rp->rcb_laddr, mtod(nam, caddr_t), (size_t)nam->m_len);
166 }
167
168 void
169 raw_setpeeraddr(rp, nam)
170 struct rawcb *rp;
171 struct mbuf *nam;
172 {
173
174 nam->m_len = rp->rcb_faddr->sa_len;
175 bcopy(rp->rcb_faddr, mtod(nam, caddr_t), (size_t)nam->m_len);
176 }
177
178 /*ARGSUSED*/
179 int
180 raw_usrreq(so, req, m, nam, control, p)
181 struct socket *so;
182 int req;
183 struct mbuf *m, *nam, *control;
184 struct proc *p;
185 {
186 struct rawcb *rp;
187 int s;
188 int error = 0;
189
190 if (req == PRU_CONTROL)
191 return (EOPNOTSUPP);
192
193 s = splsoftnet();
194 rp = sotorawcb(so);
195 #ifdef DIAGNOSTIC
196 if (req != PRU_SEND && req != PRU_SENDOOB && control)
197 panic("raw_usrreq: unexpected control mbuf");
198 #endif
199 if (rp == 0 && req != PRU_ATTACH) {
200 error = EINVAL;
201 goto release;
202 }
203
204 switch (req) {
205
206 /*
207 * Allocate a raw control block and fill in the
208 * necessary info to allow packets to be routed to
209 * the appropriate raw interface routine.
210 */
211 case PRU_ATTACH:
212 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) {
213 error = EACCES;
214 break;
215 }
216 error = raw_attach(so, (int)(long)nam);
217 break;
218
219 /*
220 * Destroy state just before socket deallocation.
221 * Flush data or not depending on the options.
222 */
223 case PRU_DETACH:
224 raw_detach(rp);
225 break;
226
227 /*
228 * If a socket isn't bound to a single address,
229 * the raw input routine will hand it anything
230 * within that protocol family (assuming there's
231 * nothing else around it should go to).
232 */
233 case PRU_BIND:
234 case PRU_LISTEN:
235 case PRU_CONNECT:
236 case PRU_CONNECT2:
237 error = EOPNOTSUPP;
238 break;
239
240 case PRU_DISCONNECT:
241 soisdisconnected(so);
242 raw_disconnect(rp);
243 break;
244
245 /*
246 * Mark the connection as being incapable of further input.
247 */
248 case PRU_SHUTDOWN:
249 socantsendmore(so);
250 break;
251
252 case PRU_RCVD:
253 error = EOPNOTSUPP;
254 break;
255
256 /*
257 * Ship a packet out. The appropriate raw output
258 * routine handles any massaging necessary.
259 */
260 case PRU_SEND:
261 if (control && control->m_len) {
262 m_freem(control);
263 m_freem(m);
264 error = EINVAL;
265 break;
266 }
267 if (nam) {
268 if ((so->so_state & SS_ISCONNECTED) != 0) {
269 error = EISCONN;
270 goto die;
271 }
272 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
273 (struct mbuf *)0, nam, (struct mbuf *)0, p);
274 if (error) {
275 die:
276 m_freem(m);
277 break;
278 }
279 } else {
280 if ((so->so_state & SS_ISCONNECTED) == 0) {
281 error = ENOTCONN;
282 goto die;
283 }
284 }
285 error = (*so->so_proto->pr_output)(m, so);
286 if (nam)
287 raw_disconnect(rp);
288 break;
289
290 case PRU_SENSE:
291 /*
292 * stat: don't bother with a blocksize.
293 */
294 return (0);
295
296 /*
297 * Not supported.
298 */
299 case PRU_RCVOOB:
300 error = EOPNOTSUPP;
301 break;
302
303 case PRU_SENDOOB:
304 m_freem(control);
305 m_freem(m);
306 error = EOPNOTSUPP;
307 break;
308
309 case PRU_SOCKADDR:
310 if (rp->rcb_laddr == 0) {
311 error = EINVAL;
312 break;
313 }
314 raw_setsockaddr(rp, nam);
315 break;
316
317 case PRU_PEERADDR:
318 if (rp->rcb_faddr == 0) {
319 error = ENOTCONN;
320 break;
321 }
322 raw_setpeeraddr(rp, nam);
323 break;
324
325 default:
326 panic("raw_usrreq");
327 }
328
329 release:
330 splx(s);
331 return (error);
332 }
333