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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [sys/] [netinet/] [raw_ip.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      src/sys/netinet/raw_ip.c
4
//
5
//==========================================================================
6
//####BSDCOPYRIGHTBEGIN####
7
//
8
// -------------------------------------------
9
//
10
// Portions of this software may have been derived from OpenBSD, 
11
// FreeBSD or other sources, and are covered by the appropriate
12
// copyright disclaimers included herein.
13
//
14
// Portions created by Red Hat are
15
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16
//
17
// -------------------------------------------
18
//
19
//####BSDCOPYRIGHTEND####
20
//==========================================================================
21
 
22
/*
23
 * Copyright (c) 1982, 1986, 1988, 1993
24
 *      The Regents of the University of California.  All rights reserved.
25
 *
26
 * Redistribution and use in source and binary forms, with or without
27
 * modification, are permitted provided that the following conditions
28
 * are met:
29
 * 1. Redistributions of source code must retain the above copyright
30
 *    notice, this list of conditions and the following disclaimer.
31
 * 2. Redistributions in binary form must reproduce the above copyright
32
 *    notice, this list of conditions and the following disclaimer in the
33
 *    documentation and/or other materials provided with the distribution.
34
 * 3. All advertising materials mentioning features or use of this software
35
 *    must display the following acknowledgement:
36
 *      This product includes software developed by the University of
37
 *      California, Berkeley and its contributors.
38
 * 4. Neither the name of the University nor the names of its contributors
39
 *    may be used to endorse or promote products derived from this software
40
 *    without specific prior written permission.
41
 *
42
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52
 * SUCH DAMAGE.
53
 *
54
 *      @(#)raw_ip.c    8.7 (Berkeley) 5/15/95
55
 * $FreeBSD: src/sys/netinet/raw_ip.c,v 1.64.2.8 2001/07/29 19:32:40 ume Exp $
56
 */
57
 
58
#include <sys/param.h>
59
#include <sys/malloc.h>
60
#include <sys/mbuf.h>
61
#include <sys/protosw.h>
62
#include <sys/socket.h>
63
#include <sys/socketvar.h>
64
 
65
#include <net/if.h>
66
#include <net/route.h>
67
 
68
#define _IP_VHL
69
#include <netinet/in.h>
70
#include <netinet/in_systm.h>
71
#include <netinet/ip.h>
72
#include <netinet/in_pcb.h>
73
#include <netinet/in_var.h>
74
#include <netinet/ip_var.h>
75
#include <netinet/ip_mroute.h>
76
 
77
#include <netinet/ip_fw.h>
78
 
79
#ifdef IPSEC
80
#include <netinet6/ipsec.h>
81
#endif /*IPSEC*/
82
 
83
#ifdef DUMMYNET
84
#include <netinet/ip_dummynet.h>
85
#endif
86
 
87
struct  inpcbhead ripcb;
88
struct  inpcbinfo ripcbinfo;
89
 
90
/*
91
 * Nominal space allocated to a raw ip socket.
92
 */
93
#define RIPSNDQ         8192
94
#define RIPRCVQ         8192
95
 
96
/*
97
 * Raw interface to IP protocol.
98
 */
99
 
100
/*
101
 * Initialize raw connection block q.
102
 */
103
void
104
rip_init()
105
{
106
        LIST_INIT(&ripcb);
107
        ripcbinfo.listhead = &ripcb;
108
        /*
109
         * XXX We don't use the hash list for raw IP, but it's easier
110
         * to allocate a one entry hash list than it is to check all
111
         * over the place for hashbase == NULL.
112
         */
113
        ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);
114
        ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask);
115
        ripcbinfo.ipi_zone = zinit("ripcb", sizeof(struct inpcb),
116
                                   maxsockets, ZONE_INTERRUPT, 0);
117
}
118
 
119
static struct   sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
120
/*
121
 * Setup generic address and protocol structures
122
 * for raw_input routine, then pass them along with
123
 * mbuf chain.
124
 */
125
void
126
rip_input(m, off)
127
        struct mbuf *m;
128
        int off;
