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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [netinet/] [raw_ip.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      sys/netinet/raw_ip.c
4
//
5
//     
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    gthomas
22
// Contributors: gthomas
23
// Date:         2000-01-10
24
// Purpose:      
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
 
33
/*      $OpenBSD: raw_ip.c,v 1.19 1999/09/23 07:20:35 deraadt Exp $     */
34
/*      $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $     */
35
 
36
/*
37
 * Copyright (c) 1982, 1986, 1988, 1993
38
 *      The Regents of the University of California.  All rights reserved.
39
 *
40
 * Redistribution and use in source and binary forms, with or without
41
 * modification, are permitted provided that the following conditions
42
 * are met:
43
 * 1. Redistributions of source code must retain the above copyright
44
 *    notice, this list of conditions and the following disclaimer.
45
 * 2. Redistributions in binary form must reproduce the above copyright
46
 *    notice, this list of conditions and the following disclaimer in the
47
 *    documentation and/or other materials provided with the distribution.
48
 * 3. All advertising materials mentioning features or use of this software
49
 *    must display the following acknowledgement:
50
 *      This product includes software developed by the University of
51
 *      California, Berkeley and its contributors.
52
 * 4. Neither the name of the University nor the names of its contributors
53
 *    may be used to endorse or promote products derived from this software
54
 *    without specific prior written permission.
55
 *
56
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66
 * SUCH DAMAGE.
67
 *
68
 *      @(#)raw_ip.c    8.2 (Berkeley) 1/4/94
69
 */
70
 
71
/*
72
%%% portions-copyright-nrl-95
73
Portions of this software are Copyright 1995-1998 by Randall Atkinson,
74
Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
75
Reserved. All rights under this copyright have been assigned to the US
76
Naval Research Laboratory (NRL). The NRL Copyright Notice and License
77
Agreement Version 1.1 (January 17, 1995) applies to these portions of the
78
software.
79
You should have received a copy of the license with this software. If you
80
didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
81
*/
82
 
83
#include <sys/param.h>
84
#include <sys/malloc.h>
85
#include <sys/mbuf.h>
86
#include <sys/socket.h>
87
#include <sys/protosw.h>
88
#include <sys/socketvar.h>
89
#include <sys/errno.h>
90
#ifndef __ECOS
91
#include <sys/systm.h>
92
#endif
93
 
94
#include <net/if.h>
95
#include <net/route.h>
96
 
97
#include <netinet/in.h>
98
#include <netinet/in_systm.h>
99
#include <netinet/ip.h>
100
#include <netinet/ip_mroute.h>
101
#include <netinet/ip_var.h>
102
#include <netinet/in_pcb.h>
103
#include <netinet/in_var.h>
104
#include <netinet/ip_icmp.h>
105
 
106
#ifdef IPSEC
107
extern int      check_ipsec_policy  __P((struct inpcb *, u_int32_t));
108
#endif
109
 
110
#include <machine/stdarg.h>
111
 
112
struct inpcbtable rawcbtable;
113
 
114
/*
115
 * Nominal space allocated to a raw ip socket.
116
 */
117
#define RIPSNDQ         8192
118
#define RIPRCVQ         8192
119
 
120
/*
121
 * Raw interface to IP protocol.
122
 */
123
 
124
/*
125
 * Initialize raw connection block q.
126
 */
127
void
128
rip_init()
129
{
130
 
131
        in_pcbinit(&rawcbtable, 1);
132
}
133
 
134
struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
135
 
136
/*
137
 * Setup generic address and protocol structures
138
 * for raw_input routine, then pass them along with
139
 * mbuf chain.
140
 */
141
void
142
#if __STDC__
143
rip_input(struct mbuf *m, ...)
144
#else
145
rip_input(m, va_alist)
146
        struct mbuf *m;
147
        va_dcl
148
#endif
149
{
150
        register struct ip *ip = mtod(m, struct ip *);
151
        register struct inpcb *inp;
152
        struct socket *last = 0;
153
 
154
        ripsrc.sin_addr = ip->ip_src;
155
        for (inp = rawcbtable.inpt_queue.cqh_first;
156
            inp != (struct inpcb *)&rawcbtable.inpt_queue;
157
            inp = inp->inp_queue.cqe_next) {
158
                if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p)
159
                        continue;
160
                if (inp->inp_laddr.s_addr &&
161
                    inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
162
                        continue;
163
                if (inp->inp_faddr.s_addr &&
164
                    inp->inp_faddr.s_addr != ip->ip_src.s_addr)
165
                        continue;
166
                if (last) {
167
                        struct mbuf *n;
168
                        if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
169
                                if (sbappendaddr(&last->so_rcv,
170
                                    sintosa(&ripsrc), n,
171
                                    (struct mbuf *)0) == 0)
172
                                        /* should notify about lost packet */
173
                                        m_freem(n);
174
                                else
175
                                        sorwakeup(last);
176
                        }
177
                }
178
                last = inp->inp_socket;
179
        }
180
        if (last) {
181
                if (sbappendaddr(&last->so_rcv, sintosa(&ripsrc), m,
182
                    (struct mbuf *)0) == 0)
183
                        m_freem(m);
184
                else
185
                        sorwakeup(last);
186
        } else {
187
                if (ip->ip_p != IPPROTO_ICMP)
188
                        icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 0);
189
                else
190
                        m_freem(m);
191
                ipstat.ips_noproto++;
192
                ipstat.ips_delivered--;
193
        }
