raw_usrreq.c revision 1.2 1 /*
2 * Copyright (c) 1980, 1986 Regents of the University of California.
3 * 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 * from: @(#)raw_usrreq.c 7.9 (Berkeley) 6/28/90
34 * $Id: raw_usrreq.c,v 1.2 1993/05/18 18:20:00 cgd Exp $
35 */
36
37 #include "param.h"
38 #include "socket.h"
39 #include "select.h"
40 #include "mbuf.h"
41 #include "domain.h"
42 #include "protosw.h"
43 #include "socket.h"
44 #include "socketvar.h"
45 #include "errno.h"
46
47 #include "if.h"
48 #include "route.h"
49 #include "netisr.h"
50 #include "raw_cb.h"
51
52 #include "machine/mtpr.h"
53
54 /*
55 * Initialize raw connection block q.
56 */
57 raw_init()
58 {
59
60 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
61 rawintrq.ifq_maxlen = IFQ_MAXLEN;
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 raw_input(m0, proto, src, dst)
74 struct mbuf *m0;
75 register struct sockproto *proto;
76 struct sockaddr *src, *dst;
77 {
78 register struct rawcb *rp;
79 register struct mbuf *m = m0;
80 register int sockets = 0;
81 struct socket *last;
82
83 last = 0;
84 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
85 if (rp->rcb_proto.sp_family != proto->sp_family)
86 continue;
87 if (rp->rcb_proto.sp_protocol &&
88 rp->rcb_proto.sp_protocol != proto->sp_protocol)
89 continue;
90 /*
91 * We assume the lower level routines have
92 * placed the address in a canonical format
93 * suitable for a structure comparison.
94 *
95 * Note that if the lengths are not the same
96 * the comparison will fail at the first byte.
97 */
98 #define equal(a1, a2) \
99 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
100 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
101 continue;
102 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
103 continue;
104 if (last) {
105 struct mbuf *n;
106 if (n = m_copy(m, 0, (int)M_COPYALL)) {
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 return (sockets);
130 }
131
132 /*ARGSUSED*/
133 raw_ctlinput(cmd, arg)
134 int cmd;
135 struct sockaddr *arg;
136 {
137
138 if (cmd < 0 || cmd > PRC_NCMDS)
139 return;
140 /* INCOMPLETE */
141 }
142
143 /*ARGSUSED*/
144 raw_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 }
305 release:
306 if (m != NULL)
307 m_freem(m);
308 return (error);
309 }
310
311 rawintr() {} /* XXX - referenced by locore. will soon go away */
312