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

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [net/] [ipv4/] [ip_forward.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
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 IP forwarding functionality.
7
 *
8
 * Authors:     see ip.c
9
 *
10
 * Fixes:
11
 *              Many            :       Split from ip.c , see ip_input.c for
12
 *                                      history.
13
 *              Dave Gregorich  :       NULL ip_rt_put fix for multicast
14
 *                                      routing.
15
 *              Jos Vos         :       Add call_out_firewall before sending,
16
 *                                      use output device for accounting.
17
 *              Jos Vos         :       Call forward firewall after routing
18
 *                                      (always use output device).
19
 *              Philip Gladstone:       Add some missing ip_rt_put()
20
 */
21
 
22
#include <linux/config.h>
23
#include <linux/types.h>
24
#include <linux/mm.h>
25
#include <linux/sched.h>
26
#include <linux/skbuff.h>
27
#include <linux/ip.h>
28
#include <linux/icmp.h>
29
#include <linux/netdevice.h>
30
#include <net/sock.h>
31
#include <net/ip.h>
32
#include <net/icmp.h>
33
#include <linux/tcp.h>
34
#include <linux/udp.h>
35
#include <linux/firewall.h>
36
#include <linux/ip_fw.h>
37
#ifdef CONFIG_IP_MASQUERADE
38
#include <net/ip_masq.h>
39
#endif
40
#include <net/checksum.h>
41
#include <linux/route.h>
42
#include <net/route.h>
43
 
44
#ifdef CONFIG_IP_FORWARD /* set the default */
45
int sysctl_ip_forward = 1;
46
#else
47
int sysctl_ip_forward = 0;
48
#endif
49
 
50
#ifdef CONFIG_IP_MROUTE
51
 
52
/*
53
 *      Encapsulate a packet by attaching a valid IPIP header to it.
54
 *      This avoids tunnel drivers and other mess and gives us the speed so
55
 *      important for multicast video.
56
 */
57
 
58
static void ip_encap(struct sk_buff *skb, int len, struct device *out, __u32 daddr)
59
{
60
        /*
61
         *      There is space for the IPIP header and MAC left.
62
         *
63
         *      Firstly push down and install the IPIP header.
64
         */
65
        struct iphdr *iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr));
66
 
67
        if(len>65515)
68
                len=65515;
69
 
70
 
71
        iph->version    =       4;
72
        iph->tos        =       skb->ip_hdr->tos;
73
        iph->ttl        =       skb->ip_hdr->ttl;
74
        iph->frag_off   =       0;
75
        iph->daddr      =       daddr;
76
        iph->saddr      =       out->pa_addr;
77
        iph->protocol   =       IPPROTO_IPIP;
78
        iph->ihl        =       5;
79
        iph->tot_len    =       htons(skb->len + len);  /* Anand, ernet */
80
        iph->id         =       htons(ip_id_count++);
81
        ip_send_check(iph);
82
 
83
        skb->dev = out;
84
        skb->arp = 1;
85
        skb->raddr=daddr;  /* Router address is not destination address. The
86
                            * correct value is given eventually. I have not
87
                            * removed this statement. But could have.
88
                            * Anand, ernet.
89
                            */
90
        /*
91
         *      Now add the physical header (driver will push it down).
92
         */
93
 
94
        /* The last parameter of out->hard_header() needed skb->len + len.
95
         * Anand, ernet.
96
         */
97
        if (out->hard_header && out->hard_header(skb, out, ETH_P_IP, NULL, NULL,
98
        skb->len + len)<0)
99
                        skb->arp=0;
100
        /*
101
         *      Read to queue for transmission.
102
         */
103
}
104
 
105
#endif
106
 
107
/*
108
 *      Forward an IP datagram to its next destination.
109
 */
110
 
111
int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
112
               __u32 target_addr)
