patch-1.3.71 linux/drivers/net/tunnel.c
Next file: linux/drivers/net/wavelan.c
Previous file: linux/drivers/net/sunlance.c
Back to the patch index
Back to the overall index
- Lines: 314
- Date:
Thu Jan 1 02:00:00 1970
- Orig file:
v1.3.70/linux/drivers/net/tunnel.c
- Orig date:
Wed Feb 7 15:11:27 1996
diff -u --recursive --new-file v1.3.70/linux/drivers/net/tunnel.c linux/drivers/net/tunnel.c
@@ -1,313 +0,0 @@
-/* tunnel.c: an IP tunnel driver
-
- The purpose of this driver is to provide an IP tunnel through
- which you can tunnel network traffic transparently across subnets.
-
- This was written by looking at Nick Holloway's dummy driver
- Thanks for the great code!
-
- -Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
-
- Minor tweaks:
- Cleaned up the code a little and added some pre-1.3.0 tweaks.
- dev->hard_header/hard_header_len changed to use no headers.
- Comments/bracketing tweaked.
- Made the tunnels use dev->name not tunnel: when error reporting.
- Added tx_dropped stat
-
- -Alan Cox (Alan.Cox@linux.org) 21 March 95
-*/
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <netinet/in.h>
-#include <linux/ip.h>
-#include <linux/string.h>
-#include <asm/system.h>
-#include <linux/errno.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-#include <linux/skbuff.h>
-#include <net/ip.h>
-
-#include <net/checksum.h> /* If using 1.3.0-pre net code */
-
-#define ip_header_len sizeof(struct iphdr)
-
-static int tunnel_xmit(struct sk_buff *skb, struct device *dev);
-static struct enet_statistics *tunnel_get_stats(struct device *dev);
-
-#ifdef MODULE
-static int tunnel_open(struct device *dev)
-{
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int tunnel_close(struct device *dev)
-{
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-#endif
-
-
-int tunnel_init(struct device *dev)
-{
- static int tun_msg=0;
- if(!tun_msg)
- {
- printk ( KERN_INFO "tunnel: version v0.1a\n" );
- tun_msg=1;
- }
-
- /* Fill in fields of the dev structure with ethernet-generic values. */
- ether_setup(dev);
-
- /* Custom initialize the device structure. */
- dev->hard_start_xmit = tunnel_xmit;
- dev->get_stats = tunnel_get_stats;
- dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOMEM;
- memset(dev->priv, 0, sizeof(struct enet_statistics));
-#ifdef MODULE
- dev->open = &tunnel_open;
- dev->stop = &tunnel_close;
-#endif
- /* Now stomp the bits that are different */
- dev->type = ARPHRD_TUNNEL; /* IP tunnel hardware type (Linux 1.1.89) */
- dev->flags |= IFF_NOARP;
- dev->flags |= IFF_LOOPBACK; /* Why doesn't tunnel work without this? [ should do now - AC]*/
- dev->addr_len=0;
- dev->tx_queue_len=2; /* Small queue - it should all run through */
- dev->hard_header_len=0;
- dev->hard_header=NULL;
- dev->header_cache_bind=NULL;
- dev->rebuild_header=NULL;
- /* End of stomp 8) */
- return 0;
-}
-
-#ifdef TUNNEL_DEBUG
-void print_ip(struct iphdr *ip)
-{
- unsigned char *ipaddr;
-
- printk("IP packet:\n");
- printk("--- header len = %d\n", ip->ihl*4);
- printk("--- ip version: %d\n", ip->version);
- printk("--- ip protocol: %d\n", ip->protocol);
- ipaddr=(unsigned char *)&ip->saddr;
- printk("--- source address: %u.%u.%u.%u\n",
- *ipaddr, *(ipaddr+1), *(ipaddr+2), *(ipaddr+3));
- ipaddr=(unsigned char *)&ip->daddr;
- printk("--- destination address: %u.%u.%u.%u\n",
- *ipaddr, *(ipaddr+1), *(ipaddr+2), *(ipaddr+3));
- printk("--- total packet len: %d\n", ntohs(ip->tot_len));
-}
-#endif
-
-/* This function assumes it is being called from dev_queue_xmit()
- and that skb is filled properly by that function.
- We also presume that if we return 0, we need to free skb, but
- if we return 1, we don't free anything. Right? Wrong?
-*/
-
-static int tunnel_xmit(struct sk_buff *skb, struct device *dev)
-{
- struct enet_statistics *stats;
- struct sk_buff *skb2; /* The output packet */
- int newlen; /* The length of skb2->data */
- struct iphdr *iph; /* Our new IP header */
-
- /*
- * Return if there is nothing to do
- */
-
- if (skb == NULL || dev == NULL)
- return 0;
-
- /*
- * Make sure we are not busy (check lock variable)
- */
-
- stats = (struct enet_statistics *)dev->priv;
- cli();
- if (dev->tbusy != 0)
- {
- sti();
- stats->tx_errors++;
- return(1);
- }
- dev->tbusy = 1;
- sti();
-
- /*
- * Perform some sanity checks on the packet
- */
-
- if ( ! dev->pa_dstaddr )
- {
- printk("%s: packet sent through tunnel to never-never land!\n", dev->name);
- dev_kfree_skb(skb, FREE_WRITE);
- dev->tbusy = 0;
- return(1);
- }
-
- iph=(struct iphdr *)skb->data;
- if ( iph->version != 4 )
- {
- /*
- * Bad IP packet? Possibly an ARP packet
- */
- printk("%s: Bad IP packet: ip version %d\n", dev->name, iph->version);
- dev_kfree_skb(skb, FREE_WRITE);
- dev->tbusy = 0;
- return(0);
- }
-
-
- /*
- * Check for routing loops
- */
-
- if ( iph->protocol == IPPROTO_IPIP && iph->saddr == dev->pa_addr )
- {
- /*
- * We really should do an ICMP reply here...
- */
- printk("%s: Warning: IP routing loop!\n", dev->name);
- dev->tbusy = 0;
- dev_kfree_skb(skb, FREE_WRITE);
- return(0);
- }
-
- if ( iph->daddr == dev->pa_addr )
- {
- printk("%s: Received inbound packet -- not handled.\n",dev->name);
- dev_kfree_skb(skb, FREE_WRITE);
- dev->tbusy = 0;
- return(0);
- }
-
-#ifdef TUNNEL_DEBUG
-printk("Old IP Header....\n");
-print_ip(iph);
-#endif
- /*
- * Everything is okay:
- * See if we need to allocate memory for a new packet
- */
-
- newlen = (skb->len + ip_header_len);
- if ( !(skb2 = dev_alloc_skb(newlen)) )
- {
- printk("%s: No free memory.\n",dev->name);
- dev_kfree_skb(skb, FREE_WRITE);
- dev->tbusy = 0;
- stats->tx_dropped++;
- return(1);
- }
-
- /* Copy the packet to a new buffer, adding a new ip header */
- skb2->free=1;
- skb_put(skb2,newlen);
- iph=skb2->h.iph=(struct iphdr *)skb2->data;
- skb2->ip_hdr=iph;
- memcpy(skb2->h.iph, skb->data, ip_header_len );
- memcpy(skb2->data + ip_header_len, skb->data, skb->len);
- /* Free the old packet, we no longer need it */
- dev_kfree_skb(skb, FREE_WRITE);
-
- /* Correct the fields in the new ip header */
- ++iph->ttl; /* Note: ip_forward() decrements ttl, so compensate */
- iph->saddr = dev->pa_addr;
- iph->daddr = dev->pa_dstaddr;
- iph->protocol = IPPROTO_IPIP;
- iph->ihl = 5;
- iph->tot_len = htons(skb2->len);
- iph->frag_off = 0;
-
- /* Here is where we compute the IP checksum */
- /* ip_fast_csum() is an inline function from net/inet/ip.h/checksum.h */
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
-#ifdef TUNNEL_DEBUG
-printk("New IP Header....\n");
-print_ip(iph);
-#endif
- /* Now send the packet on its way */
-#ifdef TUNNEL_DEBUG
- printk("tunnel: calling ip_forward()\n");
-#endif
- if(ip_forward(skb2, dev, 0, iph->daddr))
- kfree_skb(skb2, FREE_WRITE);
-
-
-#ifdef TUNNEL_DEBUG
- printk("Packet sent through tunnel interface!\n");
-#endif
- /* Record statistics */
- stats->tx_packets++;
-
-#ifdef TUNNEL_DEBUG
- printk("tunnel: Updated usage statistics.\n");
-#endif
- dev->tbusy=0;
- return 0;
-}
-
-static struct enet_statistics *
-tunnel_get_stats(struct device *dev)
-{
- return((struct enet_statistics*) dev->priv);
-}
-
-#ifdef MODULE
-
-static int tunnel_probe(struct device *dev)
-{
- tunnel_init(dev);
- return 0;
-}
-
-static struct device dev_tunnel = {
- "tunl0\0 ",
- 0, 0, 0, 0,
- 0x0, 0,
- 0, 0, 0, NULL, tunnel_probe };
-
-int init_module(void)
-{
- /* Find a name for this unit */
- int ct= 1;
-
- while(dev_get(dev_tunnel.name)!=NULL && ct<100)
- {
- sprintf(dev_tunnel.name,"tunl%d",ct);
- ct++;
- }
-
-#ifdef TUNNEL_DEBUG
- printk("tunnel: registering device %s\n", dev_tunnel.name);
-#endif
- if (register_netdev(&dev_tunnel) != 0)
- return -EIO;
- return 0;
-}
-
-void cleanup_module(void)
-{
- unregister_netdev(&dev_tunnel);
- kfree_s(dev_tunnel.priv,sizeof(struct enet_statistics));
- dev_tunnel.priv=NULL;
-}
-#endif /* MODULE */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this