raw_usrreq.c revision 181803
1/*-
2 * Copyright (c) 1980, 1986, 1993
3 *	The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 4. Neither the name of the University nor the names of its contributors
15 *    may be used to endorse or promote products derived from this software
16 *    without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 *	@(#)raw_usrreq.c	8.1 (Berkeley) 6/10/93
31 * $FreeBSD: head/sys/net/raw_usrreq.c 181803 2008-08-17 23:27:27Z bz $
32 */
33
34#include <sys/param.h>
35#include <sys/kernel.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/mbuf.h>
39#include <sys/mutex.h>
40#include <sys/priv.h>
41#include <sys/protosw.h>
42#include <sys/signalvar.h>
43#include <sys/socket.h>
44#include <sys/socketvar.h>
45#include <sys/sx.h>
46#include <sys/systm.h>
47#include <sys/vimage.h>
48
49#include <net/raw_cb.h>
50
51MTX_SYSINIT(rawcb_mtx, &rawcb_mtx, "rawcb", MTX_DEF);
52
53/*
54 * Initialize raw connection block q.
55 */
56void
57raw_init(void)
58{
59
60	LIST_INIT(&V_rawcb_list);
61}
62
63/*
64 * Raw protocol input routine.  Find the socket associated with the packet(s)
65 * and move them over.  If nothing exists for this packet, drop it.
66 */
67/*
68 * Raw protocol interface.
69 */
70void
71raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
72{
73	struct rawcb *rp;
74	struct mbuf *m = m0;
75	struct socket *last;
76
77	last = 0;
78	mtx_lock(&rawcb_mtx);
79	LIST_FOREACH(rp, &V_rawcb_list, list) {
80		if (rp->rcb_proto.sp_family != proto->sp_family)
81			continue;
82		if (rp->rcb_proto.sp_protocol  &&
83		    rp->rcb_proto.sp_protocol != proto->sp_protocol)
84			continue;
85		if (last) {
86			struct mbuf *n;
87			n = m_copy(m, 0, (int)M_COPYALL);
88			if (n) {
89				if (sbappendaddr(&last->so_rcv, src,
90				    n, (struct mbuf *)0) == 0)
91					/* should notify about lost packet */
92					m_freem(n);
93				else
94					sorwakeup(last);
95			}
96		}
97		last = rp->rcb_socket;
98	}
99	if (last) {
100		if (sbappendaddr(&last->so_rcv, src,
101		    m, (struct mbuf *)0) == 0)
102			m_freem(m);
103		else
104			sorwakeup(last);
105	} else
106		m_freem(m);
107	mtx_unlock(&rawcb_mtx);
108}
109
110/*ARGSUSED*/
111void
112raw_ctlinput(int cmd, struct sockaddr *arg, void *dummy)
113{
114
115	if (cmd < 0 || cmd >= PRC_NCMDS)
116		return;
117	/* INCOMPLETE */
118}
119
120static void
121raw_uabort(struct socket *so)
122{
123
124	KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
125
126	soisdisconnected(so);
127}
128
129static void
130raw_uclose(struct socket *so)
131{
132
133	KASSERT(sotorawcb(so) != NULL, ("raw_uabort: rp == NULL"));
134
135	soisdisconnected(so);
136}
137
138/* pru_accept is EOPNOTSUPP */
139
140static int
141raw_uattach(struct socket *so, int proto, struct thread *td)
142{
143	int error;
144
145	/*
146	 * Implementors of raw sockets will already have allocated the PCB,
147	 * so it must be non-NULL here.
148	 */
149	KASSERT(sotorawcb(so) != NULL, ("raw_uattach: so_pcb == NULL"));
150
151	if (td != NULL) {
152		error = priv_check(td, PRIV_NET_RAW);
153		if (error)
154			return (error);
155	}
156	return (raw_attach(so, proto));
157}
158
159static int
160raw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
161{
162
163	return (EINVAL);
164}
165
166static int
167raw_uconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
168{
169
170	return (EINVAL);
171}
172
173/* pru_connect2 is EOPNOTSUPP */
174/* pru_control is EOPNOTSUPP */
175
176static void
177raw_udetach(struct socket *so)
178{
179	struct rawcb *rp = sotorawcb(so);
180
181	KASSERT(rp != NULL, ("raw_udetach: rp == NULL"));
182
183	raw_detach(rp);
184}
185
186static int
187raw_udisconnect(struct socket *so)
188{
189
190	KASSERT(sotorawcb(so) != NULL, ("raw_udisconnect: rp == NULL"));
191
192	return (ENOTCONN);
193}
194
195/* pru_listen is EOPNOTSUPP */
196
197static int
198raw_upeeraddr(struct socket *so, struct sockaddr **nam)
199{
200
201	KASSERT(sotorawcb(so) != NULL, ("raw_upeeraddr: rp == NULL"));
202
203	return (ENOTCONN);
204}
205
206/* pru_rcvd is EOPNOTSUPP */
207/* pru_rcvoob is EOPNOTSUPP */
208
209static int
210raw_usend(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
211    struct mbuf *control, struct thread *td)
212{
213
214	KASSERT(sotorawcb(so) != NULL, ("raw_usend: rp == NULL"));
215
216	if ((flags & PRUS_OOB) || (control && control->m_len)) {
217		/* XXXRW: Should control also be freed here? */
218		if (m != NULL)
219			m_freem(m);
220		return (EOPNOTSUPP);
221	}
222
223	/*
224	 * For historical (bad?) reasons, we effectively ignore the address
225	 * argument to sendto(2).  Perhaps we should return an error instead?
226	 */
227	return ((*so->so_proto->pr_output)(m, so));
228}
229
230/* pru_sense is null */
231
232static int
233raw_ushutdown(struct socket *so)
234{
235
236	KASSERT(sotorawcb(so) != NULL, ("raw_ushutdown: rp == NULL"));
237
238	socantsendmore(so);
239	return (0);
240}
241
242static int
243raw_usockaddr(struct socket *so, struct sockaddr **nam)
244{
245
246	KASSERT(sotorawcb(so) != NULL, ("raw_usockaddr: rp == NULL"));
247
248	return (EINVAL);
249}
250
251struct pr_usrreqs raw_usrreqs = {
252	.pru_abort =		raw_uabort,
253	.pru_attach =		raw_uattach,
254	.pru_bind =		raw_ubind,
255	.pru_connect =		raw_uconnect,
256	.pru_detach =		raw_udetach,
257	.pru_disconnect =	raw_udisconnect,
258	.pru_peeraddr =		raw_upeeraddr,
259	.pru_send =		raw_usend,
260	.pru_shutdown =		raw_ushutdown,
261	.pru_sockaddr =		raw_usockaddr,
262	.pru_close =		raw_uclose,
263};
264