raw_usrreq.c revision 25201
1207618Srdivacky/*
2198090Srdivacky * Copyright (c) 1980, 1986, 1993
3353358Sdim *	The Regents of the University of California.  All rights reserved.
4353358Sdim *
5353358Sdim * Redistribution and use in source and binary forms, with or without
6198090Srdivacky * modification, are permitted provided that the following conditions
7198090Srdivacky * are met:
8198090Srdivacky * 1. Redistributions of source code must retain the above copyright
9198090Srdivacky *    notice, this list of conditions and the following disclaimer.
10198090Srdivacky * 2. Redistributions in binary form must reproduce the above copyright
11198090Srdivacky *    notice, this list of conditions and the following disclaimer in the
12198090Srdivacky *    documentation and/or other materials provided with the distribution.
13198090Srdivacky * 3. All advertising materials mentioning features or use of this software
14198090Srdivacky *    must display the following acknowledgement:
15198090Srdivacky *	This product includes software developed by the University of
16321369Sdim *	California, Berkeley and its contributors.
17249423Sdim * 4. Neither the name of the University nor the names of its contributors
18327952Sdim *    may be used to endorse or promote products derived from this software
19198090Srdivacky *    without specific prior written permission.
20198090Srdivacky *
21198090Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22198090Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23280031Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24321369Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25353358Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26249423Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27249423Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28309124Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29296417Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30198090Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31249423Sdim * SUCH DAMAGE.
32314564Sdim *
33314564Sdim *	@(#)raw_usrreq.c	8.1 (Berkeley) 6/10/93
34314564Sdim *	$Id: raw_usrreq.c,v 1.11 1997/04/14 18:23:25 phk Exp $
35314564Sdim */
36314564Sdim
37314564Sdim#include <sys/param.h>
38314564Sdim#include <sys/queue.h>
39314564Sdim#include <sys/systm.h>
40314564Sdim#include <sys/mbuf.h>
41314564Sdim#include <sys/domain.h>
42314564Sdim#include <sys/proc.h>
43314564Sdim#include <sys/protosw.h>
44314564Sdim#include <sys/socket.h>
45314564Sdim#include <sys/socketvar.h>
46314564Sdim#include <sys/errno.h>
47314564Sdim
48314564Sdim#include <net/if.h>
49314564Sdim#include <net/route.h>
50314564Sdim#include <net/netisr.h>
51249423Sdim#include <net/raw_cb.h>
52198090Srdivacky
53341825Sdim/*
54249423Sdim * Initialize raw connection block q.
55249423Sdim */
56249423Sdimvoid
57249423Sdimraw_init()
58249423Sdim{
59249423Sdim	LIST_INIT(&rawcb_list);
60249423Sdim}
61249423Sdim
62249423Sdim
63249423Sdim/*
64249423Sdim * Raw protocol input routine.  Find the socket
65249423Sdim * associated with the packet(s) and move them over.  If
66249423Sdim * nothing exists for this packet, drop it.
67249423Sdim */
68249423Sdim/*
69341825Sdim * Raw protocol interface.
70353358Sdim */
71249423Sdimvoid
72341825Sdimraw_input(m0, proto, src, dst)
73353358Sdim	struct mbuf *m0;
74249423Sdim	register struct sockproto *proto;
75344779Sdim	struct sockaddr *src, *dst;
76344779Sdim{
77344779Sdim	register struct rawcb *rp;
78249423Sdim	register struct mbuf *m = m0;
79344779Sdim	register int sockets = 0;
80344779Sdim	struct socket *last;
81344779Sdim
82344779Sdim	last = 0;
83344779Sdim	LIST_FOREACH(rp, &rawcb_list, list) {
84249423Sdim		if (rp->rcb_proto.sp_family != proto->sp_family)
85249423Sdim			continue;
86249423Sdim		if (rp->rcb_proto.sp_protocol  &&
87249423Sdim		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
88249423Sdim			continue;
89249423Sdim		/*
90198090Srdivacky		 * We assume the lower level routines have
91344779Sdim		 * placed the address in a canonical format
92344779Sdim		 * suitable for a structure comparison.
93249423Sdim		 *
94344779Sdim		 * Note that if the lengths are not the same
95344779Sdim		 * the comparison will fail at the first byte.
96249423Sdim		 */
97198090Srdivacky#define	equal(a1, a2) \
98341825Sdim  (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
99288943Sdim		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
100249423Sdim			continue;
101249423Sdim		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
102198090Srdivacky			continue;
103249423Sdim		if (last) {
104249423Sdim			struct mbuf *n;
105249423Sdim			n = m_copy(m, 0, (int)M_COPYALL);
106198090Srdivacky			if (n) {
107341825Sdim				if (sbappendaddr(&last->so_rcv, src,
108249423Sdim				    n, (struct mbuf *)0) == 0)
109249423Sdim					/* should notify about lost packet */
110249423Sdim					m_freem(n);
111249423Sdim				else {
112249423Sdim					sorwakeup(last);
113198090Srdivacky					sockets++;
114341825Sdim				}
115327952Sdim			}
116327952Sdim		}
117327952Sdim		last = rp->rcb_socket;
118327952Sdim	}
119327952Sdim	if (last) {
120344779Sdim		if (sbappendaddr(&last->so_rcv, src,
121344779Sdim		    m, (struct mbuf *)0) == 0)
122344779Sdim			m_freem(m);
123344779Sdim		else {
124344779Sdim			sorwakeup(last);
125344779Sdim			sockets++;
126344779Sdim		}
127341825Sdim	} else
128249423Sdim		m_freem(m);
129249423Sdim}
130249423Sdim
131249423Sdim/*ARGSUSED*/
132234353Sdimvoid
133344779Sdimraw_ctlinput(cmd, arg, dummy)
134344779Sdim	int cmd;
135344779Sdim	struct sockaddr *arg;
136344779Sdim	void *dummy;
137344779Sdim{
138344779Sdim
139344779Sdim	if (cmd < 0 || cmd > PRC_NCMDS)
140344779Sdim		return;
141344779Sdim	/* INCOMPLETE */
142344779Sdim}
143344779Sdim
144314564Sdimstatic int
145314564Sdimraw_uabort(struct socket *so)
146314564Sdim{
147314564Sdim	struct rawcb *rp = sotorawcb(so);
148314564Sdim
149314564Sdim	if (rp == 0)
150314564Sdim		return EINVAL;
151314564Sdim	raw_disconnect(rp);
152314564Sdim	sofree(so);
153314564Sdim	soisdisconnected(so);
154314564Sdim	return 0;
155314564Sdim}
156314564Sdim
157314564Sdim/* pru_accept is EOPNOTSUPP */
158314564Sdim
159314564Sdimstatic int
160314564Sdimraw_uattach(struct socket *so, int proto, struct proc *p)
161314564Sdim{
162314564Sdim	struct rawcb *rp = sotorawcb(so);
163314564Sdim	int error;
164314564Sdim
165314564Sdim	if (rp == 0)
166314564Sdim		return EINVAL;
167314564Sdim	if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
168314564Sdim		return error;
169314564Sdim	return raw_attach(so, proto);
170314564Sdim}
171321369Sdim
172327952Sdimstatic int
173327952Sdimraw_ubind(struct socket *so, struct mbuf *nam, struct proc *p)
174327952Sdim{
175327952Sdim	return EINVAL;
176321369Sdim}
177321369Sdim
178327952Sdimstatic int
179327952Sdimraw_uconnect(struct socket *so, struct mbuf *nam, struct proc *p)
180327952Sdim{
181314564Sdim	return EINVAL;
182314564Sdim}
183314564Sdim
184314564Sdim/* pru_connect2 is EOPNOTSUPP */
185314564Sdim/* pru_control is EOPNOTSUPP */
186314564Sdim
187314564Sdimstatic int
188314564Sdimraw_udetach(struct socket *so)
189314564Sdim{
190314564Sdim	struct rawcb *rp = sotorawcb(so);
191314564Sdim
192314564Sdim	if (rp == 0)
193314564Sdim		return EINVAL;
194314564Sdim
195314564Sdim	raw_detach(rp);
196341825Sdim	return 0;
197314564Sdim}
198314564Sdim
199314564Sdimstatic int
200321369Sdimraw_udisconnect(struct socket *so)
201321369Sdim{
202353358Sdim	struct rawcb *rp = sotorawcb(so);
203321369Sdim
204341825Sdim	if (rp == 0)
205296417Sdim		return EINVAL;
206296417Sdim	if (rp->rcb_faddr == 0) {
207309124Sdim		return ENOTCONN;
208309124Sdim	}
209309124Sdim	raw_disconnect(rp);
210309124Sdim	soisdisconnected(so);
211296417Sdim	return 0;
212296417Sdim}
213296417Sdim
214296417Sdim/* pru_listen is EOPNOTSUPP */
215327952Sdim
216353358Sdimstatic int
217327952Sdimraw_upeeraddr(struct socket *so, struct mbuf *nam)
218327952Sdim{
219327952Sdim	struct rawcb *rp = sotorawcb(so);
220198090Srdivacky	unsigned len;
221341825Sdim
222296417Sdim	if (rp == 0)
223296417Sdim		return EINVAL;
224296417Sdim	if (rp->rcb_faddr == 0) {
225296417Sdim		return ENOTCONN;
226314564Sdim	}
227353358Sdim	len = rp->rcb_faddr->sa_len;
228314564Sdim	bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), len);
229314564Sdim	nam->m_len = len;
230321369Sdim	return 0;
231327952Sdim}
232198090Srdivacky
233341825Sdim/* pru_rcvd is EOPNOTSUPP */
234353358Sdim/* pru_rcvoob is EOPNOTSUPP */
235198090Srdivacky
236198090Srdivackystatic int
237198090Srdivackyraw_usend(struct socket *so, int flags, struct mbuf *m,
238	  struct mbuf *nam, struct mbuf *control, struct proc *p)
239{
240	int error;
241	struct rawcb *rp = sotorawcb(so);
242
243	if (rp == 0) {
244		error = EINVAL;
245		goto release;
246	}
247
248	if (flags & PRUS_OOB) {
249		error = EOPNOTSUPP;
250		goto release;
251	}
252
253	if (control && control->m_len) {
254		error = EOPNOTSUPP;
255		goto release;
256	}
257	if (nam) {
258		if (rp->rcb_faddr) {
259			error = EISCONN;
260			goto release;
261		}
262		rp->rcb_faddr = mtod(nam, struct sockaddr *);
263	} else if (rp->rcb_faddr == 0) {
264		error = ENOTCONN;
265		goto release;
266	}
267	error = (*so->so_proto->pr_output)(m, so);
268	m = NULL;
269	if (nam)
270		rp->rcb_faddr = 0;
271release:
272	if (m != NULL)
273		m_freem(m);
274	return (error);
275}
276
277/* pru_sense is null */
278
279static int
280raw_ushutdown(struct socket *so)
281{
282	struct rawcb *rp = sotorawcb(so);
283
284	if (rp == 0)
285		return EINVAL;
286	socantsendmore(so);
287	return 0;
288}
289
290static int
291raw_usockaddr(struct socket *so, struct mbuf *nam)
292{
293	struct rawcb *rp = sotorawcb(so);
294	unsigned len;
295
296	if (rp == 0)
297		return EINVAL;
298	if (rp->rcb_laddr == 0)
299		return EINVAL;
300	len = rp->rcb_laddr->sa_len;
301	bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), len);
302	nam->m_len = len;
303	return 0;
304}
305
306struct pr_usrreqs raw_usrreqs = {
307	raw_uabort, pru_accept_notsupp, raw_uattach, raw_ubind, raw_uconnect,
308	pru_connect2_notsupp, pru_control_notsupp, raw_udetach,
309	raw_udisconnect, pru_listen_notsupp, raw_upeeraddr, pru_rcvd_notsupp,
310	pru_rcvoob_notsupp, raw_usend, pru_sense_null, raw_ushutdown,
311	raw_usockaddr, sosend, soreceive, soselect
312};
313