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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [net/] [new_tunnel.c] - Blame information for rev 1777

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

Line No. Rev Author Line
1 1626 jcastillo
/* tunnel.c: an IP tunnel driver
2
 
3
        The purpose of this driver is to provide an IP tunnel through
4
        which you can tunnel network traffic transparently across subnets.
5
 
6
        This was written by looking at Nick Holloway's dummy driver
7
        Thanks for the great code!
8
 
9
                -Sam Lantinga   (slouken@cs.ucdavis.edu)  02/01/95
10
 
11
        Minor tweaks:
12
                Cleaned up the code a little and added some pre-1.3.0 tweaks.
13
                dev->hard_header/hard_header_len changed to use no headers.
14
                Comments/bracketing tweaked.
15
                Made the tunnels use dev->name not tunnel: when error reporting.
16
                Added tx_dropped stat
17
 
18
                -Alan Cox       (Alan.Cox@linux.org) 21 March 95
19
 
20
        Reworked:
21
                Changed to tunnel to destination gateway in addition to the
22
                        tunnel's pointopoint address
23
                Almost completely rewritten
24
                Note:  There is currently no firewall or ICMP handling done.
25
 
26
                -Sam Lantinga   (slouken@cs.ucdavis.edu) 02/13/96
27
 
28
        Note:
29
                The old driver is in tunnel.c if you have funnies with the
30
                new one.
31
*/
32
 
33
/* Things I wish I had known when writing the tunnel driver:
34
 
35
        When the tunnel_xmit() function is called, the skb contains the
36
        packet to be sent (plus a great deal of extra info), and dev
37
        contains the tunnel device that _we_ are.
38
 
39
        When we are passed a packet, we are expected to fill in the
40
        source address with our source IP address.
41
 
42
        What is the proper way to allocate, copy and free a buffer?
43
        After you allocate it, it is a "0 length" chunk of memory
44
        starting at zero.  If you want to add headers to the buffer
45
        later, you'll have to call "skb_reserve(skb, amount)" with
46
        the amount of memory you want reserved.  Then, you call
47
        "skb_put(skb, amount)" with the amount of space you want in
48
        the buffer.  skb_put() returns a pointer to the top (#0) of
49
        that buffer.  skb->len is set to the amount of space you have
50
        "allocated" with skb_put().  You can then write up to skb->len
51
        bytes to that buffer.  If you need more, you can call skb_put()
52
        again with the additional amount of space you need.  You can
53
        find out how much more space you can allocate by calling
54
        "skb_tailroom(skb)".
55
        Now, to add header space, call "skb_push(skb, header_len)".
56
        This creates space at the beginning of the buffer and returns
57
        a pointer to this new space.  If later you need to strip a
58
        header from a buffer, call "skb_pull(skb, header_len)".
59
        skb_headroom() will return how much space is left at the top
60
        of the buffer (before the main data).  Remember, this headroom
61
        space must be reserved before the skb_put() function is called.
62
*/
63
 
64
#include <linux/module.h>
65
 
66
/* Only two headers!! :-) */
67
#include <net/ip.h>
68
#include <linux/if_arp.h>
69
 
70
 
71
/*#define TUNNEL_DEBUG*/
72
 
73
/*
74
 *      Our header is a simple IP packet with no options
75
 */
76
 
77
#define tunnel_hlen     sizeof(struct iphdr)
78
 
79
/*
80
 *      Okay, this needs to be high enough that we can fit a "standard"
81
 *      ethernet header and an IP tunnel header into the outgoing packet.
82
 *      [36 bytes]
83
 */
84
 
85
#define TUNL_HLEN       (((ETH_HLEN+15)&~15)+tunnel_hlen)
86
 
87
 
88
static int tunnel_open(struct device *dev)
89
{
90
        MOD_INC_USE_COUNT;
91
        return 0;
92
}
93
 
94
static int tunnel_close(struct device *dev)
95
{
96
        MOD_DEC_USE_COUNT;
97
        return 0;
98
}
99
 
