source: rtems/cpukit/libnetworking/net/raw_usrreq.c @ e791c230

4.104.114.84.9
Last change on this file since e791c230 was e791c230, checked in by Ralf Corsepius <ralf.corsepius@…>, on Mar 25, 2007 at 5:29:54 AM

Partial update from FreeBSD.

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