113
{
114
        struct device *dev2;    /* Output device */
115
        struct iphdr *iph;      /* Our header */
116
        struct sk_buff *skb2;   /* Output packet */
117
        struct rtable *rt = NULL;       /* Route we use */
118
        unsigned char *ptr;     /* Data pointer */
119
        unsigned long raddr;    /* Router IP address */
120
        struct   options * opt  = (struct options*)skb->proto_priv;
121
        struct hh_cache *hh = NULL;
122
        int encap = 0;           /* Encap length */
123
#ifdef CONFIG_FIREWALL
124
        int fw_res = 0;          /* Forwarding result */
125
#ifdef CONFIG_IP_MASQUERADE     
126
        struct sk_buff *skb_in = skb;   /* So we can remember if the masquerader did some swaps */
127
#endif /* CONFIG_IP_MASQUERADE */
128
#endif /* CONFIG_FIREWALL */
129
 
130
        /*
131
         *      According to the RFC, we must first decrease the TTL field. If
132
         *      that reaches zero, we must reply an ICMP control message telling
133
         *      that the packet's lifetime expired.
134
         *
135
         *      Exception:
136
         *      We may not generate an ICMP for an ICMP. icmp_send does the
137
         *      enforcement of this so we can forget it here. It is however
138
         *      sometimes VERY important.
139
         */
140
 
141
        iph = skb->h.iph;
142
        if (!(is_frag&IPFWD_NOTTLDEC))
143
        {
144
                unsigned long checksum = iph->check;
145
                iph->ttl--;
146
 
147
        /*
148
         *      Re-compute the IP header checksum.
149
         *      This is efficient. We know what has happened to the header
150
         *      and can thus adjust the checksum as Phil Karn does in KA9Q
151
         *      except we do this in "network byte order".
152
         */
153
                checksum += htons(0x0100);
154
                /* carry overflow? */
155
                checksum += checksum >> 16;
156
                iph->check = checksum;
157
        }
158
 
159
        if (iph->ttl <= 0)
160
        {
161
                /* Tell the sender its packet died... */
162
                icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev);
163
                return -1;
164
        }
165
 
166
        /* If IPFWD_MULTITUNNEL flag is set, then we have to perform routing
167
         * decision so as to reach the other end of the tunnel. This condition
168
         * also means that we are dealing with a unicast IP packet "in a way".
169
         * Anand, ernet.
170
         */
171
 
172
#ifdef CONFIG_IP_MROUTE
173
        if(!(is_frag&IPFWD_MULTICASTING) || (is_frag&IPFWD_MULTITUNNEL))
174
        {
175
#endif  
176
                /*
177
                 * OK, the packet is still valid.  Fetch its destination address,
178
                 * and give it to the IP sender for further processing.
179
                 */
180
 
181
                rt = ip_rt_route(target_addr, 0, NULL);
182
 
183
                if (rt == NULL)
184
                {
185
                        /*
186
                         *      Tell the sender its packet cannot be delivered. Again
187
                         *      ICMP is screened later.
188
                         */
189
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
190
                        return -1;
191
                }
192
 
193
 
194
                /*
195
                 * Gosh.  Not only is the packet valid; we even know how to
196
                 * forward it onto its final destination.  Can we say this
197
                 * is being plain lucky?
198
                 * If the router told us that there is no GW, use the dest.
199
                 * IP address itself- we seem to be connected directly...
200
                 */
201
 
202
                raddr = rt->rt_gateway;
203
 
204
                if (opt->is_strictroute && (rt->rt_flags & RTF_GATEWAY)) {
205
                        /*
206
                         *      Strict routing permits no gatewaying
207
                         */
208
 
209
                        ip_rt_put(rt);
210
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0, dev);
211
                        return -1;
212
                }
213
 
214
                /*
215
                 *      Having picked a route we can now send the frame out
216
                 *      after asking the firewall permission to do so.
217
                 */
218
 
219
                dev2 = rt->rt_dev;
220
                hh = rt->rt_hh;
221
                /*
222
                 *      In IP you never have to forward a frame on the interface that it
223
                 *      arrived upon. We now generate an ICMP HOST REDIRECT giving the route
224
                 *      we calculated.
225
                 */
226
#ifndef CONFIG_IP_NO_ICMP_REDIRECT
227
                if (dev == dev2 &&
228
                        !((iph->saddr^dev->pa_addr)&dev->pa_mask) &&
229
                        /* The daddr!=raddr test isn't obvious - what it's doing
230
                           is avoiding sending a frame the receiver will not
231
                           believe anyway.. */
232
                        iph->daddr != raddr/*ANK*/ && !opt->srr)
233
                                icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
234
#endif
235
#ifdef CONFIG_IP_MROUTE
236
 
237
                /* This is for ip encap. Anand, ernet.*/
238
 
239
                if (is_frag&IPFWD_MULTITUNNEL)
240
                {
241
                        encap=20;
242
                }
243
        }
244
        else
245
        {
246
                /*
247
                 *      Multicast route forward. Routing is already done
248
                 */
249
                dev2=skb->dev;
250
                raddr=skb->raddr;
251
                if(is_frag&IPFWD_MULTITUNNEL)   /* VIFF_TUNNEL mode */
252
                        encap=20;
253
                rt=NULL;
254
        }
