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