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

4.104.114.84.9
Last change on this file since f190f08 was 4c672b93, checked in by Ralf Corsepius <ralf.corsepius@…>, on Mar 25, 2007 at 5:40:14 AM

More updates from FreeBSD.

  • Property mode set to 100644
File size: 6.7 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        LIST_INIT(&rawcb_list);
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        struct socket *last;
80
81        last = 0;
82        LIST_FOREACH(rp, &rawcb_list, list) {
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  (bcmp((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                        n = m_copy(m, 0, (int)M_COPYALL);
105                        if (n) {
106                                if (sbappendaddr(&last->so_rcv, src,
107                                    n, (struct mbuf *)0) == 0)
108                                        /* should notify about lost packet */
109                                        m_freem(n);
110                                else {
111                                        sorwakeup(last);
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                }
124        } else
125                m_freem(m);
126}
127
128/*ARGSUSED*/
129void
130raw_ctlinput(cmd, arg, dummy)
131        int cmd;
132        struct sockaddr *arg;
133        void *dummy;
134{
135
136        if (cmd < 0 || cmd > PRC_NCMDS)
137                return;
138        /* INCOMPLETE */
139}
140
141/*ARGSUSED*/
142int
143raw_usrreq(so, req, m, nam, control)
144        struct socket *so;
145        int req;
146        struct mbuf *m, *nam, *control;
147{
148        register struct rawcb *rp = sotorawcb(so);
149        register int error = 0;
150        int len;
151
152        if (req == PRU_CONTROL)
153                return (EOPNOTSUPP);
154        if (control && control->m_len) {
155                error = EOPNOTSUPP;
156                goto release;
157        }
158        if (rp == 0) {
159                error = EINVAL;
160                goto release;
161        }
162        switch (req) {
163
164        /*
165         * Allocate a raw control block and fill in the
166         * necessary info to allow packets to be routed to
167         * the appropriate raw interface routine.
168         */
169        case PRU_ATTACH:
170                if ((so->so_state & SS_PRIV) == 0) {
171                        error = EACCES;
172                        break;
173                }
174                error = raw_attach(so, (intptr_t)nam);
175                break;
176
177        /*
178         * Destroy state just before socket deallocation.
179         * Flush data or not depending on the options.
180         */
181        case PRU_DETACH:
182                if (rp == 0) {
183                        error = ENOTCONN;
184                        break;
185                }
186                raw_detach(rp);
187                break;
188
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                error = EINVAL;
197#if 0
198                if (rp->rcb_faddr) {
199                        error = EISCONN;
200                        break;
201                }
202                nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
203                rp->rcb_faddr = mtod(nam, struct sockaddr *);
204                soisconnected(so);
205#endif
206                break;
207
208        case PRU_BIND:
209                error = EINVAL;
210#if 0
211                if (rp->rcb_laddr) {
212                        error = EINVAL;                 /* XXX */
213                        break;
214                }
215                error = raw_bind(so, nam);
216#endif
217                break;
218
219        case PRU_CONNECT2:
220                error = EOPNOTSUPP;
221                goto release;
222
223        case PRU_DISCONNECT:
224                if (rp->rcb_faddr == 0) {
225                        error = ENOTCONN;
226                        break;
227                }
228                raw_disconnect(rp);
229                soisdisconnected(so);
230                break;
231
232        /*
233         * Mark the connection as being incapable of further input.
234         */
235        case PRU_SHUTDOWN:
236                socantsendmore(so);
237                break;
238
239        /*
240         * Ship a packet out.  The appropriate raw output
241         * routine handles any massaging necessary.
242         */
243        case PRU_SEND:
244                if (nam) {
245                        if (rp->rcb_faddr) {
246                                error = EISCONN;
247                                break;
248                        }
249                        rp->rcb_faddr = mtod(nam, struct sockaddr *);
250                } else if (rp->rcb_faddr == 0) {
251                        error = ENOTCONN;
252                        break;
253                }
254                error = (*so->so_proto->pr_output)(m, so);
255                m = NULL;
256                if (nam)
257                        rp->rcb_faddr = 0;
258                break;
259
260        case PRU_ABORT:
261                raw_disconnect(rp);
262                sofree(so);
263                soisdisconnected(so);
264                break;
265
266        case PRU_SENSE:
267                /*
268                 * stat: don't bother with a blocksize.
269                 */
270                return (0);
271
272        /*
273         * Not supported.
274         */
275        case PRU_RCVOOB:
276        case PRU_RCVD:
277                return(EOPNOTSUPP);
278
279        case PRU_LISTEN:
280        case PRU_ACCEPT:
281        case PRU_SENDOOB:
282                error = EOPNOTSUPP;
283                break;
284
285        case PRU_SOCKADDR:
286                if (rp->rcb_laddr == 0) {
287                        error = EINVAL;
288                        break;
289                }
290                len = rp->rcb_laddr->sa_len;
291                bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
292                nam->m_len = len;
293                break;
294
295        case PRU_PEERADDR:
296                if (rp->rcb_faddr == 0) {
297                        error = ENOTCONN;
298                        break;
299                }
300                len = rp->rcb_faddr->sa_len;
301                bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
302                nam->m_len = len;
303                break;
304
305        default:
306                panic("raw_usrreq");
307        }
308release:
309        if (m != NULL)
310                m_freem(m);
311        return (error);
312}
Note: See TracBrowser for help on using the repository browser.