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

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