129
{
130
        register struct ip *ip = mtod(m, struct ip *);
131
        register struct inpcb *inp;
132
        struct inpcb *last = 0;
133
        struct mbuf *opts = 0;
134
        int proto = ip->ip_p;
135
 
136
        ripsrc.sin_addr = ip->ip_src;
137
        LIST_FOREACH(inp, &ripcb, inp_list) {
138
#ifdef INET6
139
                if ((inp->inp_vflag & INP_IPV4) == 0)
140
                        continue;
141
#endif
142
                if (inp->inp_ip_p && inp->inp_ip_p != proto)
143
                        continue;
144
                if (inp->inp_laddr.s_addr &&
145
                  inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
146
                        continue;
147
                if (inp->inp_faddr.s_addr &&
148
                  inp->inp_faddr.s_addr != ip->ip_src.s_addr)
149
                        continue;
150
                if (last) {
151
                        struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
152
 
153
#ifdef IPSEC
154
                        /* check AH/ESP integrity. */
155
                        if (n && ipsec4_in_reject_so(n, last->inp_socket)) {
156
                                m_freem(n);
157
                                ipsecstat.in_polvio++;
158
                                /* do not inject data to pcb */
159
                        } else
160
#endif /*IPSEC*/
161
                        if (n) {
162
                                if (last->inp_flags & INP_CONTROLOPTS ||
163
                                    last->inp_socket->so_options & SO_TIMESTAMP)
164
                                    ip_savecontrol(last, &opts, ip, n);
165
                                if (sbappendaddr(&last->inp_socket->so_rcv,
166
                                    (struct sockaddr *)&ripsrc, n,
167
                                    opts) == 0) {
168
                                        /* should notify about lost packet */
169
                                        m_freem(n);
170
                                        if (opts)
171
                                            m_freem(opts);
172
                                } else
173
                                        sorwakeup(last->inp_socket);
174
                                opts = 0;
175
                        }
176
                }
177
                last = inp;
178
        }
179
#ifdef IPSEC
180
        /* check AH/ESP integrity. */
181
        if (last && ipsec4_in_reject_so(m, last->inp_socket)) {
182
                m_freem(m);
183
                ipsecstat.in_polvio++;
184
                ipstat.ips_delivered--;
185
                /* do not inject data to pcb */
186
        } else
187
#endif /*IPSEC*/
188
        if (last) {
189
                if (last->inp_flags & INP_CONTROLOPTS ||
190
                    last->inp_socket->so_options & SO_TIMESTAMP)
191
                        ip_savecontrol(last, &opts, ip, m);
192
                if (sbappendaddr(&last->inp_socket->so_rcv,
193
                    (struct sockaddr *)&ripsrc, m, opts) == 0) {
194
                        m_freem(m);
195
                        if (opts)
196
                            m_freem(opts);
197
                } else
198
                        sorwakeup(last->inp_socket);
199
        } else {
200
                m_freem(m);
201
                ipstat.ips_noproto++;
202
                ipstat.ips_delivered--;
203
        }
204
}
205
 
206
/*
207
 * Generate IP header and pass packet to ip_output.
208
 * Tack on options user may have setup with control call.
209
 */
210
int
211
rip_output(m, so, dst)
212
        struct mbuf *m;
213
        struct socket *so;
214
        u_long dst;
215
{
216
        register struct ip *ip;
217
        register struct inpcb *inp = sotoinpcb(so);
218
        int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
219
 
220
        /*
221
         * If the user handed us a complete IP packet, use it.
222
         * Otherwise, allocate an mbuf for a header and fill it in.
223
         */
224
        if ((inp->inp_flags & INP_HDRINCL) == 0) {
225
                if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
226
                        m_freem(m);
227
                        return(EMSGSIZE);
228
                }
229
                M_PREPEND(m, sizeof(struct ip), M_WAIT);
230
                ip = mtod(m, struct ip *);
231
                ip->ip_tos = inp->inp_ip_tos;
232
                ip->ip_off = 0;
233
                ip->ip_p = inp->inp_ip_p;
234
                ip->ip_len = m->m_pkthdr.len;
235
                ip->ip_src = inp->inp_laddr;
236
                ip->ip_dst.s_addr = dst;
237
                ip->ip_ttl = inp->inp_ip_ttl;
238
        } else {
239
                if (m->m_pkthdr.len > IP_MAXPACKET) {
240
                        m_freem(m);
241
                        return(EMSGSIZE);
242
                }
243
                ip = mtod(m, struct ip *);
244
                /* don't allow both user specified and setsockopt options,
245
                   and don't allow packet length sizes that will crash */
246
                if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))
