OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [libnetworking/] [netinet/] [raw_ip.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 158 chris
/*
2
 * Copyright (c) 1982, 1986, 1988, 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
 * 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
 *      @(#)raw_ip.c    8.7 (Berkeley) 5/15/95
34 208 chris
 *      $Id: raw_ip.c,v 1.2 2001-09-27 12:01:56 chris Exp $
35 158 chris
 */
36
 
37
#include <sys/param.h>
38
#include <sys/queue.h>
39
#include <sys/malloc.h>
40
#include <sys/mbuf.h>
41
#include <sys/socket.h>
42
#include <sys/protosw.h>
43
#include <sys/socketvar.h>
44
#include <sys/errno.h>
45
#include <sys/systm.h>
46
 
47
#include <net/if.h>
48
#include <net/route.h>
49
 
50
#define _IP_VHL
51
#include <netinet/in.h>
52
#include <netinet/in_systm.h>
53
#include <netinet/ip.h>
54
#include <netinet/in_pcb.h>
55
#include <netinet/in_var.h>
56
#include <netinet/ip_var.h>
57
#include <netinet/ip_mroute.h>
58
 
59
#include <netinet/ip_fw.h>
60
 
61
#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
62
#undef COMPAT_IPFW
63
#define COMPAT_IPFW 1
64
#else
65
#undef COMPAT_IPFW
66
#endif
67
 
68
static struct inpcbhead ripcb;
69
static struct inpcbinfo ripcbinfo;
70
 
71
/*
72
 * Nominal space allocated to a raw ip socket.
73
 */
74
#define RIPSNDQ         8192
75
#define RIPRCVQ         8192
76
 
77
/*
78
 * Raw interface to IP protocol.
79
 */
80
 
81
/*
82
 * Initialize raw connection block q.
83
 */
84
void
85
rip_init()
86
{
87
        LIST_INIT(&ripcb);
88
        ripcbinfo.listhead = &ripcb;
89
        /*
90
         * XXX We don't use the hash list for raw IP, but it's easier
91
         * to allocate a one entry hash list than it is to check all
92
         * over the place for hashbase == NULL.
93
         */
94
        ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);
95
}
96
 
97
static struct   sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
98
/*
99
 * Setup generic address and protocol structures
100
 * for raw_input routine, then pass them along with
101
 * mbuf chain.
102
 */
103
void
104
rip_input(m, iphlen)
105
        struct mbuf *m;
106
        int iphlen;
107
{
108
        register struct ip *ip = mtod(m, struct ip *);
109
        register struct inpcb *inp;
110
        struct inpcb *last = 0;
111
        struct mbuf *opts = 0;
112
 
113
        ripsrc.sin_addr = ip->ip_src;
114
        for (inp = ripcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
115
                if (inp->inp_ip_p && inp->inp_ip_p != ip->ip_p)
116
                        continue;
117
                if (inp->inp_laddr.s_addr &&
118
                  inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
119
                        continue;
120
                if (inp->inp_faddr.s_addr &&
121
                  inp->inp_faddr.s_addr != ip->ip_src.s_addr)
122
                        continue;
123
                if (last) {
124
                        struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
125
                        if (n) {
126
                                if (last->inp_flags & INP_CONTROLOPTS ||
127
                                    last->inp_socket->so_options & SO_TIMESTAMP)
128
                                    ip_savecontrol(last, &opts, ip, n);
129
                                if (sbappendaddr(&last->inp_socket->so_rcv,
130
                                    (struct sockaddr *)&ripsrc, n,
131
                                    opts) == 0) {
132
                                        /* should notify about lost packet */
133
                                        m_freem(n);
134
                                        if (opts)
135
                                            m_freem(opts);
136
                                } else
137
                                        sorwakeup(last->inp_socket);
138
                                opts = 0;
139
                        }
140
                }
141
                last = inp;
142
        }
143
        if (last) {
144
                if (last->inp_flags & INP_CONTROLOPTS ||
145
                    last->inp_socket->so_options & SO_TIMESTAMP)
146
                        ip_savecontrol(last, &opts, ip, m);
147
                if (sbappendaddr(&last->inp_socket->so_rcv,
148
                    (struct sockaddr *)&ripsrc, m, opts) == 0) {
149
                        m_freem(m);
150
                        if (opts)
151
                            m_freem(opts);
152
                } else
153
                        sorwakeup(last->inp_socket);
154
        } else {
155
                m_freem(m);
156
              ipstat.ips_noproto++;
157
              ipstat.ips_delivered--;
158
      }
159
}
160
 
161
/*
162
 * Generate IP header and pass packet to ip_output.
163
 * Tack on options user may have setup with control call.
164
 */
165
int
166
rip_output(m, so, dst)
167
        register struct mbuf *m;
168
        struct socket *so;
169
        u_long dst;
170
{
171
        register struct ip *ip;
172
        register struct inpcb *inp = sotoinpcb(so);
173
        int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
174
 
175
        /*
176
         * If the user handed us a complete IP packet, use it.
177
         * Otherwise, allocate an mbuf for a header and fill it in.
178
         */
179
        if ((inp->inp_flags & INP_HDRINCL) == 0) {
180
                if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
181
                        m_freem(m);
182
                        return(EMSGSIZE);
183
                }
184
                M_PREPEND(m, sizeof(struct ip), M_WAIT);
185
                ip = mtod(m, struct ip *);
186
                ip->ip_tos = 0;
187
                ip->ip_off = 0;
188
                ip->ip_p = inp->inp_ip_p;
189
                ip->ip_len = m->m_pkthdr.len;
190
                ip->ip_src = inp->inp_laddr;
191
                ip->ip_dst.s_addr = dst;
192
                ip->ip_ttl = MAXTTL;
193
        } else {
194
                if (m->m_pkthdr.len > IP_MAXPACKET) {
195
                        m_freem(m);
196
                        return(EMSGSIZE);
197
                }
198
                ip = mtod(m, struct ip *);
199
                /* don't allow both user specified and setsockopt options,
200
                   and don't allow packet length sizes that will crash */
201
                if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))