100
#ifdef TUNNEL_DEBUG
101
void print_ip(struct iphdr *ip)
102
{
103
        unsigned char *ipaddr;
104
 
105
        printk("IP packet:\n");
106
        printk("--- header len = %d\n", ip->ihl*4);
107
        printk("--- ip version: %d\n", ip->version);
108
        printk("--- ip protocol: %d\n", ip->protocol);
109
        ipaddr=(unsigned char *)&ip->saddr;
110
        printk("--- source address: %u.%u.%u.%u\n",
111
                        *ipaddr, *(ipaddr+1), *(ipaddr+2), *(ipaddr+3));
112
        ipaddr=(unsigned char *)&ip->daddr;
113
        printk("--- destination address: %u.%u.%u.%u\n",
114
                        *ipaddr, *(ipaddr+1), *(ipaddr+2), *(ipaddr+3));
115
        printk("--- total packet len: %d\n", ntohs(ip->tot_len));
116
}
117
#endif
118
 
119
/*
120
 *      This function assumes it is being called from dev_queue_xmit()
121
 *      and that skb is filled properly by that function.
122
 */
123
 
124
static int tunnel_xmit(struct sk_buff *skb, struct device *dev)
125
{
126
        struct enet_statistics *stats;          /* This device's statistics */
127
        struct rtable *rt;                      /* Route to the other host */
128
        struct device *tdev;                    /* Device to other host */
129
        struct iphdr  *iph;                     /* Our new IP header */
130
        __u32          target;                  /* The other host's IP address */
131
        int      max_headroom;                  /* The extra header space needed */
132
 
133
        /*
134
         *      Return if there is nothing to do.  (Does this ever happen?)
135
         */
136
        if (skb == NULL || dev == NULL) {
137
#ifdef TUNNEL_DEBUG
138
                printk ( KERN_INFO "tunnel: Nothing to do!\n" );
139
#endif
140
                return 0;
141
        }
142
 
143
        /*
144
         *      Make sure we are not busy (check lock variable)
145
         */
146
 
147
        stats = (struct enet_statistics *)dev->priv;
148
        cli();
149
        if (dev->tbusy != 0)
150
        {
151
                sti();
152
                stats->tx_errors++;
153
                return(1);
154
        }
155
        dev->tbusy = 1;
156
        sti();
157
 
158
        /*printk("-");*/
159
        /*
160
         *  First things first.  Look up the destination address in the
161
         *  routing tables
162
         */
163
        iph = (struct iphdr *) skb->data;
164
        if ((rt = ip_rt_route(iph->daddr, 0, skb->sk?skb->sk->bound_device:NULL)) == NULL)
165
        {
166
                /* No route to host */
167
                /* Where did the packet come from? */
168
                /*icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);*/
169
                printk ( KERN_INFO "%s: Packet with no route!\n", dev->name);
170
                dev->tbusy=0;
171
                stats->tx_errors++;
172
                dev_kfree_skb(skb, FREE_WRITE);
173
                return 0;
174
        }
175
 
176
        /*
177
         * Get the target address (other end of IP tunnel)
178
         */
179
        if (rt->rt_flags & RTF_GATEWAY)
180
                target = rt->rt_gateway;
181
        else
182
                target = dev->pa_dstaddr;
183
 
184
        if ( ! target )
185
        {       /* No gateway to tunnel through? */
186
                /* Where did the packet come from? */
187
                /*icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);*/
188
                printk ( KERN_INFO "%s: Packet with no target gateway!\n", dev->name);
189
                ip_rt_put(rt);
190
                dev->tbusy=0;
191
                stats->tx_errors++;
192
                dev_kfree_skb(skb, FREE_WRITE);
193
                return 0;
194
        }
195
        ip_rt_put(rt);
196
 
197
        if ((rt = ip_rt_route(target, 0, skb->sk?skb->sk->bound_device:NULL)) == NULL)
198
        {
199
                /* No route to host */
200
                /* Where did the packet come from? */
201
                /*icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);*/
202
                printk ( KERN_INFO "%s: Can't reach target gateway!\n", dev->name);
203
                dev->tbusy=0;
204
                stats->tx_errors++;
205
                dev_kfree_skb(skb, FREE_WRITE);
206
                return 0;
207
        }
208
        tdev = rt->rt_dev;
209
 
210
        if (tdev == dev)
211
        {
212
                /* Tunnel to ourselves?  -- I don't think so. */
213
                printk ( KERN_INFO "%s: Packet targetted at myself!\n" , dev->name);
214
                ip_rt_put(rt);
215
                dev->tbusy=0;
216
                stats->tx_errors++;
217
                dev_kfree_skb(skb, FREE_WRITE);
218
                return 0;
219
        }
220
 
221
#ifdef TUNNEL_DEBUG
222
        printk("Old IP Header....\n");
223
        print_ip(iph);
224
#endif
225
 
226
        /*
227
         * Okay, now see if we can stuff it in the buffer as-is.
228
         */
229
        max_headroom = (((tdev->hard_header_len+15)&~15)+tunnel_hlen);
230
#ifdef TUNNEL_DEBUG
231
printk("Room left at head: %d\n", skb_headroom(skb));
232
printk("Room left at tail: %d\n", skb_tailroom(skb));
233
printk("Required room: %d, Tunnel hlen: %d\n", max_headroom, TUNL_HLEN);
234
#endif
235
        if (skb_headroom(skb) >= max_headroom && skb->free) {
236
                skb->h.iph = (struct iphdr *) skb_push(skb, tunnel_hlen);
237
                skb_device_unlock(skb);
238
        } else {
239
                struct sk_buff *new_skb;
240
 
241
                if ( !(new_skb = dev_alloc_skb(skb->len+max_headroom)) )
242
                {
243
                        printk( KERN_INFO "%s: Out of memory, dropped packet\n",
244
                                dev->name);
245
                        ip_rt_put(rt);
246
                        dev->tbusy = 0;
247
                        stats->tx_dropped++;
248
                        dev_kfree_skb(skb, FREE_WRITE);
249
                        return 0;
250
                }
251
                new_skb->free = 1;
252
 
253
                /*
254
                 * Reserve space for our header and the lower device header
255
                 */
256
                skb_reserve(new_skb, max_headroom);
257
 
258
                /*
259
                 * Copy the old packet to the new buffer.
260
                 * Note that new_skb->h.iph will be our (tunnel driver's) header
261
                 * and new_skb->ip_hdr is the IP header of the old packet.
262
                 */
263
                new_skb->ip_hdr = (struct iphdr *) skb_put(new_skb, skb->len);
264
                new_skb->dev = skb->dev;
265
                memcpy(new_skb->ip_hdr, skb->data, skb->len);
266
                memset(new_skb->proto_priv, 0, sizeof(skb->proto_priv));
267
 
268
                /* Tack on our header */
269
                new_skb->h.iph = (struct iphdr *) skb_push(new_skb, tunnel_hlen);
270
                new_skb->mac.raw = (void *)new_skb->ip_hdr;
271
 
272
                /* Free the old packet, we no longer need it */
273
                dev_kfree_skb(skb, FREE_WRITE);
274
                skb = new_skb;
275
        }
276
 
277
        /*
278
         *      Push down and install the IPIP header.
279
         */
280
 
281
        iph                     =       skb->h.iph;
282
        iph->version            =       4;
283
        iph->tos                =       skb->ip_hdr->tos;
284
        iph->ttl                =       skb->ip_hdr->ttl;
285
        iph->frag_off           =       0;
286
        iph->daddr              =       target;
287
        iph->saddr              =       tdev->pa_addr;
288
        iph->protocol           =       IPPROTO_IPIP;
289
        iph->ihl                =       5;
290
        iph->tot_len            =       htons(skb->len);
291
        iph->id                 =       htons(ip_id_count++);   /* Race condition here? */
292
        ip_send_check(iph);
293
        skb->ip_hdr             =       skb->h.iph;
294
        skb->protocol           =       htons(ETH_P_IP);
295
#ifdef TUNNEL_DEBUG
296
        printk("New IP Header....\n");
297
        print_ip(iph);
298
#endif
299
 
300
        /*
301
         *      Send the packet on its way!
302
         *      Note that dev_queue_xmit() will eventually free the skb.
303
         *      If ip_forward() made a copy, it will return 1 so we can free.
304
         */
305
 
306
        if (sysctl_ip_forward) {
307
                if (ip_forward(skb, dev, IPFWD_NOTTLDEC, target))
308
                        kfree_skb(skb, FREE_WRITE);
309
        } else
310
                kfree_skb(skb, FREE_WRITE);
311
 
312
        /*
313
         *      Clean up:  We're done with the route and the packet
314
         */
315
 
316
        ip_rt_put(rt);
317
 
318
#ifdef TUNNEL_DEBUG
319
        printk("Packet sent through tunnel interface!\n");
320
#endif
321
/*printk(">");*/
322
        /* Record statistics and return */
323
        stats->tx_packets++;
324
        dev->tbusy=0;
325
        return 0;
326
}
327
 