247
                     && inp->inp_options)
248
                    || (ip->ip_len > m->m_pkthdr.len)
249
                    || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {
250
                        m_freem(m);
251
                        return EINVAL;
252
                }
253
                if (ip->ip_id == 0)
254
#ifdef RANDOM_IP_ID
255
                        ip->ip_id = ip_randomid();
256
#else
257
                        ip->ip_id = htons(ip_id++);
258
#endif
259
                /* XXX prevent ip_output from overwriting header fields */
260
                flags |= IP_RAWOUTPUT;
261
                ipstat.ips_rawout++;
262
        }
263
 
264
#ifdef IPSEC
265
        if (ipsec_setsocket(m, so) != 0) {
266
                m_freem(m);
267
                return ENOBUFS;
268
        }
269
#endif /*IPSEC*/
270
 
271
        return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
272
                          inp->inp_moptions));
273
}
274
 
275
/*
276
 * Raw IP socket option processing.
277
 */
278
int
279
rip_ctloutput(so, sopt)
280
        struct socket *so;
281
        struct sockopt *sopt;
282
{
283
        struct  inpcb *inp = sotoinpcb(so);
284
        int     error, optval;
285
 
286
        if (sopt->sopt_level != IPPROTO_IP)
287
                return (EINVAL);
288
 
289
        error = 0;
290
 
291
        switch (sopt->sopt_dir) {
292
        case SOPT_GET:
293
                switch (sopt->sopt_name) {
294
                case IP_HDRINCL:
295
                        optval = inp->inp_flags & INP_HDRINCL;
296
                        error = sooptcopyout(sopt, &optval, sizeof optval);
297
                        break;
298
 
299
                case IP_FW_ADD:
300
                case IP_FW_GET:
301
                        if (ip_fw_ctl_ptr == 0)
302
                                error = ENOPROTOOPT;
303
                        else
304
                                error = ip_fw_ctl_ptr(sopt);
305
                        break;
306
 
307
#ifdef DUMMYNET
308
                case IP_DUMMYNET_GET:
309
                        if (ip_dn_ctl_ptr == NULL)
310
                                error = ENOPROTOOPT ;
311
                        else
312
                                error = ip_dn_ctl_ptr(sopt);
313
                        break ;
314
#endif /* DUMMYNET */
315
 
316
                case MRT_INIT:
317
                case MRT_DONE:
318
                case MRT_ADD_VIF:
319
                case MRT_DEL_VIF:
320
                case MRT_ADD_MFC:
321
                case MRT_DEL_MFC:
322
                case MRT_VERSION:
323
                case MRT_ASSERT:
324
                        error = ip_mrouter_get(so, sopt);
325
                        break;
326
 
327
                default:
328
                        error = ip_ctloutput(so, sopt);
329
                        break;
330
                }
331
                break;
332
 
333
        case SOPT_SET:
334
                switch (sopt->sopt_name) {
335
                case IP_HDRINCL:
336
                        error = sooptcopyin(sopt, &optval, sizeof optval,
337
                                            sizeof optval);
338
                        if (error)
339
                                break;
340
                        if (optval)
341
                                inp->inp_flags |= INP_HDRINCL;
342
                        else
343
                                inp->inp_flags &= ~INP_HDRINCL;
344
                        break;
345
 
346
                case IP_FW_ADD:
347
                case IP_FW_DEL:
348
                case IP_FW_FLUSH:
349
                case IP_FW_ZERO:
350
                case IP_FW_RESETLOG:
351
                        if (ip_fw_ctl_ptr == 0)
352
                                error = ENOPROTOOPT;
353
                        else
354
                                error = ip_fw_ctl_ptr(sopt);
355
                        break;
356
 
357
#ifdef DUMMYNET
358
                case IP_DUMMYNET_CONFIGURE:
359
                case IP_DUMMYNET_DEL:
360
                case IP_DUMMYNET_FLUSH:
361
                        if (ip_dn_ctl_ptr == NULL)
362
                                error = ENOPROTOOPT ;
363
                        else
364
                                error = ip_dn_ctl_ptr(sopt);
365
                        break ;
366
#endif
367
 
368
                case IP_RSVP_ON:
369
                        error = ip_rsvp_init(so);
370
                        break;
371
 
372
                case IP_RSVP_OFF:
373
                        error = ip_rsvp_done();
374
                        break;
375
 
376
                        /* XXX - should be combined */
377
                case IP_RSVP_VIF_ON:
378
                        error = ip_rsvp_vif_init(so, sopt);
379
                        break;
380
 
381
                case IP_RSVP_VIF_OFF:
382
                        error = ip_rsvp_vif_done(so, sopt);
383
                        break;
384
 
385
                case MRT_INIT:
386
                case MRT_DONE:
387
                case MRT_ADD_VIF:
388
                case MRT_DEL_VIF:
389
                case MRT_ADD_MFC:
390
                case MRT_DEL_MFC:
391
                case MRT_VERSION:
392
                case MRT_ASSERT:
393
                        error = ip_mrouter_set(so, sopt);
394
                        break;
395
 
396
                default:
397
                        error = ip_ctloutput(so, sopt);
398
                        break;
399
                }
400
                break;
401
        }
402
 
403
        return (error);
404
}
405
 
