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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [net/] [ipv4/] [ip_input.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1629 jcastillo
/*
2
 * INET         An implementation of the TCP/IP protocol suite for the LINUX
3
 *              operating system.  INET is implemented using the  BSD Socket
4
 *              interface as the means of communication with the user level.
5
 *
6
 *              The Internet Protocol (IP) module.
7
 *
8
 * Version:     @(#)ip.c        1.0.16b 9/1/93
9
 *
10
 * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
11
 *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
12
 *              Donald Becker, <becker@super.org>
13
 *              Alan Cox, <Alan.Cox@linux.org>
14
 *              Richard Underwood
15
 *              Stefan Becker, <stefanb@yello.ping.de>
16
 *              Jorge Cwik, <jorge@laser.satlink.net>
17
 *              Arnt Gulbrandsen, <agulbra@nvg.unit.no>
18
 *
19
 *
20
 * Fixes:
21
 *              Alan Cox        :       Commented a couple of minor bits of surplus code
22
 *              Alan Cox        :       Undefining IP_FORWARD doesn't include the code
23
 *                                      (just stops a compiler warning).
24
 *              Alan Cox        :       Frames with >=MAX_ROUTE record routes, strict routes or loose routes
25
 *                                      are junked rather than corrupting things.
26
 *              Alan Cox        :       Frames to bad broadcast subnets are dumped
27
 *                                      We used to process them non broadcast and
28
 *                                      boy could that cause havoc.
29
 *              Alan Cox        :       ip_forward sets the free flag on the
30
 *                                      new frame it queues. Still crap because
31
 *                                      it copies the frame but at least it
32
 *                                      doesn't eat memory too.
33
 *              Alan Cox        :       Generic queue code and memory fixes.
34
 *              Fred Van Kempen :       IP fragment support (borrowed from NET2E)
35
 *              Gerhard Koerting:       Forward fragmented frames correctly.
36
 *              Gerhard Koerting:       Fixes to my fix of the above 8-).
37
 *              Gerhard Koerting:       IP interface addressing fix.
38
 *              Linus Torvalds  :       More robustness checks
39
 *              Alan Cox        :       Even more checks: Still not as robust as it ought to be
40
 *              Alan Cox        :       Save IP header pointer for later
41
 *              Alan Cox        :       ip option setting
42
 *              Alan Cox        :       Use ip_tos/ip_ttl settings
43
 *              Alan Cox        :       Fragmentation bogosity removed
44
 *                                      (Thanks to Mark.Bush@prg.ox.ac.uk)
45
 *              Dmitry Gorodchanin :    Send of a raw packet crash fix.
46
 *              Alan Cox        :       Silly ip bug when an overlength
47
 *                                      fragment turns up. Now frees the
48
 *                                      queue.
49
 *              Linus Torvalds/ :       Memory leakage on fragmentation
50
 *              Alan Cox        :       handling.
51
 *              Gerhard Koerting:       Forwarding uses IP priority hints
52
 *              Teemu Rantanen  :       Fragment problems.
53
 *              Alan Cox        :       General cleanup, comments and reformat
54
 *              Alan Cox        :       SNMP statistics
55
 *              Alan Cox        :       BSD address rule semantics. Also see
56
 *                                      UDP as there is a nasty checksum issue
57
 *                                      if you do things the wrong way.
58
 *              Alan Cox        :       Always defrag, moved IP_FORWARD to the config.in file
59
 *              Alan Cox        :       IP options adjust sk->priority.
60
 *              Pedro Roque     :       Fix mtu/length error in ip_forward.
61
 *              Alan Cox        :       Avoid ip_chk_addr when possible.
62
 *      Richard Underwood       :       IP multicasting.
63
 *              Alan Cox        :       Cleaned up multicast handlers.
64
 *              Alan Cox        :       RAW sockets demultiplex in the BSD style.
65
 *              Gunther Mayer   :       Fix the SNMP reporting typo
66
 *              Alan Cox        :       Always in group 224.0.0.1
67
 *      Pauline Middelink       :       Fast ip_checksum update when forwarding
68
 *                                      Masquerading support.
69
 *              Alan Cox        :       Multicast loopback error for 224.0.0.1
70
 *              Alan Cox        :       IP_MULTICAST_LOOP option.
71
 *              Alan Cox        :       Use notifiers.
72
 *              Bjorn Ekwall    :       Removed ip_csum (from slhc.c too)
73
 *              Bjorn Ekwall    :       Moved ip_fast_csum to ip.h (inline!)
74
 *              Stefan Becker   :       Send out ICMP HOST REDIRECT
75
 *      Arnt Gulbrandsen        :       ip_build_xmit
76
 *              Alan Cox        :       Per socket routing cache
77
 *              Alan Cox        :       Fixed routing cache, added header cache.
78
 *              Alan Cox        :       Loopback didn't work right in original ip_build_xmit - fixed it.
79
 *              Alan Cox        :       Only send ICMP_REDIRECT if src/dest are the same net.
80
 *              Alan Cox        :       Incoming IP option handling.
81
 *              Alan Cox        :       Set saddr on raw output frames as per BSD.
82
 *              Alan Cox        :       Stopped broadcast source route explosions.
83
 *              Alan Cox        :       Can disable source routing
84
 *              Takeshi Sone    :       Masquerading didn't work.
85
 *      Dave Bonn,Alan Cox      :       Faster IP forwarding whenever possible.
86
 *              Alan Cox        :       Memory leaks, tramples, misc debugging.
87
 *              Alan Cox        :       Fixed multicast (by popular demand 8))
88
 *              Alan Cox        :       Fixed forwarding (by even more popular demand 8))
89
 *              Alan Cox        :       Fixed SNMP statistics [I think]
90
 *      Gerhard Koerting        :       IP fragmentation forwarding fix
91
 *              Alan Cox        :       Device lock against page fault.
92
 *              Alan Cox        :       IP_HDRINCL facility.
93
 *      Werner Almesberger      :       Zero fragment bug
94
 *              Alan Cox        :       RAW IP frame length bug
95
 *              Alan Cox        :       Outgoing firewall on build_xmit
96
 *              A.N.Kuznetsov   :       IP_OPTIONS support throughout the kernel
97
 *              Alan Cox        :       Multicast routing hooks
98
 *              Jos Vos         :       Do accounting *before* call_in_firewall
99
 *      Willy Konynenberg       :       Transparent proxying support
100
 *
101
 *
102
 *
103
 * To Fix:
104
 *              IP fragmentation wants rewriting cleanly. The RFC815 algorithm is much more efficient
105
 *              and could be made very efficient with the addition of some virtual memory hacks to permit
106
 *              the allocation of a buffer that can then be 'grown' by twiddling page tables.
107
 *              Output fragmentation wants updating along with the buffer management to use a single
108
 *              interleaved copy algorithm so that fragmenting has a one copy overhead. Actual packet
109
 *              output should probably do its own fragmentation at the UDP/RAW layer. TCP shouldn't cause
110
 *              fragmentation anyway.
111
 *
112
 *              FIXME: copy frag 0 iph to qp->iph
113
 *
114
 *              This program is free software; you can redistribute it and/or
115
 *              modify it under the terms of the GNU General Public License
116
 *              as published by the Free Software Foundation; either version
117
 *              2 of the License, or (at your option) any later version.
118
 */
119
 
120
#include <asm/segment.h>
121
#include <asm/system.h>
122
#include <linux/types.h>
123
#include <linux/kernel.h>
124
#include <linux/sched.h>
125
#include <linux/mm.h>
126
#include <linux/string.h>
127
#include <linux/errno.h>
128
#include <linux/config.h>
129
 
130
#include <linux/socket.h>
131
#include <linux/sockios.h>
132
#include <linux/in.h>
133
#include <linux/inet.h>
134
#include <linux/netdevice.h>
135
#include <linux/etherdevice.h>
136
#include <linux/proc_fs.h>
137
#include <linux/stat.h>
138
 
139
#include <net/snmp.h>
140
#include <net/ip.h>
141
#include <net/protocol.h>
142
#include <net/route.h>
143
#include <net/tcp.h>
144
#include <net/udp.h>
145
#include <linux/skbuff.h>
146
#include <net/sock.h>
147
#include <net/arp.h>
148
#include <net/icmp.h>
149
#include <net/raw.h>
150
#include <net/checksum.h>
151
#include <linux/igmp.h>
152
#include <linux/ip_fw.h>
153
#ifdef CONFIG_IP_MASQUERADE
154
#include <net/ip_masq.h>
155
#endif
156
#include <linux/firewall.h>
157
#include <linux/mroute.h>
158
#include <net/netlink.h>
159
#ifdef CONFIG_NET_ALIAS
160
#include <linux/net_alias.h>
161
#endif
162
 
163
extern int last_retran;
164
extern void sort_send(struct sock *sk);
165
 
166
#define min(a,b)        ((a)<(b)?(a):(b))
167
 
168
/*
169
 *      SNMP management statistics
170
 */
171
 
172
#ifdef CONFIG_IP_FORWARD
173
struct ip_mib ip_statistics={1,64,};    /* Forwarding=Yes, Default TTL=64 */
174
#else
175
struct ip_mib ip_statistics={2,64,};    /* Forwarding=No, Default TTL=64 */
176
#endif
177
 
178
/*
179
 *      Handle the issuing of an ioctl() request
180
 *      for the ip device. This is scheduled to
181
 *      disappear
182
 */
183
 
184
int ip_ioctl(struct sock *sk, int cmd, unsigned long arg)
185
{
186
        switch(cmd)
187
        {
188
                default:
189
                        return(-EINVAL);
190
        }
191
}
192
 
193
#ifdef CONFIG_IP_TRANSPARENT_PROXY
194
/*
195
 *      Check the packet against our socket administration to see
196
 *      if it is related to a connection on our system.
197
 *      Needed for transparent proxying.
198
 */
199
 
200
int ip_chksock(struct sk_buff *skb)
201
{
202
        switch (skb->h.iph->protocol) {
203
        case IPPROTO_ICMP:
204
                return icmp_chkaddr(skb);
205
        case IPPROTO_TCP:
206
                return tcp_chkaddr(skb);
207
        case IPPROTO_UDP:
208
                return udp_chkaddr(skb);
209
        default:
210
                return 0;
211
        }
212
}
213
#endif
214
 
215
 
216
/*
217
 *      This function receives all incoming IP datagrams.
218
 *
219
 *      On entry skb->data points to the start of the IP header and
220
 *      the MAC header has been removed.
221
 */
222
 
223
int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
224
{
225
        struct iphdr *iph = skb->h.iph;
226
        struct sock *raw_sk=NULL;
227
        unsigned char hash;
228
        unsigned char flag = 0;
229
        struct inet_protocol *ipprot;
230
        int brd=IS_MYADDR;
231
        struct options * opt = NULL;
232
        int is_frag=0;
233
        __u32 daddr;
234
 
235
#ifdef CONFIG_FIREWALL
236
        int fwres;
237
        __u16 rport;
238
#endif  
239
#ifdef CONFIG_IP_MROUTE
240
        int mroute_pkt=0;
241
#endif  
242
 
243
#ifdef CONFIG_NET_IPV6
244
        /*
245
         *      Intercept IPv6 frames. We dump ST-II and invalid types just below..
246
         */
247
 
248
        if(iph->version == 6)
249
                return ipv6_rcv(skb,dev,pt);
250
#endif          
251
 
252
        ip_statistics.IpInReceives++;
253
 
254
 
255
        /*
256
         *      Tag the ip header of this packet so we can find it
257
         */
258
 
259
        skb->ip_hdr = iph;
260
 
261
        /*
262
         *      RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.
263
         *      RFC1122: 3.1.2.3 MUST discard a frame with invalid source address [NEEDS FIXING].
264
         *
265
         *      Is the datagram acceptable?
266
         *
267
         *      1.      Length at least the size of an ip header
268
         *      2.      Version of 4
269
         *      3.      Checksums correctly. [Speed optimisation for later, skip loopback checksums]
270
         *      4.      Doesn't have a bogus length
271
         *      (5.     We ought to check for IP multicast addresses and undefined types.. does this matter ?)
272
         */
273
 
274
        if (skb->len<sizeof(struct iphdr) || iph->ihl<5 || iph->version != 4 || ip_fast_csum((unsigned char *)iph, iph->ihl) !=0
275
                || skb->len < ntohs(iph->tot_len))
276
        {
277
                ip_statistics.IpInHdrErrors++;
278
                kfree_skb(skb, FREE_WRITE);
279
                return(0);
280
        }
281
 
282
        /*
283
         *      Our transport medium may have padded the buffer out. Now we know it
284
         *      is IP we can trim to the true length of the frame.
285
         *      Note this now means skb->len holds ntohs(iph->tot_len).
286
         */
287
 
288
        skb_trim(skb,ntohs(iph->tot_len));
289
 
290
        if(skb->len < (iph->ihl<<2))
291
        {
292
                ip_statistics.IpInHdrErrors++;
293
                kfree_skb(skb, FREE_WRITE);
294
                return 0;
295
        }
296
 
297
        /*
298
         *      Account for the packet (even if the packet is
299
         *      not accepted by the firewall!). We do this after
300
         *      the sanity checks and the additional ihl check
301
         *      so we dont account garbage as we might do before.
302
         */
303
 
304
#ifdef CONFIG_IP_ACCT
305
        ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN);
306
#endif  
307
 
308
        /*
309
         *      Try to select closest <src,dst> alias device, if any.
310
         *      net_alias_dev_rx32 returns main device if it
311
         *      fails to found other.
312
         *      If successful, also incr. alias rx count.
313
         *
314
         *      Only makes sense for unicasts - Thanks ANK.
315
         */
316
 
317
#ifdef CONFIG_NET_ALIAS
318
        if (skb->pkt_type == PACKET_HOST && iph->daddr != skb->dev->pa_addr && net_alias_has(skb->dev)) {
319
                skb->dev = dev = net_alias_dev_rx32(skb->dev, AF_INET, iph->saddr, iph->daddr);
320
        }
321
#endif
322
 
323
        if (iph->ihl > 5)
324
        {
325
                skb->ip_summed = 0;
326
                if (ip_options_compile(NULL, skb))
327
                        return(0);
328
                opt = (struct options*)skb->proto_priv;
329
#ifdef CONFIG_IP_NOSR
330
                if (opt->srr)
331
                {
332
                        kfree_skb(skb, FREE_READ);
333
                        return -EINVAL;
334
                }
335
#endif                                  
336
        }
337
 
338
#if defined(CONFIG_IP_TRANSPARENT_PROXY) && !defined(CONFIG_IP_ALWAYS_DEFRAG)
339
#define CONFIG_IP_ALWAYS_DEFRAG 1
340
#endif
341
#ifdef CONFIG_IP_ALWAYS_DEFRAG
342
        /*
343
         * Defragment all incoming traffic before even looking at it.
344
         * If you have forwarding enabled, this makes the system a
345
         * defragmenting router.  Not a common thing.
346
         * You probably DON'T want to enable this unless you have to.
347
         * You NEED to use this if you want to use transparent proxying,
348
         * otherwise, we can't vouch for your sanity.
349
         */
350
 
351
        /*
352
         *      See if the frame is fragmented.
353
         */
354
 
355
        if(iph->frag_off)
356
        {
357
                if (iph->frag_off & htons(IP_MF))
358
                        is_frag|=IPFWD_FRAGMENT;
359
                /*
360
                 *      Last fragment ?
361
                 */
362
 
363
                if (iph->frag_off & htons(IP_OFFSET))
364
                        is_frag|=IPFWD_LASTFRAG;
365
 
366
                /*
367
                 *      Reassemble IP fragments.
368
                 */
369
 
370
                if(is_frag)
371
                {
372
                        /* Defragment. Obtain the complete packet if there is one */
373
                        skb=ip_defrag(iph,skb,dev);
374
                        if(skb==NULL)
375
                                return 0;
376
                        skb->dev = dev;
377
                        iph=skb->h.iph;
378
                        is_frag = 0;
379
                        /*
380
                         * When the reassembled packet gets forwarded, the ip
381
                         * header checksum should be correct.
382
                         * For better performance, this should actually only
383
                         * be done in that particular case, i.e. set a flag
384
                         * here and calculate the checksum in ip_forward.
385
                         */
386
                        ip_send_check(iph);
387
                }
388
        }
389
 
390
#endif
391
        /*
392
         *      See if the firewall wants to dispose of the packet.
393
         */
394
 
395
#ifdef  CONFIG_FIREWALL
396
 
397
        if ((fwres=call_in_firewall(PF_INET, skb->dev, iph, &rport))<FW_ACCEPT)
398
        {
399
                if(fwres==FW_REJECT)
400
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
401
                kfree_skb(skb, FREE_WRITE);
402
                return 0;
403
        }
404
 
405
#ifdef  CONFIG_IP_TRANSPARENT_PROXY
406
        if (fwres==FW_REDIRECT)
407
                skb->redirport = rport;
408
        else
409
#endif
410
                skb->redirport = 0;
411
#endif
412
 
413
#ifndef CONFIG_IP_ALWAYS_DEFRAG
414
        /*
415
         *      Remember if the frame is fragmented.
416
         */
417
 
418
        if(iph->frag_off)
419
        {
420
                if (iph->frag_off & htons(IP_MF))
421
                        is_frag|=IPFWD_FRAGMENT;
422
                /*
423
                 *      Last fragment ?
424
                 */
425
 
426
                if (iph->frag_off & htons(IP_OFFSET))
427
                        is_frag|=IPFWD_LASTFRAG;
428
        }
429
 
430
#endif
431
        /*
432
         *      Do any IP forwarding required.  chk_addr() is expensive -- avoid it someday.
433
         *
434
         *      This is inefficient. While finding out if it is for us we could also compute
435
         *      the routing table entry. This is where the great unified cache theory comes
436
         *      in as and when someone implements it
437
         *
438
         *      For most hosts over 99% of packets match the first conditional
439
         *      and don't go via ip_chk_addr. Note: brd is set to IS_MYADDR at
440
         *      function entry.
441
         */
442
        daddr = iph->daddr;
443
#ifdef CONFIG_IP_TRANSPARENT_PROXY
444
        /*
445
         *      ip_chksock adds still more overhead for forwarded traffic...
446
         */
447
        if ( iph->daddr == skb->dev->pa_addr || skb->redirport || (brd = ip_chk_addr(iph->daddr)) != 0 || ip_chksock(skb))
448
#else
449
        if ( iph->daddr == skb->dev->pa_addr || (brd = ip_chk_addr(iph->daddr)) != 0)
450
#endif
451
        {
452
                if (opt && opt->srr)
453
                {
454
                        int srrspace, srrptr;
455
                        __u32 nexthop;
456
                        unsigned char * optptr = ((unsigned char *)iph) + opt->srr;
457
 
458
                        if (brd != IS_MYADDR || skb->pkt_type != PACKET_HOST)
459
                        {
460
                                kfree_skb(skb, FREE_WRITE);
461
                                return 0;
462
                        }
463
 
464
                        for ( srrptr=optptr[2], srrspace = optptr[1];
465
                              srrptr <= srrspace;
466
                              srrptr += 4
467
                             )
468
                        {
469
                                int brd2;
470
                                if (srrptr + 3 > srrspace)
471
                                {
472
                                        icmp_send(skb, ICMP_PARAMETERPROB, 0, opt->srr+2,
473
                                                  skb->dev);
474
                                        kfree_skb(skb, FREE_WRITE);
475
                                        return 0;
476
                                }
477
                                memcpy(&nexthop, &optptr[srrptr-1], 4);
478
                                if ((brd2 = ip_chk_addr(nexthop)) == 0)
479
                                        break;
480
                                if (brd2 != IS_MYADDR)
481
                                {
482
 
483
                                        /*
484
                                         *      ANK: should we implement weak tunneling of multicasts?
485
                                         *      Are they obsolete? DVMRP specs (RFC-1075) is old enough...
486
                                         *      [They are obsolete]
487
                                         */
488
                                        kfree_skb(skb, FREE_WRITE);
489
                                        return -EINVAL;
490
                                }
491
                                memcpy(&daddr, &optptr[srrptr-1], 4);
492
                        }
493
                        if (srrptr <= srrspace)
494
                        {
495
                                opt->srr_is_hit = 1;
496
                                opt->is_changed = 1;
497
                                if (sysctl_ip_forward) {
498
                                        if (ip_forward(skb, dev, is_frag, nexthop))
499
                                                kfree_skb(skb, FREE_WRITE);
500
                                } else {
501
                                        ip_statistics.IpInAddrErrors++;
502
                                        kfree_skb(skb, FREE_WRITE);
503
                                }
504
                                return 0;
505
                        }
506
                }
507
 
508
#ifdef CONFIG_IP_MULTICAST      
509
                if(!(dev->flags&IFF_ALLMULTI) && brd==IS_MULTICAST && iph->daddr!=IGMP_ALL_HOSTS && !(dev->flags&IFF_LOOPBACK))
510
                {
511
                        /*
512
                         *      Check it is for one of our groups
513
                         */
514
                        struct ip_mc_list *ip_mc=dev->ip_mc_list;
515
                        do
516
                        {
517
                                if(ip_mc==NULL)
518
                                {
519
                                        kfree_skb(skb, FREE_WRITE);
520
                                        return 0;
521
                                }
522
                                if(ip_mc->multiaddr==iph->daddr)
523
                                        break;
524
                                ip_mc=ip_mc->next;
525
                        }
526
                        while(1);
527
                }
528
#endif
529
 
530
#ifndef CONFIG_IP_ALWAYS_DEFRAG
531
                /*
532
                 *      Reassemble IP fragments.
533
                 */
534
 
535
                if(is_frag)
536
                {
537
                        /* Defragment. Obtain the complete packet if there is one */
538
                        skb=ip_defrag(iph,skb,dev);
539
                        if(skb==NULL)
540
                                return 0;
541
                        skb->dev = dev;
542
                        iph=skb->h.iph;
543
                }
544
 
545
#endif
546
 
547
#ifdef CONFIG_IP_MASQUERADE
548
                /*
549
                 * Do we need to de-masquerade this packet?
550
                 */
551
                {
552
                        int ret = ip_fw_demasquerade(&skb,dev);
553
                        if (ret < 0) {
554
                                kfree_skb(skb, FREE_WRITE);
555
                                return 0;
556
                        }
557
 
558
                        if (ret)
559
                        {
560
                                struct iphdr *iph=skb->h.iph;
561
                                if (ip_forward(skb, dev, IPFWD_MASQUERADED, iph->daddr))
562
                                        kfree_skb(skb, FREE_WRITE);
563
                                return 0;
564
                        }
565
                }
566
#endif
567
 
568
                /*
569
                 *      Point into the IP datagram, just past the header.
570
                 */
571
 
572
                skb->ip_hdr = iph;
573
                skb->h.raw += iph->ihl*4;
574
 
575
#ifdef CONFIG_IP_MROUTE         
576
                /*
577
                 *      Check the state on multicast routing (multicast and not 224.0.0.z)
578
                 */
579
 
580
                if(brd==IS_MULTICAST && (iph->daddr&htonl(0xFFFFFF00))!=htonl(0xE0000000))
581
                        mroute_pkt=1;
582
 
583
#endif
584
                /*
585
                 *      Deliver to raw sockets. This is fun as to avoid copies we want to make no surplus copies.
586
                 *
587
                 *      RFC 1122: SHOULD pass TOS value up to the transport layer.
588
                 */
589
 
590
                /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */
591
                hash = iph->protocol & (MAX_INET_PROTOS - 1);
592
 
593
                /*
594
                 *      If there maybe a raw socket we must check - if not we don't care less
595
                 */
596
 
597
                if((raw_sk = raw_v4_htable[hash]) != NULL) {
598
                        struct sock *sknext = NULL;
599
                        struct sk_buff *skb1;
600
 
601
                        raw_sk = raw_v4_lookup(raw_sk, iph->protocol,
602
                                               iph->saddr, iph->daddr);
603
                        if(raw_sk) {    /* Any raw sockets */
604
                                do {
605
                                        /* Find the next */
606
                                        sknext = raw_v4_lookup(raw_sk->next,
607
                                                               iph->protocol,
608
                                                               iph->saddr,
609
                                                               iph->daddr);
610
                                        if(sknext)
611
                                                skb1 = skb_clone(skb, GFP_ATOMIC);
612
                                        else
613
                                                break;  /* One pending raw socket left */
614
                                        if(skb1)
615
                                                raw_rcv(raw_sk, skb1, dev, iph->saddr,daddr);
616
                                        raw_sk = sknext;
617
                                } while(raw_sk!=NULL);
618
 
619
                                /*
620
                                 *      Here either raw_sk is the last raw socket, or NULL if none
621
                                 */
622
 
623
                                /*
624
                                 *      We deliver to the last raw socket AFTER the protocol checks as it avoids a surplus copy
625
                                 */
626
                        }
627
                }
628
 
629
                /*
630
                 *      skb->h.raw now points at the protocol beyond the IP header.
631
                 */
632
 
633
                for (ipprot = (struct inet_protocol *)inet_protos[hash];ipprot != NULL;ipprot=(struct inet_protocol *)ipprot->next)
634
                {
635
                        struct sk_buff *skb2;
636
 
637
                        if (ipprot->protocol != iph->protocol)
638
                                continue;
639
                       /*
640
                        *       See if we need to make a copy of it.  This will
641
                        *       only be set if more than one protocol wants it.
642
                        *       and then not for the last one. If there is a pending
643
                        *       raw delivery wait for that
644
                        */
645
 
646
#ifdef CONFIG_IP_MROUTE
647
                        if (ipprot->copy || raw_sk || mroute_pkt)
648
#else   
649
                        if (ipprot->copy || raw_sk)
650
#endif                  
651
                        {
652
                                skb2 = skb_clone(skb, GFP_ATOMIC);
653
                                if(skb2==NULL)
654
                                        continue;
655
                        }
656
                        else
657
                        {
658
                                skb2 = skb;
659
                        }
660
                        flag = 1;
661
 
662
                       /*
663
                        *       Pass on the datagram to each protocol that wants it,
664
                        *       based on the datagram protocol.  We should really
665
                        *       check the protocol handler's return values here...
666
                        */
667
 
668
                        ipprot->handler(skb2, dev, opt, daddr,
669
                                (ntohs(iph->tot_len) - (iph->ihl * 4)),
670
                                iph->saddr, 0, ipprot);
671
                }
672
 
673
                /*
674
                 *      All protocols checked.
675
                 *      If this packet was a broadcast, we may *not* reply to it, since that
676
                 *      causes (proven, grin) ARP storms and a leakage of memory (i.e. all
677
                 *      ICMP reply messages get queued up for transmission...)
678
                 */
679
 
680
#ifdef CONFIG_IP_MROUTE          
681
                /*
682
                 *      Forward the last copy to the multicast router. If
683
                 *      there is a pending raw delivery however make a copy
684
                 *      and forward that.
685
                 */
686
 
687
                if(mroute_pkt)
688
                {
689
                        flag=1;
690
                        if(raw_sk==NULL)
691
                                ipmr_forward(skb, is_frag);
692
                        else
693
                        {
694
                                struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
695
                                if(skb2)
696
                                {
697
                                        skb2->free=1;
698
                                        ipmr_forward(skb2, is_frag);
699
                                }
700
                        }
701
                }
702
#endif          
703
 
704
                if(raw_sk!=NULL)        /* Shift to last raw user */
705
                        raw_rcv(raw_sk, skb, dev, iph->saddr, daddr);
706
                else if (!flag)         /* Free and report errors */
707
                {
708
                        if (brd != IS_BROADCAST && brd!=IS_MULTICAST)
709
                                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0, dev);
710
                        kfree_skb(skb, FREE_WRITE);
711
                }
712
 
713
                return(0);
714
        }