194
}
195
 
196
/*
197
 * Generate IP header and pass packet to ip_output.
198
 * Tack on options user may have setup with control call.
199
 */
200
int
201
#if __STDC__
202
rip_output(struct mbuf *m, ...)
203
#else
204
rip_output(m, va_alist)
205
        struct mbuf *m;
206
        va_dcl
207
#endif
208
{
209
        struct socket *so;
210
        u_long dst;
211
        register struct ip *ip;
212
        register struct inpcb *inp;
213
        int flags;
214
        va_list ap;
215
 
216
        va_start(ap, m);
217
        so = va_arg(ap, struct socket *);
218
        dst = va_arg(ap, u_long);
219
        va_end(ap);
220
 
221
        inp = sotoinpcb(so);
222
        flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
223
 
224
        /*
225
         * If the user handed us a complete IP packet, use it.
226
         * Otherwise, allocate an mbuf for a header and fill it in.
227
         */
228
        if ((inp->inp_flags & INP_HDRINCL) == 0) {
229
                if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
230
                        m_freem(m);
231
                        return (EMSGSIZE);
232
                }
233
                M_PREPEND(m, sizeof(struct ip), M_WAIT);
234
                ip = mtod(m, struct ip *);
235
                ip->ip_tos = 0;
236
                ip->ip_off = 0;
237
                ip->ip_p = inp->inp_ip.ip_p;
238
                ip->ip_len = m->m_pkthdr.len;
239
                ip->ip_src = inp->inp_laddr;
240
                ip->ip_dst.s_addr = dst;
241
                ip->ip_ttl = MAXTTL;
242
        } else {
243
                if (m->m_pkthdr.len > IP_MAXPACKET) {
244
                        m_freem(m);
245
                        return (EMSGSIZE);
246
                }
247
                ip = mtod(m, struct ip *);
248
                NTOHS(ip->ip_len);
249
                NTOHS(ip->ip_off);
250
                /*
251
                 * don't allow both user specified and setsockopt options,
252
                 * and don't allow packet length sizes that will crash
253
                 */
254
                if ((ip->ip_hl != (sizeof (*ip) >> 2) && inp->inp_options) ||
255
                    ip->ip_len > m->m_pkthdr.len ||
256
                    ip->ip_len < ip->ip_hl << 2) {
257
                        m_freem(m);
258
                        return (EINVAL);
259
                }
260
                if (ip->ip_id == 0) {
261
#ifdef RANDOM_IP_ID
262
                        ip->ip_id = ip_randomid();
263
#else
264
                        ip->ip_id = htons(ip_id++);
265
#endif
266
                }
267
                /* XXX prevent ip_output from overwriting header fields */
268
                flags |= IP_RAWOUTPUT;
269
                ipstat.ips_rawout++;
270
        }