406
/*
407
 * This function exists solely to receive the PRC_IFDOWN messages which
408
 * are sent by if_down().  It looks for an ifaddr whose ifa_addr is sa,
409
 * and calls in_ifadown() to remove all routes corresponding to that address.
410
 * It also receives the PRC_IFUP messages from if_up() and reinstalls the
411
 * interface routes.
412
 */
413
void
414
rip_ctlinput(cmd, sa, vip)
415
        int cmd;
416
        struct sockaddr *sa;
417
        void *vip;
418
{
419
        struct in_ifaddr *ia;
420
        struct ifnet *ifp;
421
        int err;
422
        int flags;
423
 
424
        switch (cmd) {
425
        case PRC_IFDOWN:
426
                for (ia = in_ifaddrhead.tqh_first; ia;
427
                     ia = ia->ia_link.tqe_next) {
428
                        if (ia->ia_ifa.ifa_addr == sa
429
                            && (ia->ia_flags & IFA_ROUTE)) {
430
                                /*
431
                                 * in_ifscrub kills the interface route.
432
                                 */
433
                                in_ifscrub(ia->ia_ifp, ia);
434
                                /*
435
                                 * in_ifadown gets rid of all the rest of
436
                                 * the routes.  This is not quite the right
437
                                 * thing to do, but at least if we are running
438
                                 * a routing process they will come back.
439
                                 */
440
                                in_ifadown(&ia->ia_ifa, 0);
441
                                break;
442
                        }
443
                }
444
                break;
445
 
446
        case PRC_IFUP:
447
                for (ia = in_ifaddrhead.tqh_first; ia;
448
                     ia = ia->ia_link.tqe_next) {
449
                        if (ia->ia_ifa.ifa_addr == sa)
450
                                break;
451
                }
452
                if (ia == 0 || (ia->ia_flags & IFA_ROUTE))
453
                        return;
454
                flags = RTF_UP;
455
                ifp = ia->ia_ifa.ifa_ifp;
456
 
457
                if ((ifp->if_flags & IFF_LOOPBACK)
458
                    || (ifp->if_flags & IFF_POINTOPOINT))
459
                        flags |= RTF_HOST;
460
 
461
                err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
462
                if (err == 0)
463
                        ia->ia_flags |= IFA_ROUTE;
464
                break;
465
        }
466
}
467
 
468
u_long  rip_sendspace = RIPSNDQ;
469
u_long  rip_recvspace = RIPRCVQ;
470
 
