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 * $Id: raw_usrreq.c,v 1.1 94/10/20 00:01:36 bill Exp Locker: bill $
34 */
35
36 #include "sys/param.h"
37 /*#include "sys/file.h"*/
38 #include "sys/errno.h"
39 #include "mbuf.h"
40 #include "domain.h"
41 #include "socketvar.h"
42 #include "protosw.h"
43 #include "prototypes.h"
44
45 #include "if.h"
46 #include "route.h"
47 #include "netisr.h"
48 #include "raw_cb.h"
49
50 struct ifqueue rawintrq; /* raw protocol input queue */
51
52 /*
53 * Initialize raw connection block q.
54 */
raw_init()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 (memcmp((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*/
raw_ctlinput(cmd,arg)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 memcpy(mtod(nam, caddr_t), (caddr_t)rp->rcb_laddr,
287 (unsigned)len);
288 nam->m_len = len;
289 break;
290
291 case PRU_PEERADDR:
292 if (rp->rcb_faddr == 0) {
293 error = ENOTCONN;
294 break;
295 }
296 len = rp->rcb_faddr->sa_len;
297 memcpy(mtod(nam, caddr_t), (caddr_t)rp->rcb_faddr,
298 (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