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

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