202
                     && inp->inp_options)
203
                    || (ip->ip_len > m->m_pkthdr.len)
204
                    || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {
205
                        m_freem(m);
206
                        return EINVAL;
207
                }
208
                if (ip->ip_id == 0)
209
                        ip->ip_id = htons(ip_id++);
210
                /* XXX prevent ip_output from overwriting header fields */
211
                flags |= IP_RAWOUTPUT;
212
                ipstat.ips_rawout++;
213
        }
214
        return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
215
                          inp->inp_moptions));
216
}
217
 
218
/*
219
 * Raw IP socket option processing.
220
 */
221
int
222
rip_ctloutput(op, so, level, optname, m)
223
        int op;
224
        struct socket *so;
225
        int level, optname;
226
        struct mbuf **m;
227
{
228
        register struct inpcb *inp = sotoinpcb(so);
229
        register int error;
230
 
231
        if (level != IPPROTO_IP) {
232
                if (op == PRCO_SETOPT && *m)
233
                        (void)m_free(*m);
234
                return (EINVAL);
235
        }
236
 
237
        switch (optname) {
238
 
239
        case IP_HDRINCL:
240
                error = 0;
241
                if (op == PRCO_SETOPT) {
242
                        if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int))
243
                                error = EINVAL;
244
                        else if (*mtod(*m, int *))
245
                                inp->inp_flags |= INP_HDRINCL;
246
                        else
247
                                inp->inp_flags &= ~INP_HDRINCL;
248
                        if (*m)
249
                                (void)m_free(*m);
250
                } else {
251
                        *m = m_get(M_WAIT, MT_SOOPTS);
252
                        (*m)->m_len = sizeof (int);
253
                        *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL;
254
                }
255
                return (error);
256
 
257
#ifdef COMPAT_IPFW
258
        case IP_FW_GET:
259
                if (ip_fw_ctl_ptr == NULL || op == PRCO_SETOPT) {
260
                        if (*m) (void)m_free(*m);
261
                        return(EINVAL);
262
                }
263
                return (*ip_fw_ctl_ptr)(optname, m);
264
 
265
        case IP_FW_ADD:
266
        case IP_FW_DEL:
267
        case IP_FW_FLUSH:
268
        case IP_FW_ZERO:
269
                if (ip_fw_ctl_ptr == NULL || op != PRCO_SETOPT) {
270
                        if (*m) (void)m_free(*m);
271
                        return(EINVAL);
272
                }
273
                return (*ip_fw_ctl_ptr)(optname, m);
274
 
275
        case IP_NAT:
276
                if (ip_nat_ctl_ptr == NULL) {
277
                        if (*m) (void)m_free(*m);
278
                        return(EINVAL);
279
                }
280
                return (*ip_nat_ctl_ptr)(op, m);
281
 
282
#endif
283
        case IP_RSVP_ON:
284
                return ip_rsvp_init(so);
285
                break;
286
 
287
        case IP_RSVP_OFF:
288
                return ip_rsvp_done();
289
                break;
290
 
291
        case IP_RSVP_VIF_ON:
292
                return ip_rsvp_vif_init(so, *m);
293
 
294
        case IP_RSVP_VIF_OFF:
295
                return ip_rsvp_vif_done(so, *m);
296
 
297
        case MRT_INIT:
298
        case MRT_DONE:
299
        case MRT_ADD_VIF:
300
        case MRT_DEL_VIF:
301
        case MRT_ADD_MFC:
302
        case MRT_DEL_MFC:
303
        case MRT_VERSION:
304
        case MRT_ASSERT:
305
                if (op == PRCO_SETOPT) {
306
                        error = ip_mrouter_set(optname, so, *m);
307
                        if (*m)
308
                                (void)m_free(*m);
309
                } else if (op == PRCO_GETOPT) {
310
                        error = ip_mrouter_get(optname, so, m);
311
                } else
312
                        error = EINVAL;
313
                return (error);
314
        }
315
        return (ip_ctloutput(op, so, level, optname, m));
316
}
317
 