255
#endif  
256
 
257
        /*
258
         *      See if we are allowed to forward this.
259
         *      Note: demasqueraded fragments are always 'back'warded.
260
         */
261
 
262
#ifdef CONFIG_FIREWALL
263
        if(!(is_frag&IPFWD_MASQUERADED))
264
        {
265
#ifdef CONFIG_IP_MASQUERADE
266
                /*
267
                 *      Check that any ICMP packets are not for a
268
                 *      masqueraded connection.  If so rewrite them
269
                 *      and skip the firewall checks
270
                 */
271
                if (iph->protocol == IPPROTO_ICMP)
272
                {
273
#ifdef CONFIG_IP_MASQUERADE_ICMP
274
#define icmph ((struct icmphdr *)((char *)iph + (iph->ihl<<2)))
275
                     if ((icmph->type==ICMP_DEST_UNREACH)||
276
                         (icmph->type==ICMP_SOURCE_QUENCH)||
277
                         (icmph->type==ICMP_TIME_EXCEEDED))
278
                       {
279
#endif
280
                        if ((fw_res = ip_fw_masq_icmp(&skb, dev2)) < 0)
281
                        {
282
                                if (rt)
283
                                        ip_rt_put(rt);
284
                                /* Problem - ie bad checksum */
285
                                return -1;
286
                        }
287
 
288
                        if (fw_res)
289
                                /* ICMP matched - skip firewall */
290
                                goto skip_call_fw_firewall;
291
#ifdef CONFIG_IP_MASQUERADE_ICMP
292
                       }
293
#endif                          
294
                }
295
#endif
296
                fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL);
297
                switch (fw_res) {
298
                case FW_ACCEPT:
299
                case FW_MASQUERADE:
300
                        break;
301
                case FW_REJECT:
302
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
303
                        /* fall thru */
304
                default:
305
                        if (rt)
306
                                ip_rt_put(rt);
307
                        return -1;
308
                }
309
 
310
#ifdef CONFIG_IP_MASQUERADE
311
                skip_call_fw_firewall:
312
#endif          
313
        }
314
#endif
315
 
316
        /*
317
         * We now may allocate a new buffer, and copy the datagram into it.
318
         * If the indicated interface is up and running, kick it.
319
         */
320
 
321
        if (dev2->flags & IFF_UP)
322
        {
323
#ifdef CONFIG_IP_MASQUERADE
324
                __u32   premasq_saddr = iph->saddr;
325
                __u16   premasq_sport = 0;
326
                __u16   *portptr=NULL;
327
                long    premasq_len_diff = skb->len;
328
 
329
                if (iph->protocol==IPPROTO_UDP ||
330
                    iph->protocol==IPPROTO_TCP) {
331
                        portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
332
                        premasq_sport = portptr[0];
333
                }
334
 
335
                /*
336
                 * If this fragment needs masquerading, make it so...
337
                 * (Don't masquerade de-masqueraded fragments)
338
                 */
339
                if (!(is_frag&IPFWD_MASQUERADED) && fw_res==FW_MASQUERADE)
340
                        if (ip_fw_masquerade(&skb, dev2) < 0)
341
                        {
342
                                /*
343
                                 * Masquerading failed; silently discard this packet.
344
                                 */
345
                                if (rt)
346
                                        ip_rt_put(rt);
347
                                return -1;
348
                        }
349
#endif
350
                IS_SKB(skb);
351
 
352
                if (skb->len+encap > dev2->mtu && (iph->frag_off & htons(IP_DF)))
353
                {
354
                        ip_statistics.IpFragFails++;
355
#ifdef CONFIG_IP_MASQUERADE
356
                        /* If we're demasquerading, put the correct daddr back */
357
                        if (is_frag&IPFWD_MASQUERADED)
358
                                iph->daddr = dev->pa_addr;
359
 
360
                        /* If we're masquerading, put the correct source back */
361
                        else if (fw_res==FW_MASQUERADE) {
362
                                iph->saddr = premasq_saddr;
363
                                if (premasq_sport)
364
                                        portptr[0] = premasq_sport;
365
                        }
366
 
367
                        /* If the packet has got larger and this has caused it to
368
                           exceed the MTU, then we'll claim that our MTU just got
369
                           smaller and hope it works */
370
                        premasq_len_diff -= skb->len;
371
 
372
                        if (premasq_len_diff < 0)
373
                                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
374
                                          htonl(dev2->mtu+premasq_len_diff), dev);
375
                        else
376
#endif
377
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dev2->mtu), dev);
378
                        if(rt)