715
 
716
        /*
717
         *      Do any unicast IP forwarding required.
718
         */
719
 
720
        /*
721
         *      Don't forward multicast or broadcast frames.
722
         */
723
 
724
        if(skb->pkt_type!=PACKET_HOST || brd==IS_BROADCAST)
725
        {
726
                kfree_skb(skb,FREE_WRITE);
727
                return 0;
728
        }
729
 
730
        /*
731
         *      The packet is for another target. Forward the frame
732
         */
733
 
734
        if (sysctl_ip_forward) {
735
                if (opt && opt->is_strictroute)
736
                {
737
                        icmp_send(skb, ICMP_PARAMETERPROB, 0, 16, skb->dev);
738
                        kfree_skb(skb, FREE_WRITE);
739
                        return -1;
740
                }
741
                if (ip_forward(skb, dev, is_frag, iph->daddr))
742
                        kfree_skb(skb, FREE_WRITE);
743
        } else {
744
/*      printk("Machine %lx tried to use us as a forwarder to %lx but we have forwarding disabled!\n",
745
                        iph->saddr,iph->daddr);*/
746
                ip_statistics.IpInAddrErrors++;
747
                kfree_skb(skb, FREE_WRITE);
748
        }
749
        return(0);
750
}
751
 
752
 

powered by: WebSVN 2.1.0

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