1 /* $OpenBSD: raw_usrreq.c,v 1.10 2004/01/03 14:08:53 espie Exp $ */
2 /* $NetBSD: raw_usrreq.c,v 1.11 1996/02/13 22:00:43 christos Exp $ */
3
4 /*
5 * Copyright (c) 1980, 1986, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93
33 */
34
35 #include <sys/param.h>
36 #include <sys/mbuf.h>
37 #include <sys/domain.h>
38 #include <sys/protosw.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
41 #include <sys/errno.h>
42 #include <sys/systm.h>
43
44 #include <net/if.h>
45 #include <net/route.h>
46 #include <net/netisr.h>
47 #include <net/raw_cb.h>
48
49 #include <sys/stdarg.h>
50 /*
51 * Initialize raw connection block q.
52 */
53 void
54 raw_init()
55 {
56
57 LIST_INIT(&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(struct mbuf *m0, ...)
71 {
72 struct rawcb *rp;
73 struct mbuf *m = m0;
74 int sockets = 0;
75 struct socket *last;
76 va_list ap;
77 struct sockproto *proto;
78 struct sockaddr *src, *dst;
79
80 va_start(ap, m0);
81 proto = va_arg(ap, struct sockproto *);
82 src = va_arg(ap, struct sockaddr *);
83 dst = va_arg(ap, struct sockaddr *);
84 va_end(ap);
85
86 last = 0;
87 LIST_FOREACH(rp, &rawcb, rcb_list) {
88 if (rp->rcb_proto.sp_family != proto->sp_family)
89 continue;
90 if (rp->rcb_proto.sp_protocol &&
91 rp->rcb_proto.sp_protocol != proto->sp_protocol)
92 continue;
93 /*
94 * We assume the lower level routines have
95 * placed the address in a canonical format
96 * suitable for a structure comparison.
97 *
98 * Note that if the lengths are not the same
99 * the comparison will fail at the first byte.
100 */
101 #define equal(a1, a2) \
102 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
103 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
104 continue;
105 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
106 continue;
107 if (last) {
108 struct mbuf *n;
109 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
110 if (sbappendaddr(&last->so_rcv, src,
111 n, (struct mbuf *)0) == 0)
112 /* should notify about lost packet */
113 m_freem(n);
114 else {
115 sorwakeup(last);
116 sockets++;
117 }
118 }
119 }
120 last = rp->rcb_socket;
121 }
122 if (last) {
123 if (sbappendaddr(&last->so_rcv, src,
124 m, (struct mbuf *)0) == 0)
125 m_freem(m);
126 else {
127 sorwakeup(last);
128 sockets++;
129 }
130 } else
131 m_freem(m);
132 }
133
134 /*ARGSUSED*/
135 void *
136 raw_ctlinput(cmd, arg, d)
137 int cmd;
138 struct sockaddr *arg;
139 void *d;
140 {
141
142 if (cmd < 0 || cmd >= PRC_NCMDS)
143 return NULL;
144 return NULL;
145 /* INCOMPLETE */
146 }
147
148 /*ARGSUSED*/
149 int
150 raw_usrreq(so, req, m, nam, control)
151 struct socket *so;
152 int req;
153 struct mbuf *m, *nam, *control;
154 {
155 struct rawcb *rp = sotorawcb(so);
156 int error = 0;
157 int len;
158
159 if (req == PRU_CONTROL)
160 return (EOPNOTSUPP);
161 if (control && control->m_len) {
162 error = EOPNOTSUPP;
163 goto release;
164 }
165 if (rp == 0) {
166 error = EINVAL;
167 goto release;
168 }
169 switch (req) {
170
171 /*
172 * Allocate a raw control block and fill in the
173 * necessary info to allow packets to be routed to
174 * the appropriate raw interface routine.
175 */
176 case PRU_ATTACH:
177 if ((so->so_state & SS_PRIV) == 0) {
178 error = EACCES;
179 break;
180 }
181 error = raw_attach(so, (int)(long)nam);
182 break;
183
184 /*
185 * Destroy state just before socket deallocation.
186 * Flush data or not depending on the options.
187 */
188 case PRU_DETACH:
189 if (rp == 0) {
190 error = ENOTCONN;
191 break;
192 }
193 raw_detach(rp);
194 break;
195
196 #ifdef notdef
197 /*
198 * If a socket isn't bound to a single address,
199 * the raw input routine will hand it anything
200 * within that protocol family (assuming there's
201 * nothing else around it should go to).
202 */
203 case PRU_CONNECT:
204 if (rp->rcb_faddr) {
205 error = EISCONN;
206 break;
207 }
208 nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
209 rp->rcb_faddr = mtod(nam, struct sockaddr *);
210 soisconnected(so);
211 break;
212
213 case PRU_BIND:
214 if (rp->rcb_laddr) {
215 error = EINVAL; /* XXX */
216 break;
217 }
218 error = raw_bind(so, nam);
219 break;
220 #else
221 case PRU_CONNECT:
222 case PRU_BIND:
223 #endif
224 case PRU_CONNECT2:
225 error = EOPNOTSUPP;
226 goto release;
227
228 case PRU_DISCONNECT:
229 if (rp->rcb_faddr == 0) {
230 error = ENOTCONN;
231 break;
232 }
233 raw_disconnect(rp);
234 soisdisconnected(so);
235 break;
236
237 /*
238 * Mark the connection as being incapable of further input.
239 */
240 case PRU_SHUTDOWN:
241 socantsendmore(so);
242 break;
243
244 /*
245 * Ship a packet out. The appropriate raw output
246 * routine handles any massaging necessary.
247 */
248 case PRU_SEND:
249 if (nam) {
250 if (rp->rcb_faddr) {
251 error = EISCONN;
252 break;
253 }
254 rp->rcb_faddr = mtod(nam, struct sockaddr *);
255 } else if (rp->rcb_faddr == 0) {
256 error = ENOTCONN;
257 break;
258 }
259 error = (*so->so_proto->pr_output)(m, so);
260 m = NULL;
261 if (nam)
262 rp->rcb_faddr = 0;
263 break;
264
265 case PRU_ABORT:
266 raw_disconnect(rp);
267 sofree(so);
268 soisdisconnected(so);
269 break;
270
271 case PRU_SENSE:
272 /*
273 * stat: don't bother with a blocksize.
274 */
275 return (0);
276
277 /*
278 * Not supported.
279 */
280 case PRU_RCVOOB:
281 case PRU_RCVD:
282 return (EOPNOTSUPP);
283
284 case PRU_LISTEN:
285 case PRU_ACCEPT:
286 case PRU_SENDOOB:
287 error = EOPNOTSUPP;
288 break;
289
290 case PRU_SOCKADDR:
291 if (rp->rcb_laddr == 0) {
292 error = EINVAL;
293 break;
294 }
295 len = rp->rcb_laddr->sa_len;
296 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
297 nam->m_len = len;
298 break;
299
300 case PRU_PEERADDR:
301 if (rp->rcb_faddr == 0) {
302 error = ENOTCONN;
303 break;
304 }
305 len = rp->rcb_faddr->sa_len;
306 bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
307 nam->m_len = len;
308 break;
309
310 default:
311 panic("raw_usrreq");
312 }
313 release:
314 if (m != NULL)
315 m_freem(m);
316 return (error);
317 }