271
#ifdef INET6
272
        /*
273
         * A thought:  Even though raw IP shouldn't be able to set IPv6
274
         *             multicast options, if it does, the last parameter to
275
         *             ip_output should be guarded against v6/v4 problems.
276
         */
277
#endif
278
        return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
279
            inp->inp_moptions, inp));
280
}
281
 
282
/*
283
 * Raw IP socket option processing.
284
 */
285
int
286
rip_ctloutput(op, so, level, optname, m)
287
        int op;
288
        struct socket *so;
289
        int level, optname;
290
        struct mbuf **m;
291
{
292
        register struct inpcb *inp = sotoinpcb(so);
293
        register int error;
294
 
295
        if (level != IPPROTO_IP) {
296
                if (op == PRCO_SETOPT && *m)
297
                        (void) m_free(*m);
298
                return (EINVAL);
299
        }
300
 
301
        switch (optname) {
302
 
303
        case IP_HDRINCL:
304
                error = 0;
305
                if (op == PRCO_SETOPT) {
306
                        if (*m == 0 || (*m)->m_len < sizeof (int))
307
                                error = EINVAL;
308
                        else if (*mtod(*m, int *))
309
                                inp->inp_flags |= INP_HDRINCL;
310
                        else
311
                                inp->inp_flags &= ~INP_HDRINCL;
312
                        if (*m)
313
                                (void)m_free(*m);
314
                } else {
315
                        *m = m_get(M_WAIT, M_SOOPTS);
316
                        (*m)->m_len = sizeof(int);
317
                        *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL;
318
                }
319
                return (error);
320
 
321
        case MRT_INIT:
322
        case MRT_DONE:
323
        case MRT_ADD_VIF:
324
        case MRT_DEL_VIF:
325
        case MRT_ADD_MFC:
326
        case MRT_DEL_MFC:
327
        case MRT_VERSION:
328
        case MRT_ASSERT:
329
#ifdef MROUTING
330
                switch (op) {
331
                case PRCO_SETOPT:
332
                        error = ip_mrouter_set(optname, so, m);
333
                        break;
334
                case PRCO_GETOPT:
335
                        error = ip_mrouter_get(optname, so, m);
336
                        break;
337
                default:
338
                        error = EINVAL;
339
                        break;
340
                }
341
                return (error);
342
#else
343
                if (op == PRCO_SETOPT && *m)
344
                        m_free(*m);
345
                return (EOPNOTSUPP);
346
#endif
347
        }
348
        return (ip_ctloutput(op, so, level, optname, m));
349
}
350
 
351
u_long  rip_sendspace = RIPSNDQ;
352
u_long  rip_recvspace = RIPRCVQ;
353
 
354
/*ARGSUSED*/
355
int
356
rip_usrreq(so, req, m, nam, control)
357
        register struct socket *so;
358
        int req;
359
        struct mbuf *m, *nam, *control;
