raw_usrreq.c revision 1.7 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 * from: @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93
34 * $Id: raw_usrreq.c,v 1.7 1994/05/13 06:03:13 mycroft Exp $
35 */
36
37 #include <sys/param.h>
38 #include <sys/mbuf.h>
39 #include <sys/domain.h>
40 #include <sys/protosw.h>
41 #include <sys/socket.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 /*
51 * Initialize raw connection block q.
52 */
53 void
54 raw_init()
55 {
56
57 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
58 }
59
60
61 /*
62 * Raw protocol input routine. Find the socket
63 * associated with the packet(s) and move them over. If
64 * nothing exists for this packet, drop it.
65 */
66 /*
67 * Raw protocol interface.
68 */
69 void
70 raw_input(m0, proto, src, dst)
71 struct mbuf *m0;
72 register struct sockproto *proto;
73 struct sockaddr *src, *dst;
74 {
75 register struct rawcb *rp;
76 register struct mbuf *m = m0;
77 register int sockets = 0;
78 struct socket *last;
79
80 last = 0;
81 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
82 if (rp->rcb_proto.sp_family != proto->sp_family)
83 continue;
84 if (rp->rcb_proto.sp_protocol &&
85 rp->rcb_proto.sp_protocol != proto->sp_protocol)
86 continue;
87 /*
88 * We assume the lower level routines have
89 * placed the address in a canonical format
90 * suitable for a structure comparison.
91 *
92 * Note that if the lengths are not the same
93 * the comparison will fail at the first byte.
94 */
95 #define equal(a1, a2) \
96 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
97 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
98 continue;
99 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
100 continue;
101 if (last) {
102 struct mbuf *n;
103 if (n = m_copy(m, 0, (int)M_COPYALL)) {
104 if (sbappendaddr(&last->so_rcv, src,
105 n, (struct mbuf *)0) == 0)
106 /* should notify about lost packet */
107 m_freem(n);
108 else {
109 sorwakeup(last);
110 sockets++;
111 }
112 }
113 }
114 last = rp->rcb_socket;
115 }
116 if (last) {
117 if (sbappendaddr(&last->so_rcv, src,
118 m, (struct mbuf *)0) == 0)
119 m_freem(m);
120 else {
121 sorwakeup(last);
122 sockets++;
123 }
124 } else
125 m_freem(m);
126 }
127
128 /*ARGSUSED*/
129 void
130 raw_ctlinput(cmd, arg)
131 int cmd;
132 struct sockaddr *arg;
133 {
134
135 if (cmd < 0 || cmd > PRC_NCMDS)
136 return;
137 /* INCOMPLETE */
138 }
139
140 /*ARGSUSED*/
141 int
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