471
static int
472
rip_attach(struct socket *so, int proto, struct proc *p)
473
{
474
        struct inpcb *inp;
475
        int error, s;
476
 
477
        inp = sotoinpcb(so);
478
        if (inp)
479
                panic("rip_attach");
480
 
481
        error = soreserve(so, rip_sendspace, rip_recvspace);
482
        if (error)
483
                return error;
484
        s = splnet();
485
        error = in_pcballoc(so, &ripcbinfo, p);
486
        splx(s);
487
        if (error)
488
                return error;
489
        inp = (struct inpcb *)so->so_pcb;
490
        inp->inp_vflag |= INP_IPV4;
491
        inp->inp_ip_p = proto;
492
        inp->inp_ip_ttl = ip_defttl;
493
        return 0;
494
}
495
 
496
static int
497
rip_detach(struct socket *so)
498
{
499
        struct inpcb *inp;
500
 
501
        inp = sotoinpcb(so);
502
        if (inp == 0)
503
                panic("rip_detach");
504
        if (so == ip_mrouter)
505
                ip_mrouter_done();
506
        ip_rsvp_force_done(so);
507
        if (so == ip_rsvpd)
508
                ip_rsvp_done();
509
        in_pcbdetach(inp);
510
        return 0;
511
}
512
 
513
static int
514
rip_abort(struct socket *so)
515
{
516
        soisdisconnected(so);
517
        return rip_detach(so);
518
}
519
 
520
static int
521
rip_disconnect(struct socket *so)
522
{
523
        if ((so->so_state & SS_ISCONNECTED) == 0)
524
                return ENOTCONN;
525
        return rip_abort(so);
526
}
527
 
528
static int
529
rip_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
530
{
531
        struct inpcb *inp = sotoinpcb(so);
532
        struct sockaddr_in *addr = (struct sockaddr_in *)nam;
533
 
534
        if (nam->sa_len != sizeof(*addr))
535
                return EINVAL;
536
 
537
        if (TAILQ_EMPTY(&ifnet) || ((addr->sin_family != AF_INET) &&
538
                                    (addr->sin_family != AF_IMPLINK)) ||
539
            (addr->sin_addr.s_addr &&
540
             ifa_ifwithaddr((struct sockaddr *)addr) == 0))
541
                return EADDRNOTAVAIL;
542
        inp->inp_laddr = addr->sin_addr;
543
        return 0;
544
}
545
 
546
static int
547
rip_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
548
{
549
        struct inpcb *inp = sotoinpcb(so);
550
        struct sockaddr_in *addr = (struct sockaddr_in *)nam;
551
 
552
        if (nam->sa_len != sizeof(*addr))
553
                return EINVAL;
554
        if (TAILQ_EMPTY(&ifnet))
555
                return EADDRNOTAVAIL;
556
        if ((addr->sin_family != AF_INET) &&
557
            (addr->sin_family != AF_IMPLINK))
558
                return EAFNOSUPPORT;
559
        inp->inp_faddr = addr->sin_addr;
560
        soisconnected(so);
561
        return 0;
562
}
563
 
564
static int
565
rip_shutdown(struct socket *so)
566
{
567
        socantsendmore(so);
568
        return 0;
569
}
570
 
571
static int
572
rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
573
         struct mbuf *control, struct proc *p)
574
{
575
        struct inpcb *inp = sotoinpcb(so);
576
        register u_long dst;
577
 
578
        if (so->so_state & SS_ISCONNECTED) {
579
                if (nam) {
580
                        m_freem(m);
581
                        return EISCONN;
582
                }
583
                dst = inp->inp_faddr.s_addr;
584
        } else {
585
                if (nam == NULL) {
586
                        m_freem(m);
587
                        return ENOTCONN;
588
                }
589
                dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;
590
        }
591
        return rip_output(m, so, dst);
592
}
593
 
594
struct pr_usrreqs rip_usrreqs = {
595
        rip_abort, pru_accept_notsupp, rip_attach, rip_bind, rip_connect,
596
        pru_connect2_notsupp, in_control, rip_detach, rip_disconnect,
597
        pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,
598
        pru_rcvoob_notsupp, rip_send, pru_sense_null, rip_shutdown,
599
        in_setsockaddr, sosend, soreceive, sopoll
600
};

powered by: WebSVN 2.1.0

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