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

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