328
static struct enet_statistics *tunnel_get_stats(struct device *dev)
329
{
330
        return((struct enet_statistics*) dev->priv);
331
}
332
 
333
/*
334
 *      Called when a new tunnel device is initialized.
335
 *      The new tunnel device structure is passed to us.
336
 */
337
 
338
int tunnel_init(struct device *dev)
339
{
340
        int i;
341
 
342
        /* Oh, just say we're here, in case anyone cares */
343
        static int tun_msg=0;
344
        if(!tun_msg)
345
        {
346
                printk ( KERN_INFO "tunnel: version v0.2b2\n" );
347
                tun_msg=1;
348
        }
349
 
350
        /* Add our tunnel functions to the device */
351
        dev->open               = tunnel_open;
352
        dev->stop               = tunnel_close;
353
        dev->hard_start_xmit    = tunnel_xmit;
354
        dev->get_stats          = tunnel_get_stats;
355
        dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
356
        if (dev->priv == NULL)
357
                return -ENOMEM;
358
        memset(dev->priv, 0, sizeof(struct enet_statistics));
359
 
360
        /* Initialize the tunnel device structure */
361
        for (i = 0; i < DEV_NUMBUFFS; i++)
362
                skb_queue_head_init(&dev->buffs[i]);
363
 
364
        dev->hard_header        = NULL;
365
        dev->rebuild_header     = NULL;
366
        dev->set_mac_address    = NULL;
367
        dev->header_cache_bind  = NULL;
368
        dev->header_cache_update= NULL;
369
 
370
        dev->type                               = ARPHRD_TUNNEL;
371
        dev->hard_header_len    = TUNL_HLEN;
372
        dev->mtu                = 1500-tunnel_hlen;     /* eth_mtu */
373
        dev->addr_len           = 0;             /* Is this only for ARP? */
374
        dev->tx_queue_len       = 2;            /* Small queue */
375
        memset(dev->broadcast,0xFF, ETH_ALEN);
376
 
377
        /* New-style flags. */
378
        dev->flags              = IFF_NOARP;    /* Don't use ARP on this device */
379
                                                /* No broadcasting through a tunnel */
380
        dev->family             = AF_INET;
381
        dev->pa_addr            = 0;
382
        dev->pa_brdaddr         = 0;
383
        dev->pa_mask            = 0;
384
        dev->pa_alen            = 4;
385
 
386
        /* We're done.  Have I forgotten anything? */
387
        return 0;
388
}
389
 
