raw_usrreq.c revision 1.5 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.5 1994/01/06 14:00:35 deraadt Exp $
35 */
36
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/mbuf.h>
40 #include <sys/domain.h>
41 #include <sys/protosw.h>
42 #include <sys/socketvar.h>
43 #include <sys/errno.h>
44
45 #include <net/if.h>
46 #include <net/route.h>
47 #include <net/netisr.h>
48 #include <net/raw_cb.h>
49
50 #include <machine/mtpr.h>
51
52 /*
53 * Initialize raw connection block q.
54 */
55 raw_init()
56 {
57
58 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
59 rawintrq.ifq_maxlen = IFQ_MAXLEN;
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 raw_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 if (n = m_copy(m, 0, (int)M_COPYALL)) {
105 if (sbappendaddr(&last->so_rcv, src,
106 n, (struct mbuf *)0) == 0)
107 /* should notify about lost packet */
108 m_freem(n);
109 else {
110 sorwakeup(last);
111 sockets++;
112 }
113 }
114 }
115 last = rp->rcb_socket;
116 }
117 if (last) {
118 if (sbappendaddr(&last->so_rcv, src,
119 m, (struct mbuf *)0) == 0)
120 m_freem(m);
121 else {
122 sorwakeup(last);
123 sockets++;
124 }
125 } else
126 m_freem(m);
127 return (sockets);
128 }
129
130 /*ARGSUSED*/
131 raw_ctlinput(cmd, arg)
132 int cmd;
133 struct sockaddr *arg;
134 {
135
136 if (cmd < 0 || cmd > PRC_NCMDS)
137 return;
138 /* INCOMPLETE */
139 }
140
141 /*ARGSUSED*/
142 raw_usrreq(so, req, m, nam, control)
143 struct socket *so;
144 int req;
145 struct mbuf *m, *nam, *control;
146 {
147 register struct rawcb *rp = sotorawcb(so);
148 register int error = 0;
149 int len;
150
151 if (req == PRU_CONTROL)
152 return (EOPNOTSUPP);
153 if (control && control->m_len) {
154 error = EOPNOTSUPP;
155 goto release;
156 }
157 if (rp == 0) {
158 error = EINVAL;
159 goto release;
160 }
161 switch (req) {
162
163 /*
164 * Allocate a raw control block and fill in the
165 * necessary info to allow packets to be routed to
166 * the appropriate raw interface routine.
167 */
168 case PRU_ATTACH:
169 if ((so->so_state & SS_PRIV) == 0) {
170 error = EACCES;
171 break;
172 }
173 error = raw_attach(so, (int)nam);
174 break;
175
176 /*
177 * Destroy state just before socket deallocation.
178 * Flush data or not depending on the options.
179 */
180 case PRU_DETACH:
181 if (rp == 0) {
182 error = ENOTCONN;
183 break;
184 }
185 raw_detach(rp);
186 break;
187
188 #ifdef notdef
189 /*
190 * If a socket isn't bound to a single address,
191 * the raw input routine will hand it anything
192 * within that protocol family (assuming there's
193 * nothing else around it should go to).
194 */
195 case PRU_CONNECT:
196 if (rp->rcb_faddr) {
197 error = EISCONN;
198 break;
199 }
200 nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
201 rp->rcb_faddr = mtod(nam, struct sockaddr *);
202 soisconnected(so);
203 break;
204
205 case PRU_BIND:
206 if (rp->rcb_laddr) {
207 error = EINVAL; /* XXX */
208 break;
209 }
210 error = raw_bind(so, nam);
211 break;
212 #endif
213
214 case PRU_CONNECT2:
215 error = EOPNOTSUPP;
216 goto release;
217
218 case PRU_DISCONNECT:
219 if (rp->rcb_faddr == 0) {
220 error = ENOTCONN;
221 break;
222 }
223 raw_disconnect(rp);
224 soisdisconnected(so);
225 break;
226
227 /*
228 * Mark the connection as being incapable of further input.
229 */
230 case PRU_SHUTDOWN:
231 socantsendmore(so);
232 break;
233
234 /*
235 * Ship a packet out. The appropriate raw output
236 * routine handles any massaging necessary.
237 */
238 case PRU_SEND:
239 if (nam) {
240 if (rp->rcb_faddr) {
241 error = EISCONN;
242 break;
243 }
244 rp->rcb_faddr = mtod(nam, struct sockaddr *);
245 } else if (rp->rcb_faddr == 0) {
246 error = ENOTCONN;
247 break;
248 }
249 error = (*so->so_proto->pr_output)(m, so);
250 m = NULL;
251 if (nam)
252 rp->rcb_faddr = 0;
253 break;
254
255 case PRU_ABORT:
256 raw_disconnect(rp);
257 sofree(so);
258 soisdisconnected(so);
259 break;
260
261 case PRU_SENSE:
262 /*
263 * stat: don't bother with a blocksize.
264 */
265 return (0);
266
267 /*
268 * Not supported.
269 */
270 case PRU_RCVOOB:
271 case PRU_RCVD:
272 return(EOPNOTSUPP);
273
274 case PRU_LISTEN:
275 case PRU_ACCEPT:
276 case PRU_SENDOOB:
277 error = EOPNOTSUPP;
278 break;
279
280 case PRU_SOCKADDR:
281 if (rp->rcb_laddr == 0) {
282 error = EINVAL;
283 break;
284 }
285 len = rp->rcb_laddr->sa_len;
286 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
287 nam->m_len = len;
288 break;
289
290 case PRU_PEERADDR:
291 if (rp->rcb_faddr == 0) {
292 error = ENOTCONN;
293 break;
294 }
295 len = rp->rcb_faddr->sa_len;
296 bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
297 nam->m_len = len;
298 break;
299
300 default:
301 panic("raw_usrreq");
302 }
303 release:
304 if (m != NULL)
305 m_freem(m);
306 return (error);
307 }
308
309 rawintr() {} /* XXX - referenced by locore. will soon go away */
310