318
static u_long   rip_sendspace = RIPSNDQ; /* XXX sysctl ? */
319
static u_long   rip_recvspace = RIPRCVQ; /* XXX sysctl ? */
320
 
321
/*ARGSUSED*/
322
int
323
rip_usrreq(so, req, m, nam, control)
324
        register struct socket *so;
325
        int req;
326
        struct mbuf *m, *nam, *control;
327
{
328
        register int error = 0;
329
        register struct inpcb *inp = sotoinpcb(so);
330
        int s;
331
 
332
        if (req == PRU_CONTROL)
333
                return (in_control(so, (u_long)m, (caddr_t)nam,
334
                        (struct ifnet *)control));
335
 
336
        switch (req) {
337
 
338
        case PRU_ATTACH:
339
                if (inp)
340
                        panic("rip_attach");
341
                if ((so->so_state & SS_PRIV) == 0) {
342
                        error = EACCES;
343
                        break;
344
                }
345
                s = splnet();
346
                error = in_pcballoc(so, &ripcbinfo);
347
                splx(s);
348
                if (error)
349
                        break;
350
                error = soreserve(so, rip_sendspace, rip_recvspace);
351
                if (error)
352
                        break;
353
                inp = (struct inpcb *)so->so_pcb;
354
                inp->inp_ip_p = (int)nam;
355
                break;
356
 
357
        case PRU_DISCONNECT:
358
                if ((so->so_state & SS_ISCONNECTED) == 0) {
359
                        error = ENOTCONN;
360
                        break;
361
                }
362
                /* FALLTHROUGH */
363
        case PRU_ABORT:
364
                soisdisconnected(so);
365
                /* FALLTHROUGH */
366
        case PRU_DETACH:
367
                if (inp == 0)
368
                        panic("rip_detach");
369
                if (so == ip_mrouter)
370
                        ip_mrouter_done();
371
                ip_rsvp_force_done(so);
372
                if (so == ip_rsvpd)
373
                        ip_rsvp_done();
374
                in_pcbdetach(inp);
375
                break;
376
 
377
        case PRU_BIND:
378
            {
379
                struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
380
 
381
                if (nam->m_len != sizeof(*addr)) {
382
                        error = EINVAL;
383
                        break;
384
                }
385
                if ((ifnet == 0) ||
386
                    ((addr->sin_family != AF_INET) &&
387
                     (addr->sin_family != AF_IMPLINK)) ||
388
                    (addr->sin_addr.s_addr &&
389
                     ifa_ifwithaddr((struct sockaddr *)addr) == 0)) {
390
                        error = EADDRNOTAVAIL;
391
                        break;
392
                }
393
                inp->inp_laddr = addr->sin_addr;
394
                break;
395
            }
396
        case PRU_CONNECT:
397
            {
398
                struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
399
 
400
                if (nam->m_len != sizeof(*addr)) {
401
                        error = EINVAL;
402
                        break;
403
                }
404
                if (ifnet == 0) {
405
                        error = EADDRNOTAVAIL;
406
                        break;
407
                }
408
                if ((addr->sin_family != AF_INET) &&
409
                     (addr->sin_family != AF_IMPLINK)) {
410
                        error = EAFNOSUPPORT;
411
                        break;
412
                }
413
                inp->inp_faddr = addr->sin_addr;
414
                soisconnected(so);
415
                break;
416
            }
417
 
418
        case PRU_CONNECT2:
419
                error = EOPNOTSUPP;
420
                break;
421
 
422
        /*
423
         * Mark the connection as being incapable of further input.
424
         */
425
        case PRU_SHUTDOWN:
426
                socantsendmore(so);
427
                break;
428
 
429
        /*
430
         * Ship a packet out.  The appropriate raw output
431
         * routine handles any massaging necessary.
432
         */
433
        case PRU_SEND:
434
            {
435
                register u_long dst;
436
 
437
                if (so->so_state & SS_ISCONNECTED) {
438
                        if (nam) {
439
                                error = EISCONN;
440
                                break;
441
                        }
442
                        dst = inp->inp_faddr.s_addr;
443
                } else {
444
                        if (nam == NULL) {
445
                                error = ENOTCONN;
446
                                break;
447
                        }
448
                        dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
449
                }
450
                error = rip_output(m, so, dst);
451
                m = NULL;
452
                break;
453
            }
454
 
455
        case PRU_SENSE:
456
                /*
457
                 * stat: don't bother with a blocksize.
458
                 */
459
                return (0);
460
 
461
        /*
462
         * Not supported.
463
         */
464
        case PRU_RCVOOB:
465
        case PRU_RCVD:
466
        case PRU_LISTEN:
467
        case PRU_ACCEPT:
468
        case PRU_SENDOOB:
469
                error = EOPNOTSUPP;
470
                break;
471
 
472
        case PRU_SOCKADDR:
473
                in_setsockaddr(inp, nam);
474
                break;
475
 
476
        case PRU_PEERADDR:
477
                in_setpeeraddr(inp, nam);
478
                break;
479
 
480
        default:
481
                panic("rip_usrreq");
482
        }
483
        if (m != NULL)
484
                m_freem(m);
485
        return (error);
486
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.