379
                                ip_rt_put(rt);
380
                        return -1;
381
                }
382
 
383
#ifdef CONFIG_IP_MROUTE
384
                if(skb_headroom(skb)-encap<dev2->hard_header_len)
385
                {
386
                        skb2 = alloc_skb(dev2->hard_header_len + skb->len + encap + 15, GFP_ATOMIC);
387
#else
388
                if(skb_headroom(skb)<dev2->hard_header_len)
389
                {
390
                        skb2 = alloc_skb(dev2->hard_header_len + skb->len + 15, GFP_ATOMIC);
391
#endif          
392
                        /*
393
                         *      This is rare and since IP is tolerant of network failures
394
                         *      quite harmless.
395
                         */
396
 
397
                        if (skb2 == NULL)
398
                        {
399
                                NETDEBUG(printk("\nIP: No memory available for IP forward\n"));
400
                                if(rt)
401
                                        ip_rt_put(rt);
402
                                return -1;
403
                        }
404
 
405
                        IS_SKB(skb2);
406
                        /*
407
                         *      Add the physical headers.
408
                         */
409
                        skb2->protocol=htons(ETH_P_IP);
410
#ifdef CONFIG_IP_MROUTE
411
                        if(is_frag&IPFWD_MULTITUNNEL)
412
                        {
413
                                skb_reserve(skb2,(encap+dev2->hard_header_len+15)&~15); /* 16 byte aligned IP headers are good */
414
 
415
/* We need to pass on IP information of the incoming packet to ip_encap()
416
 * to fillin ttl, and tos fields.The destination should be target_addr.
417
 *  Anand, ernet.
418
 */
419
 
420
                                skb2->ip_hdr = skb->ip_hdr;
421
 
422
                                ip_encap(skb2,skb->len, dev2, target_addr);
423
 
424
/*  The router address is got earlier that to take us to the remote tunnel
425
 *  Anand, ernet.
426
 */
427
                                skb2->raddr = rt->rt_gateway;
428
                        }
429
                        else
430
#endif                  
431
                                ip_send(rt,skb2,raddr,skb->len,dev2,dev2->pa_addr);
432
 
433
                        /*
434
                         *      We have to copy the bytes over as the new header wouldn't fit
435
                         *      the old buffer. This should be very rare.
436
                         */
437
 
438
                        ptr = skb_put(skb2,skb->len);
439
                        skb2->free = 1;
440
                        skb2->h.raw = ptr;
441
                        /*
442
                         *      Copy the packet data into the new buffer.
443
                         */
444
                        memcpy(ptr, skb->h.raw, skb->len);
445
                        memcpy(skb2->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
446
                        iph = skb2->ip_hdr = skb2->h.iph;
447
                }
448
                else
449
                {
450
                        /*
451
                         *      Build a new MAC header.
452
                         */
453
 
454
                        skb2 = skb;
455
                        skb2->dev=dev2;
456
#ifdef CONFIG_IP_MROUTE
457
                        if(is_frag&IPFWD_MULTITUNNEL)
458
                                ip_encap(skb, 0, dev2, target_addr);
459
                        else
460
                        {
461
#endif
462
                                skb->arp=1;
463
                                skb->raddr=raddr;
464
                                if (hh)
465
                                {
466
                                        memcpy(skb_push(skb, dev2->hard_header_len), hh->hh_data, dev2->hard_header_len);
467
                                        if (!hh->hh_uptodate)
468
                                        {
469
#if RT_CACHE_DEBUG >= 2
470
                                                printk("ip_forward: hh miss %08x via %08x\n", target_addr, rt->rt_gateway);
471
#endif                                          
472
                                                skb->arp = 0;
473
                                        }
474
                                }
475
                                else if (dev2->hard_header)
476
                                {
477
                                        if(dev2->hard_header(skb, dev2, ETH_P_IP, NULL, NULL, skb->len)<0)
478
                                                skb->arp=0;
479
                                }
480
#ifdef CONFIG_IP_MROUTE
481
                        }
482
#endif                  
483
                }
484
#ifdef CONFIG_FIREWALL
485
                if((fw_res = call_out_firewall(PF_INET, skb2->dev, iph, NULL)) < FW_ACCEPT)
486
                {
487
                        /* FW_ACCEPT and FW_MASQUERADE are treated equal:
488
                           masquerading is only supported via forward rules */
489
                        if (fw_res == FW_REJECT)
490
                                icmp_send(skb2, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
491
                        if (skb != skb2)
492
                                kfree_skb(skb2,FREE_WRITE);
493
                        if (rt)
494
                                ip_rt_put(rt);
495
                        return -1;
496
                }
497
#endif
498
                ip_statistics.IpForwDatagrams++;
499
 
500
                if (opt->optlen)
501
                {
502
                        unsigned char * optptr;
503
                        if (opt->rr_needaddr)
504
                        {
505
                                optptr = (unsigned char *)iph + opt->rr;
506
                                memcpy(&optptr[optptr[2]-5], &dev2->pa_addr, 4);
507
                                opt->is_changed = 1;
508
                        }
509
                        if (opt->srr_is_hit)
510
                        {
511
                                int srrptr, srrspace;
512
 
513
                                optptr = (unsigned char *)iph + opt->srr;
514
 
515
                                for ( srrptr=optptr[2], srrspace = optptr[1];
516
                                      srrptr <= srrspace;
517
                                     srrptr += 4
518
                                    )
519
                                {
520
                                        if (srrptr + 3 > srrspace)
521
                                                break;
522
                                        if (memcmp(&target_addr, &optptr[srrptr-1], 4) == 0)
523
                                                break;
524
                                }
525
                                if (srrptr + 3 <= srrspace)
526
                                {
527
                                        opt->is_changed = 1;
528
                                        memcpy(&optptr[srrptr-1], &dev2->pa_addr, 4);
529
                                        iph->daddr = target_addr;
530
                                        optptr[2] = srrptr+4;
531
                                }
532
                                else
533
                                        printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n");
534
                        }
535
                        if (opt->ts_needaddr)
536
                        {
537
                                optptr = (unsigned char *)iph + opt->ts;
538
                                memcpy(&optptr[optptr[2]-9], &dev2->pa_addr, 4);
539
                                opt->is_changed = 1;
540
                        }
541
                        if (opt->is_changed)
542
                        {
543
                                opt->is_changed = 0;
544
                                ip_send_check(iph);
545
                        }
546
                }
547
/*
548
 * ANK:  this is point of "no return", we cannot send an ICMP,
549
 *       because we changed SRR option.
550
 */
551
 
552
                /*
553
                 *      See if it needs fragmenting. Note in ip_rcv we tagged
554
                 *      the fragment type. This must be right so that
555
                 *      the fragmenter does the right thing.
556
                 */
557
 
558
                if(skb2->len > dev2->mtu + dev2->hard_header_len)
559
                {
560
                        ip_fragment(NULL,skb2,dev2, is_frag);
561
                        kfree_skb(skb2,FREE_WRITE);
562
                }
563
                else
564
                {
565
#ifdef CONFIG_IP_ACCT           
566
                        /*
567
                         *      Count mapping we shortcut
568
                         */
569
 
570
                        ip_fw_chk(iph,dev2,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
571
#endif                  
572
 
573
                        /*
574
                         *      Map service types to priority. We lie about
575
                         *      throughput being low priority, but it's a good
576
                         *      choice to help improve general usage.
577
                         */
578
                        if(iph->tos & IPTOS_LOWDELAY)
579
                                dev_queue_xmit(skb2, dev2, SOPRI_INTERACTIVE);
580
                        else if(iph->tos & IPTOS_THROUGHPUT)
581
                                dev_queue_xmit(skb2, dev2, SOPRI_BACKGROUND);
582
                        else
583
                                dev_queue_xmit(skb2, dev2, SOPRI_NORMAL);
584
                }
585
        }
586
        else
587
        {
588
                if(rt)
589
                        ip_rt_put(rt);
590
                return -1;
591
        }
592
        if(rt)
593
                ip_rt_put(rt);
594
 
595
        /*
596
         *      Tell the caller if their buffer is free.
597
         */
598
 
599
        if(skb==skb2)
600
                return 0;
601
 
602
#ifdef CONFIG_IP_MASQUERADE     
603
        /*
604
         *      The original is free. Free our copy and
605
         *      tell the caller not to free.
606
         */
607
        if(skb!=skb_in)
608
        {
609
                kfree_skb(skb_in, FREE_WRITE);
610
                return 0;
611
        }
612
#endif  
613
        return 1;
614
}
615
 
616
 
617
 
618
 
619
 

powered by: WebSVN 2.1.0

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