raw_usrreq.c revision 3443
1/*
2 * Copyright (c) 1980, 1986, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	@(#)raw_usrreq.c	8.1 (Berkeley) 6/10/93
34 * $Id: raw_usrreq.c,v 1.3 1994/08/18 22:35:21 wollman Exp $
35 */
36
37#include <sys/param.h>
38#include <sys/systm.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
46#include <net/if.h>
47#include <net/route.h>
48#include <net/netisr.h>
49#include <net/raw_cb.h>
50
51/*
52 * Initialize raw connection block q.
53 */
54void
55raw_init()
56{
57
58	rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
59}
60
61
62/*
63 * Raw protocol input routine.  Find the socket
64 * associated with the packet(s) and move them over.  If
65 * nothing exists for this packet, drop it.
66 */
67/*
68 * Raw protocol interface.
69 */
70void
71raw_input(m0, proto, src, dst)
72	struct mbuf *m0;
73	register struct sockproto *proto;
74	struct sockaddr *src, *dst;
75{
76	register struct rawcb *rp;
77	register struct mbuf *m = m0;
78	register int sockets = 0;
79	struct socket *last;
80
81	last = 0;
82	for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
83		if (rp->rcb_proto.sp_family != proto->sp_family)
84			continue;
85		if (rp->rcb_proto.sp_protocol  &&
86		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
87			continue;
88		/*
89		 * We assume the lower level routines have
90		 * placed the address in a canonical format
91		 * suitable for a structure comparison.
92		 *
93		 * Note that if the lengths are not the same
94		 * the comparison will fail at the first byte.
95		 */
96#define	equal(a1, a2) \
97  (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
98		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
99			continue;
100		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
101			continue;
102		if (last) {
103			struct mbuf *n;
104			n = m_copy(m, 0, (int)M_COPYALL);
105			if (n) {
106				if (sbappendaddr(&last->so_rcv, src,
107				    n, (struct mbuf *)0) == 0)
108					/* should notify about lost packet */
109					m_freem(n);
110				else {
111					sorwakeup(last);
112					sockets++;
113				}
114			}
115		}
116		last = rp->rcb_socket;
117	}
118	if (last) {
119		if (sbappendaddr(&last->so_rcv, src,
120		    m, (struct mbuf *)0) == 0)
121			m_freem(m);
122		else {
123			sorwakeup(last);
124			sockets++;
125		}
126	} else
127		m_freem(m);
128}
129
130/*ARGSUSED*/
131void
132raw_ctlinput(cmd, arg)
133	int cmd;
134	struct sockaddr *arg;
135{
136
137	if (cmd < 0 || cmd > PRC_NCMDS)
138		return;
139	/* INCOMPLETE */
140}
141
142/*ARGSUSED*/
143int
144raw_usrreq(so, req, m, nam, control)
145	struct socket *so;
146	int req;
147	struct mbuf *m, *nam, *control;
148{
149	register struct rawcb *rp = sotorawcb(so);
150	register int error = 0;
151	int len;
152
153	if (req == PRU_CONTROL)
154		return (EOPNOTSUPP);
155	if (control && control->m_len) {
156		error = EOPNOTSUPP;
157		goto release;
158	}
159	if (rp == 0) {
160		error = EINVAL;
161		goto release;
162	}
163	switch (req) {
164
165	/*
166	 * Allocate a raw control block and fill in the
167	 * necessary info to allow packets to be routed to
168	 * the appropriate raw interface routine.
169	 */
170	case PRU_ATTACH:
171		if ((so->so_state & SS_PRIV) == 0) {
172			error = EACCES;
173			break;
174		}
175		error = raw_attach(so, (int)nam);
176		break;
177
178	/*
179	 * Destroy state just before socket deallocation.
180	 * Flush data or not depending on the options.
181	 */
182	case PRU_DETACH:
183		if (rp == 0) {
184			error = ENOTCONN;
185			break;
186		}
187		raw_detach(rp);
188		break;
189
190#ifdef notdef
191	/*
192	 * If a socket isn't bound to a single address,
193	 * the raw input routine will hand it anything
194	 * within that protocol family (assuming there's
195	 * nothing else around it should go to).
196	 */
197	case PRU_CONNECT:
198		if (rp->rcb_faddr) {
199			error = EISCONN;
200			break;
201		}
202		nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
203		rp->rcb_faddr = mtod(nam, struct sockaddr *);
204		soisconnected(so);
205		break;
206
207	case PRU_BIND:
208		if (rp->rcb_laddr) {
209			error = EINVAL;			/* XXX */
210			break;
211		}
212		error = raw_bind(so, nam);
213		break;
214#endif
215
216	case PRU_CONNECT2:
217		error = EOPNOTSUPP;
218		goto release;
219
220	case PRU_DISCONNECT:
221		if (rp->rcb_faddr == 0) {
222			error = ENOTCONN;
223			break;
224		}
225		raw_disconnect(rp);
226		soisdisconnected(so);
227		break;
228
229	/*
230	 * Mark the connection as being incapable of further input.
231	 */
232	case PRU_SHUTDOWN:
233		socantsendmore(so);
234		break;
235
236	/*
237	 * Ship a packet out.  The appropriate raw output
238	 * routine handles any massaging necessary.
239	 */
240	case PRU_SEND:
241		if (nam) {
242			if (rp->rcb_faddr) {
243				error = EISCONN;
244				break;
245			}
246			rp->rcb_faddr = mtod(nam, struct sockaddr *);
247		} else if (rp->rcb_faddr == 0) {
248			error = ENOTCONN;
249			break;
250		}
251		error = (*so->so_proto->pr_output)(m, so);
252		m = NULL;
253		if (nam)
254			rp->rcb_faddr = 0;
255		break;
256
257	case PRU_ABORT:
258		raw_disconnect(rp);
259		sofree(so);
260		soisdisconnected(so);
261		break;
262
263	case PRU_SENSE:
264		/*
265		 * stat: don't bother with a blocksize.
266		 */
267		return (0);
268
269	/*
270	 * Not supported.
271	 */
272	case PRU_RCVOOB:
273	case PRU_RCVD:
274		return(EOPNOTSUPP);
275
276	case PRU_LISTEN:
277	case PRU_ACCEPT:
278	case PRU_SENDOOB:
279		error = EOPNOTSUPP;
280		break;
281
282	case PRU_SOCKADDR:
283		if (rp->rcb_laddr == 0) {
284			error = EINVAL;
285			break;
286		}
287		len = rp->rcb_laddr->sa_len;
288		bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
289		nam->m_len = len;
290		break;
291
292	case PRU_PEERADDR:
293		if (rp->rcb_faddr == 0) {
294			error = ENOTCONN;
295			break;
296		}
297		len = rp->rcb_faddr->sa_len;
298		bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
299		nam->m_len = len;
300		break;
301
302	default:
303		panic("raw_usrreq");
304	}
305release:
306	if (m != NULL)
307		m_freem(m);
308	return (error);
309}
310