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