root/drivers/net/tunnel.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tunnel_open
  2. tunnel_close
  3. tunnel_init
  4. print_ip
  5. tunnel_xmit
  6. tunnel_get_stats
  7. tunnel_probe
  8. init_module
  9. cleanup_module

   1 /* 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 
  21 #include <linux/config.h>
  22 #ifdef CONFIG_IP_FORWARD
  23 #ifdef MODULE
  24 #include <linux/module.h>
  25 #include <linux/version.h>
  26 #endif
  27 
  28 #include <linux/kernel.h>
  29 #include <linux/sched.h>
  30 #include <linux/types.h>
  31 #include <netinet/in.h>
  32 #include <linux/ip.h>
  33 #include <linux/string.h>
  34 #include <asm/system.h>
  35 #include <linux/errno.h>
  36 
  37 #include <linux/netdevice.h>
  38 #include <linux/etherdevice.h>
  39 #include <linux/if_arp.h>
  40 #include <linux/skbuff.h>
  41 #include <net/ip.h>
  42 
  43 #include <net/checksum.h>               /* If using 1.3.0-pre net code */
  44 
  45 #define ip_header_len   sizeof(struct iphdr)
  46 
  47 static int tunnel_xmit(struct sk_buff *skb, struct device *dev);
  48 static struct enet_statistics *tunnel_get_stats(struct device *dev);
  49 
  50 #ifdef MODULE
  51 static int tunnel_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53         MOD_INC_USE_COUNT;
  54         return 0;
  55 }
  56 
  57 static int tunnel_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         MOD_DEC_USE_COUNT;
  60         return 0;
  61 }
  62 
  63 #endif
  64 
  65 
  66 int tunnel_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {
  68         static int tun_msg=0;
  69         if(!tun_msg)
  70         {
  71                 printk ( KERN_INFO "tunnel: version v0.1a\n" );
  72                 tun_msg=1;
  73         }
  74 
  75         /* Fill in fields of the dev structure with ethernet-generic values. */
  76         ether_setup(dev);
  77 
  78         /* Custom initialize the device structure. */
  79         dev->hard_start_xmit = tunnel_xmit;
  80         dev->get_stats = tunnel_get_stats;
  81         dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
  82         if (dev->priv == NULL)
  83                 return -ENOMEM;
  84         memset(dev->priv, 0, sizeof(struct enet_statistics));
  85 #ifdef MODULE
  86         dev->open = &tunnel_open;
  87         dev->stop = &tunnel_close;
  88 #endif
  89         /* Now stomp the bits that are different */
  90         dev->type = ARPHRD_TUNNEL; /* IP tunnel hardware type (Linux 1.1.89) */
  91         dev->flags |= IFF_NOARP;
  92         dev->flags |= IFF_LOOPBACK; /* Why doesn't tunnel work without this? [ should do now - AC]*/
  93         dev->addr_len=0;
  94         dev->hard_header_len=0;
  95         dev->hard_header=NULL;
  96         dev->header_cache=NULL;
  97         dev->rebuild_header=NULL;
  98         /* End of stomp 8) */
  99         return 0;
 100 }
 101 
 102 #ifdef TUNNEL_DEBUG
 103 void print_ip(struct iphdr *ip)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         unsigned char *ipaddr;
 106 
 107         printk("IP packet:\n");
 108         printk("--- header len = %d\n", ip->ihl*4);
 109         printk("--- ip version: %d\n", ip->version);
 110         printk("--- ip protocol: %d\n", ip->protocol);
 111         ipaddr=(unsigned char *)&ip->saddr;
 112         printk("--- source address: %u.%u.%u.%u\n", 
 113                         *ipaddr, *(ipaddr+1), *(ipaddr+2), *(ipaddr+3));
 114         ipaddr=(unsigned char *)&ip->daddr;
 115         printk("--- destination address: %u.%u.%u.%u\n", 
 116                         *ipaddr, *(ipaddr+1), *(ipaddr+2), *(ipaddr+3));
 117         printk("--- total packet len: %d\n", ntohs(ip->tot_len));
 118 }
 119 #endif
 120 
 121 /* This function assumes it is being called from dev_queue_xmit()
 122    and that skb is filled properly by that function.
 123    We also presume that if we return 0, we need to free skb, but
 124    if we return 1, we don't free anything.  Right?  Wrong?
 125 */
 126 
 127 static int tunnel_xmit(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129         struct enet_statistics *stats;
 130         struct sk_buff *skb2;           /* The output packet */
 131         int newlen;                     /* The length of skb2->data */
 132         struct iphdr *iph;              /* Our new IP header */
 133 
 134         /*
 135          *      Return if there is nothing to do 
 136          */
 137          
 138         if (skb == NULL || dev == NULL)
 139                 return 0;
 140 
 141         /* 
 142          *      Make sure we are not busy (check lock variable) 
 143          */
 144          
 145         stats = (struct enet_statistics *)dev->priv;
 146         cli();
 147         if (dev->tbusy != 0) 
 148         {
 149                 sti();
 150                 stats->tx_errors++;
 151                 return(1);
 152         }
 153         dev->tbusy = 1;
 154         sti();
 155   
 156         /*
 157          *      Perform some sanity checks on the packet 
 158          */
 159          
 160         if ( ! dev->pa_dstaddr ) 
 161         {
 162                 printk("%s: packet sent through tunnel to never-never land!\n", dev->name);
 163                 dev_kfree_skb(skb, FREE_WRITE);
 164                 dev->tbusy = 0;
 165                 return(1);
 166         }
 167 
 168         iph=(struct iphdr *)skb->data;
 169         if ( iph->version != 4 ) 
 170         {  
 171                 /* 
 172                  *      Bad IP packet? Possibly an ARP packet 
 173                  */
 174                 printk("%s: Bad IP packet: ip version %d\n", dev->name, iph->version);
 175                 dev_kfree_skb(skb, FREE_WRITE);
 176                 dev->tbusy = 0;
 177                 return(0);
 178         }
 179 
 180 
 181         /* 
 182          *      Check for routing loops 
 183          */
 184          
 185         if ( iph->protocol == IPPROTO_IPIP && iph->saddr == dev->pa_addr ) 
 186         {
 187                 /* 
 188                  *      We really should do an ICMP reply here... 
 189                  */
 190                 printk("%s: Warning: IP routing loop!\n", dev->name);
 191                 dev->tbusy = 0;
 192                 dev_kfree_skb(skb, FREE_WRITE);
 193                 return(0);
 194         }
 195 
 196         if ( iph->daddr == dev->pa_addr ) 
 197         {
 198                 printk("%s: Received inbound packet -- not handled.\n",dev->name);
 199                 dev_kfree_skb(skb, FREE_WRITE);
 200                 dev->tbusy = 0;
 201                 return(0);
 202         }
 203 
 204 #ifdef TUNNEL_DEBUG
 205 printk("Old IP Header....\n");
 206 print_ip(iph);
 207 #endif
 208         /*
 209          * Everything is okay: 
 210          *              See if we need to allocate memory for a new packet 
 211          */
 212 
 213         newlen = (skb->len + ip_header_len);
 214         if ( !(skb2 = dev_alloc_skb(newlen)) ) 
 215         {
 216                 printk("%s: No free memory.\n",dev->name);
 217                 dev_kfree_skb(skb, FREE_WRITE);
 218                 dev->tbusy = 0;
 219                 stats->tx_dropped++;
 220                 return(1);
 221         }
 222 
 223         /* Copy the packet to a new buffer, adding a new ip header */
 224         skb2->free=1;
 225         skb_put(skb2,newlen);
 226         iph=skb2->h.iph=(struct iphdr *)skb2->data;
 227         skb2->ip_hdr=iph;
 228         memcpy(skb2->h.iph, skb->data, ip_header_len );
 229         memcpy(skb2->data + ip_header_len, skb->data, skb->len);
 230         /* Free the old packet, we no longer need it */
 231         dev_kfree_skb(skb, FREE_WRITE);
 232 
 233         /* Correct the fields in the new ip header */
 234         ++iph->ttl;     /* Note: ip_forward() decrements ttl, so compensate */
 235         iph->saddr = dev->pa_addr;
 236         iph->daddr = dev->pa_dstaddr;
 237         iph->protocol = IPPROTO_IPIP;
 238         iph->ihl = 5;
 239         iph->tot_len = htons(skb2->len);
 240         iph->frag_off = 0;
 241 
 242         /* Here is where we compute the IP checksum */
 243         /* ip_fast_csum() is an inline function from net/inet/ip.h/checksum.h */
 244         iph->check = 0;
 245         iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 246 
 247 #ifdef TUNNEL_DEBUG
 248 printk("New IP Header....\n");
 249 print_ip(iph);
 250 #endif
 251         /* Now send the packet on its way */
 252 #ifdef TUNNEL_DEBUG
 253         printk("tunnel: calling ip_forward()\n");
 254 #endif
 255         if(ip_forward(skb2, dev, 0, iph->daddr))
 256                 kfree_skb(skb2, FREE_WRITE);
 257 
 258  
 259 #ifdef TUNNEL_DEBUG
 260         printk("Packet sent through tunnel interface!\n");
 261 #endif
 262         /* Record statistics */
 263         stats->tx_packets++;
 264 
 265 #ifdef TUNNEL_DEBUG
 266         printk("tunnel: Updated usage statistics.\n");
 267 #endif
 268         dev->tbusy=0;
 269         return 0;
 270 }
 271 
 272 static struct enet_statistics *
 273 tunnel_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 274 {
 275         return((struct enet_statistics*) dev->priv);
 276 }
 277 
 278 #ifdef MODULE
 279 char kernel_version[] = UTS_RELEASE;
 280 
 281 static int tunnel_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 282 {
 283         tunnel_init(dev);
 284         return 0;
 285 }
 286 
 287 static struct device dev_tunnel = {
 288         "tunl0\0   ", 
 289                 0, 0, 0, 0,
 290                 0x0, 0,
 291                 0, 0, 0, NULL, tunnel_probe };
 292 
 293 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 294 {
 295         /* Find a name for this unit */
 296         int ct= 1;
 297         
 298         while(dev_get(dev_tunnel.name)!=NULL && ct<100)
 299         {
 300                 sprintf(dev_tunnel.name,"tunl%d",ct);
 301                 ct++;
 302         }
 303         
 304 #ifdef TUNNEL_DEBUG
 305         printk("tunnel: registering device %s\n", dev_tunnel.name);
 306 #endif
 307         if (register_netdev(&dev_tunnel) != 0)
 308                 return -EIO;
 309         return 0;
 310 }
 311 
 312 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 313 {
 314         unregister_netdev(&dev_tunnel);
 315         kfree_s(dev_tunnel.priv,sizeof(struct enet_statistics));
 316         dev_tunnel.priv=NULL;
 317 }
 318 #endif /* MODULE */
 319 #endif

/* [previous][next][first][last][top][bottom][index][help] */