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

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