360
{
361
        register int error = 0;
362
        register struct inpcb *inp = sotoinpcb(so);
363
#ifdef MROUTING
364
        extern struct socket *ip_mrouter;
365
#endif
366
        if (req == PRU_CONTROL)
367
                return (in_control(so, (u_long)m, (caddr_t)nam,
368
                        (struct ifnet *)control));
369
 
370
        if (inp == NULL && req != PRU_ATTACH) {
371
                error = EINVAL;
372
                goto release;
373
        }
374
 
375
        switch (req) {
376
 
377
        case PRU_ATTACH:
378
                if (inp)
379
                        panic("rip_attach");
380
#ifndef __ECOS
381
                if ((so->so_state & SS_PRIV) == 0) {
382
                        error = EACCES;
383
                        break;
384
                }
385
#endif
386
                if ((error = soreserve(so, rip_sendspace, rip_recvspace)) ||
387
                    (error = in_pcballoc(so, &rawcbtable)))
388
                        break;
389
                inp = (struct inpcb *)so->so_pcb;
390
                inp->inp_ip.ip_p = (long)nam;
391
                break;
392
 
393
        case PRU_DISCONNECT:
394
                if ((so->so_state & SS_ISCONNECTED) == 0) {
395
                        error = ENOTCONN;
396
                        break;
397
                }
398
                /* FALLTHROUGH */
399
        case PRU_ABORT:
400
                soisdisconnected(so);
401
                /* FALLTHROUGH */
402
        case PRU_DETACH:
403
                if (inp == 0)
404
                        panic("rip_detach");
405
#ifdef MROUTING
406
                if (so == ip_mrouter)
407
                        ip_mrouter_done();
408
#endif
409
                in_pcbdetach(inp);
410
                break;
411
 
412
        case PRU_BIND:
413
            {
414
                struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
415
 
416
                if (nam->m_len != sizeof(*addr)) {
417
                        error = EINVAL;
418
                        break;
419
                }
420
                if ((ifnet.tqh_first == 0) ||
421
                    ((addr->sin_family != AF_INET) &&
422
                     (addr->sin_family != AF_IMPLINK)) ||
423
                    (addr->sin_addr.s_addr &&
424
                     ifa_ifwithaddr(sintosa(addr)) == 0)) {
425
                        error = EADDRNOTAVAIL;
426
                        break;
427
                }
428
                inp->inp_laddr = addr->sin_addr;
429
                break;
430
            }
431
        case PRU_CONNECT:
432
            {
433
                struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
434
 
435
                if (nam->m_len != sizeof(*addr)) {
436
                        error = EINVAL;
437
                        break;
438
                }
439
                if (ifnet.tqh_first == 0) {
440
                        error = EADDRNOTAVAIL;
441
                        break;
442
                }
443
                if ((addr->sin_family != AF_INET) &&
444
                     (addr->sin_family != AF_IMPLINK)) {
445
                        error = EAFNOSUPPORT;
446
                        break;
447
                }
448
                inp->inp_faddr = addr->sin_addr;
449
                soisconnected(so);
450
                break;
451
            }
452
 
453
        case PRU_CONNECT2:
454
                error = EOPNOTSUPP;
455
                break;
456
 
457
        /*
458
         * Mark the connection as being incapable of further input.
459
         */
460
        case PRU_SHUTDOWN:
461
                socantsendmore(so);
462
                break;
463
 
464
        /*
465
         * Ship a packet out.  The appropriate raw output
466
         * routine handles any massaging necessary.
467
         */
468
        case PRU_SEND:
469
            {
470
                register u_int32_t dst;
471
 
472
                if (so->so_state & SS_ISCONNECTED) {
473
                        if (nam) {
474
                                error = EISCONN;
475
                                break;
476
                        }
477
                        dst = inp->inp_faddr.s_addr;
478
                } else {
479
                        if (nam == NULL) {
480
                                error = ENOTCONN;
481
                                break;
482
                        }
483
                        dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
484
                }
485
#ifdef IPSEC
486
                if (!(error = check_ipsec_policy(inp, dst)))
487
#endif
488
                error = rip_output(m, so, dst);
489
                m = NULL;
490
                break;
491
            }
492
 
493
        case PRU_SENSE:
494
                /*
495
                 * stat: don't bother with a blocksize.
496
                 */
497
                return (0);
498
 
499
        /*
500
         * Not supported.
501
         */
502
        case PRU_RCVOOB:
503
        case PRU_RCVD:
504
        case PRU_LISTEN:
505
        case PRU_ACCEPT:
506
        case PRU_SENDOOB:
507
                error = EOPNOTSUPP;
508
                break;
509
 
510
        case PRU_SOCKADDR:
511
                in_setsockaddr(inp, nam);
512
                break;
513
 
514
        case PRU_PEERADDR:
515
                in_setpeeraddr(inp, nam);
516
                break;
517
 
518
        default:
519
                panic("rip_usrreq");
520
        }
521
release:
522
        if (m != NULL)
523
                m_freem(m);
524
        return (error);
525
}

powered by: WebSVN 2.1.0

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