390
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
391
/*  Module specific interface                                      */
392
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
393
#ifdef MODULE
394
 
395
static int tunnel_probe(struct device *dev)
396
{
397
        tunnel_init(dev);
398
        return 0;
399
}
400
 
401
static struct device dev_tunnel =
402
{
403
        "tunl0\0   ",
404
        0, 0, 0, 0,
405
        0x0, 0,
406
        0, 0, 0, NULL, tunnel_probe
407
 };
408
 
409
int init_module(void)
410
{
411
        /* Find a name for this unit */
412
        int ct= 1;
413
 
414
        while(dev_get(dev_tunnel.name)!=NULL && ct<100)
415
        {
416
                sprintf(dev_tunnel.name,"tunl%d",ct);
417
                ct++;
418
        }
419
 
420
#ifdef TUNNEL_DEBUG
421
        printk("tunnel: registering device %s\n", dev_tunnel.name);
422
#endif
423
        if (register_netdev(&dev_tunnel) != 0)
424
                return -EIO;
425
        return 0;
426
}
427
 
428
void cleanup_module(void)
429
{
430
        unregister_netdev(&dev_tunnel);
431
        kfree_s(dev_tunnel.priv,sizeof(struct enet_statistics));
432
        dev_tunnel.priv=NULL;
433
}
434
#endif /* MODULE */
435
 

powered by: WebSVN 2.1.0

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