This source file includes following definitions.
- tunnel_open
- tunnel_close
- tunnel_init
- print_ip
- tunnel_xmit
- tunnel_get_stats
- tunnel_probe
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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>
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)
47 {
48 MOD_INC_USE_COUNT;
49 return 0;
50 }
51
52 static int tunnel_close(struct device *dev)
53 {
54 MOD_DEC_USE_COUNT;
55 return 0;
56 }
57
58 #endif
59
60
61 int tunnel_init(struct device *dev)
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
71 ether_setup(dev);
72
73
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
85 dev->type = ARPHRD_TUNNEL;
86 dev->flags |= IFF_NOARP;
87 dev->flags |= IFF_LOOPBACK;
88 dev->addr_len=0;
89 dev->tx_queue_len=2;
90 dev->hard_header_len=0;
91 dev->hard_header=NULL;
92 dev->header_cache_bind=NULL;
93 dev->rebuild_header=NULL;
94
95 return 0;
96 }
97
98 #ifdef TUNNEL_DEBUG
99 void print_ip(struct iphdr *ip)
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
118
119
120
121
122
123 static int tunnel_xmit(struct sk_buff *skb, struct device *dev)
124 {
125 struct enet_statistics *stats;
126 struct sk_buff *skb2;
127 int newlen;
128 struct iphdr *iph;
129
130
131
132
133
134 if (skb == NULL || dev == NULL)
135 return 0;
136
137
138
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
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
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
179
180
181 if ( iph->protocol == IPPROTO_IPIP && iph->saddr == dev->pa_addr )
182 {
183
184
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
206
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
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
227 dev_kfree_skb(skb, FREE_WRITE);
228
229
230 ++iph->ttl;
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
239
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
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
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)
270 {
271 return((struct enet_statistics*) dev->priv);
272 }
273
274 #ifdef MODULE
275
276 static int tunnel_probe(struct device *dev)
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)
289 {
290
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)
308 {
309 unregister_netdev(&dev_tunnel);
310 kfree_s(dev_tunnel.priv,sizeof(struct enet_statistics));
311 dev_tunnel.priv=NULL;
312 }
313 #endif