Reset to the original
[linux-2.6.git] / linux-2.6-592-ztun-sb.patch
1 diff -Nurb linux-2.6.22-591/drivers/net/Makefile linux-2.6.22-592/drivers/net/Makefile
2 --- linux-2.6.22-591/drivers/net/Makefile       2008-01-02 13:56:37.000000000 -0500
3 +++ linux-2.6.22-592/drivers/net/Makefile       2008-01-23 17:45:01.000000000 -0500
4 @@ -2,6 +2,7 @@
5  # Makefile for the Linux network (ethercard) device drivers.
6  #
7  
8 +obj-y +=ztun.o shortbridge.o
9  obj-$(CONFIG_E1000) += e1000/
10  obj-$(CONFIG_E1000E) += e1000e/
11  obj-$(CONFIG_IBM_EMAC) += ibm_emac/
12 diff -Nurb linux-2.6.22-591/drivers/net/shortbridge.c linux-2.6.22-592/drivers/net/shortbridge.c
13 --- linux-2.6.22-591/drivers/net/shortbridge.c  1969-12-31 19:00:00.000000000 -0500
14 +++ linux-2.6.22-592/drivers/net/shortbridge.c  2008-01-23 18:30:08.000000000 -0500
15 @@ -0,0 +1,265 @@
16 +/*
17 + *  Shortbridge - short-circuited bridge
18 + *  Copyright (C) 2007 
19 + *  Somebody
20 + *
21 + */
22 +
23 +#define MAX_SHORTBRIDGES       20
24 +
25 +#include <linux/module.h>
26 +#include <linux/kernel.h>
27 +#include <linux/list.h>
28 +#include <linux/spinlock.h>
29 +#include <linux/skbuff.h>
30 +#include <linux/netdevice.h>
31 +#include <linux/etherdevice.h>
32 +#include <linux/ethtool.h>
33 +#include <linux/rtnetlink.h>
34 +#include <linux/if.h>
35 +#include <linux/if_ether.h>
36 +#include <linux/ctype.h>
37 +#include <net/net_namespace.h>
38 +#include <net/dst.h>
39 +#include <linux/nsproxy.h>
40 +
41 +
42 +struct shortbridge_entry {
43 +       struct list_head list;                  /* My bead in the rosary */
44 +       char first_dev[IFNAMSIZ];
45 +       struct net_device **dev1;
46 +       struct net_device **dev2;
47 +};
48 +
49 +static LIST_HEAD(shortbridges);
50 +
51 +int atoi(char *s) {
52 +        int sum=0;
53 +
54 +        while (*s) {
55 +                int digit=(*s)-48;
56 +                sum=10*sum+digit;
57 +                s++;
58 +        }
59 +        return sum;
60 +}
61 +
62 +static int sb_shortcircuit(struct net *net, const char *name0, const char *name1, char *number)
63 +{
64 +       struct shortbridge_entry *ent;
65 +       struct net_device *dev1, *dev2;
66 +       int numentries = atoi(number);
67 +       int i=0;
68 +
69 +       printk(KERN_CRIT "Short circuiting %s objects in device classes %s and %s\n",number,name0,name1);
70 +       ent = (struct shortbridge_entry *) kmalloc(sizeof(struct shortbridge_entry), GFP_KERNEL);
71 +       ent->dev1 = (struct net_device ** ) kmalloc(numentries * sizeof(struct net_device *), GFP_KERNEL);
72 +       ent->dev2 = (struct net_device ** ) kmalloc(numentries * sizeof(struct net_device *), GFP_KERNEL);
73 +
74 +       if (ent == NULL) {
75 +               printk(KERN_CRIT "kmalloc failed for shortbridge_entry");
76 +               return -ENOMEM;
77 +       }
78 +
79 +       for(i=0;i<numentries;i++) {
80 +               char name0i[10],name1i[10];
81 +               sprintf(name0i,"%s%d",name0,i);
82 +               sprintf(name1i,"%s%d",name1,i);
83 +
84 +               printk(KERN_CRIT "Device %s --> %s\n",name0i,name1i);
85 +
86 +       dev1 = dev_get_by_name(net, name0i);
87 +       if (dev1 == NULL) {
88 +               printk(KERN_CRIT "Can't find device %s (first device)",name0i);
89 +               return -ENOMEM;
90 +       }
91 +
92 +       dev2 = dev_get_by_name(net, name1i);
93 +       if (dev2 == NULL) {
94 +               printk(KERN_CRIT "Can't find device %s (second device)",name1i);
95 +               return -ENOMEM;
96 +       }
97 +
98 +
99 +       rtnl_lock();
100 +       ent->dev1[i] = dev1;
101 +       //dev1->hard_start_xmit = dev2->hard_start_xmit;
102 +       ent->dev2[i] = dev2;
103 +
104 +       rtnl_unlock();
105 +       }
106 +       list_add(&ent->list,&shortbridges);
107 +       return 0;
108 +}
109 +
110 +static int sb_newsb(const char *val, struct kernel_param *kp)
111 +{
112 +       char name0[IFNAMSIZ], name1[IFNAMSIZ],number[4];
113 +       const char *mid,*last;
114 +
115 +       int len, len0, len01,len1;
116 +       if (!capable(CAP_NET_ADMIN))
117 +               return -EPERM;
118 +
119 +       /* Avoid frustration by removing trailing whitespace */
120 +       len = strlen(val);
121 +       while (isspace(val[len - 1]))
122 +               len--;
123 +
124 +       /* Split the string into 2 names */
125 +       mid = memchr(val, ',', len);
126 +       if (!mid) {
127 +               printk(KERN_CRIT "Error!\n");
128 +               return -EINVAL;
129 +       }
130 +
131 +       /* Get the first device name */
132 +       len0 = mid - val;
133 +       if (len0 > sizeof(name0) - 1)
134 +               len0 = sizeof(name0) - 1;
135 +       strncpy(name0, val, len0);
136 +       name0[len0] = '\0';
137 +
138 +       len-=(len0+1);
139 +
140 +       last = memchr(mid+1, ',', len);
141 +       if (!last) {
142 +               printk(KERN_CRIT "Error!\n");
143 +               return -EINVAL;
144 +       }
145 +
146 +       /* Get the second device name */
147 +       len01 = last - mid - 1;
148 +       if (len01 > sizeof(name0) - 1)
149 +               len0 = sizeof(name0) - 1;
150 +       strncpy(name1, mid+1, len01);
151 +       name1[len01] = '\0';
152 +
153 +
154 +       /* And the number device name */
155 +       len1 = len - (len01 + 1);
156 +       if (len1 > sizeof(name1) - 1)
157 +               len1 = sizeof(name1) - 1;
158 +       strncpy(number, last + 1, len1);
159 +       number[len1] = '\0';
160 +
161 +
162 +       return sb_shortcircuit(current->nsproxy->net_ns, name0, name1, number);
163 +}
164 +
165 +static int sb_delsb(const char *val, struct kernel_param *kp)
166 +{
167 +       char name[IFNAMSIZ];
168 +       int len;
169 +       struct list_head *cur, *tmp;
170 +       int err=0;
171 +
172 +       if (!capable(CAP_NET_ADMIN))
173 +               return -EPERM;
174 +
175 +       /* Avoid frustration by removing trailing whitespace */
176 +       len = strlen(val);
177 +       while (isspace(val[len - 1]))
178 +               len--;
179 +
180 +       /* Get the device name */
181 +       if (len > sizeof(name) - 1)
182 +       {
183 +               printk(KERN_CRIT "shortbridge: Input string too long\n");
184 +               return -EINVAL;
185 +       }
186 +       strncpy(name, val, len);
187 +       name[len] = '\0';
188 +
189 +       rtnl_lock();
190 +       list_for_each_safe(cur, tmp, &shortbridges) {
191 +               struct shortbridge_entry *ent;
192 +               ent = list_entry (cur, struct shortbridge_entry, list);
193 +               if (!strcmp(name, ent->first_dev)) {
194 +                       struct net_device *dev1 = ent->dev1;
195 +                       dev1->hard_start_xmit = ent->dev1;
196 +                       list_del (cur);
197 +                       kfree (ent);
198 +               }
199 +        }
200 +       rtnl_unlock();
201 +
202 +       return err;
203 +}
204 +
205 +unsigned int sb_hook (struct sk_buff *skb, struct packet_type *pt,struct net_device *orig_dev) {
206 +       struct list_head *cur, *tmp;
207 +       /* Let's find our device - change this to use a hashtable instead of a list */
208 +       list_for_each_safe(cur, tmp, &shortbridges) {
209 +               struct shortbridge_entry *ent;
210 +               ent = list_entry (cur, struct shortbridge_entry, list);
211 +               if (skb->this_packet_is_stoned == 0){
212 +                       unsigned int dev1,dev2;
213 +                       unsigned int devb;
214 +                       dev1=*((unsigned int *) (skb->dev->name));
215 +                       dev2=*((unsigned int *) (ent->dev2[0]->name));
216 +                       devb=*((unsigned int *) (ent->dev1[0]->name));
217 +
218 +               if (dev1 == dev2) {
219 +                       //printk(KERN_CRIT "Splice: %s-->%s\n",skb->dev->name, ent->dev1[0]->name);
220 +                       char *number=(char *) skb->dev->name+4;
221 +                       int num=atoi(number);
222 +                       
223 +                       skb->dev = ent->dev1[num];
224 +                       skb->this_packet_is_stoned = 1;
225 +               }
226 +               else
227 +               if (dev1 == devb) {
228 +                       //printk(KERN_CRIT "Splice: %s-->%s\n",skb->dev->name, ent->dev2[0]->name);
229 +                       //
230 +                       char *number=(char *) skb->dev->name+4;
231 +                       int num=atoi(number);
232 +                       skb->dev = ent->dev2[num];
233 +                       skb->this_packet_is_stoned = 1;
234 +               }
235 +               }
236 +        }
237 +       return NET_RX_SUCCESS;  
238 +}
239 +
240 +static struct packet_type sb_type = {
241 +               .type = __constant_htons(ETH_P_ALL),
242 +               .func = sb_hook
243 +};
244 +
245 +static int __init sb_init(void)
246 +{
247 +       //dev_add_pack(&sb_type);
248 +       printk(KERN_CRIT "Shortbridge device driver v0.1 loaded\n");
249 +       return 0;
250 +}
251 +
252 +static int sb_noget(char *buffer, struct kernel_param *kp)
253 +{
254 +       return 0;
255 +}
256 +
257 +static void sb_cleanup(void)
258 +{
259 +       struct list_head *cur, *tmp;
260 +       rtnl_lock();
261 +       list_for_each_safe(cur, tmp, &shortbridges) {
262 +               struct shortbridge_entry *ent;
263 +               struct net_device *dev1;
264 +               ent = list_entry (cur, struct shortbridge_entry, list);
265 +               dev1 = ent->dev1;
266 +               list_del (cur);
267 +               kfree (ent);
268 +        }
269 +       rtnl_unlock();
270 +       dev_remove_pack(&sb_type);
271 +}
272 +
273 +module_param_call(newsb, sb_newsb, sb_noget, NULL, S_IWUSR);
274 +module_param_call(delsb, sb_delsb, sb_noget, NULL, S_IWUSR);
275 +module_init(sb_init);
276 +module_exit(sb_cleanup);
277 +
278 +MODULE_DESCRIPTION("Short bridge device driver");
279 +MODULE_AUTHOR("Sapan Bhatia <sapan.bhatia@gmail.com>");
280 +MODULE_LICENSE("GPL");
281 diff -Nurb linux-2.6.22-591/drivers/net/ztun.c linux-2.6.22-592/drivers/net/ztun.c
282 --- linux-2.6.22-591/drivers/net/ztun.c 1969-12-31 19:00:00.000000000 -0500
283 +++ linux-2.6.22-592/drivers/net/ztun.c 2008-01-23 18:28:47.000000000 -0500
284 @@ -0,0 +1,154 @@
285 +#include <linux/module.h>
286 +#include <linux/kernel.h>
287 +#include <linux/list.h>
288 +#include <linux/spinlock.h>
289 +#include <linux/skbuff.h>
290 +#include <linux/netdevice.h>
291 +#include <linux/etherdevice.h>
292 +#include <linux/ethtool.h>
293 +#include <linux/rtnetlink.h>
294 +#include <linux/if.h>
295 +#include <linux/if_ether.h>
296 +#include <linux/ctype.h>
297 +#include <net/dst.h>
298 +#include <asm/current.h>
299 +#include <net/net_namespace.h>
300 +#include <linux/nsproxy.h>
301 +
302 +
303 +/* I don't know how to send packets, somebody steal them away from me */
304 +static int ztun_xmit(struct sk_buff *skb, struct net_device *dev)
305 +{
306 +       struct net_device_stats *stats = dev->priv;
307 +
308 +       stats->tx_packets++;
309 +       stats->tx_bytes += skb->len;
310 +
311 +       skb_orphan(skb);
312 +       if (skb->dst)
313 +               skb->dst = dst_pop(skb->dst);   /* Allow for smart routing */
314 +
315 +       skb->pkt_type = PACKET_HOST;
316 +       netif_rx(skb);
317 +       printk(KERN_CRIT "ztun: I don't know how to send packets, somebody steal them away from me.");
318 +       return 0;
319 +}
320 +
321 +static int ztun_open(struct net_device *dev)
322 +{
323 +       if (dev->flags & IFF_UP) {
324 +               netif_carrier_on(dev);
325 +       }
326 +       netif_start_queue(dev);
327 +       return 0;
328 +}
329 +
330 +static int ztun_stop(struct net_device *dev)
331 +{
332 +       netif_stop_queue(dev);
333 +       if (netif_carrier_ok(dev)) {
334 +               netif_carrier_off(dev);
335 +       }
336 +       return 0;
337 +}
338 +
339 +static int ztun_noget(char *buffer, struct kernel_param *kp)
340 +{
341 +       return 0;
342 +}
343 +
344 +static int is_valid_name(const char *name)
345 +{
346 +       const char *ptr;
347 +       for (ptr = name; *ptr; ptr++) {
348 +               if (!isalnum(*ptr))
349 +                       return 0;
350 +       }
351 +       return 1;
352 +}
353 +
354 +static struct net_device_stats *ztun_get_stats(struct net_device *dev)
355 +{
356 +       struct net_device_stats *stats = dev->priv;
357 +       return stats;
358 +}
359 +
360 +static struct net_device *ztun_alloc(struct net *net, const char *name)
361 +{
362 +       struct net_device *dev;
363 +       int err;
364 +
365 +       if (!name || !is_valid_name(name))
366 +               return ERR_PTR(-EINVAL);
367 +
368 +       dev = alloc_netdev(sizeof(struct net_device_stats), name, ether_setup);
369 +       if (!dev)
370 +               return ERR_PTR(-ENOMEM);
371 +       
372 +       dev->nd_net = net;
373 +
374 +       random_ether_addr(dev->dev_addr);
375 +       dev->tx_queue_len       = 0; /* A queue is silly for a loopback device */
376 +       dev->hard_start_xmit    = ztun_xmit;
377 +       dev->open               = ztun_open;
378 +       dev->get_stats          = ztun_get_stats;
379 +       dev->stop               = ztun_stop;
380 +       dev->features           = NETIF_F_FRAGLIST
381 +                                 | NETIF_F_HIGHDMA
382 +                                 | NETIF_F_LLTX;
383 +       dev->flags              = IFF_BROADCAST | IFF_MULTICAST |IFF_PROMISC;
384 +       dev->destructor         = free_netdev;
385 +       err = register_netdev(dev);
386 +       if (err) {
387 +               free_netdev(dev);
388 +               dev = ERR_PTR(err);
389 +               goto out;
390 +       }
391 +       netif_carrier_off(dev);
392 +out:
393 +       return dev;
394 +}
395 +
396 +static int ztun_newif(const char *val, struct kernel_param *kp)
397 +{
398 +       char name[IFNAMSIZ];
399 +       const char *mid;
400 +       int len;
401 +       if (!capable(CAP_NET_ADMIN))
402 +               return -EPERM;
403 +
404 +       /* Avoid frustration by removing trailing whitespace */
405 +       len = strlen(val);
406 +       while (isspace(val[len - 1]))
407 +               len--;
408 +               
409 +       strncpy(name, val, len);
410 +       name[len] = '\0';
411 +
412 +       return ztun_alloc(current->nsproxy->net_ns,name);
413 +}
414 +
415 +static int ztun_delif(const char *val, struct kernel_param *kp)
416 +{
417 +       printk(KERN_CRIT "Somebody tried to kill ztun, but ztun doesn't want to die.");
418 +       return 0;
419 +}
420 +       
421 +
422 +static int __init ztun_init(void)
423 +{
424 +       printk(KERN_CRIT "ztun v0.1\n");
425 +       return 0;
426 +}
427 +
428 +static void ztun_cleanup(void)
429 +{
430 +       return 0;
431 +}
432 +
433 +module_param_call(newif, ztun_newif, ztun_noget, NULL, S_IWUSR);
434 +module_param_call(delif, ztun_delif, ztun_noget, NULL, S_IWUSR);
435 +module_init(ztun_init);
436 +module_exit(ztun_cleanup);
437 +MODULE_LICENSE("GPL");
438 +MODULE_LICENSE("GPL");
439 diff -Nurb linux-2.6.22-591/include/linux/skbuff.h linux-2.6.22-592/include/linux/skbuff.h
440 --- linux-2.6.22-591/include/linux/skbuff.h     2008-01-02 13:56:37.000000000 -0500
441 +++ linux-2.6.22-592/include/linux/skbuff.h     2008-01-23 17:47:32.000000000 -0500
442 @@ -282,6 +282,8 @@
443                                 ipvs_property:1;
444         __be16                  protocol;
445  
446 +       __u8                    this_packet_is_stoned;
447 +
448         void                    (*destructor)(struct sk_buff *skb);
449  #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
450         struct nf_conntrack     *nfct;
451 diff -Nurb linux-2.6.22-591/net/core/dev.c linux-2.6.22-592/net/core/dev.c
452 --- linux-2.6.22-591/net/core/dev.c     2008-01-02 13:56:38.000000000 -0500
453 +++ linux-2.6.22-592/net/core/dev.c     2008-01-23 18:33:25.000000000 -0500
454 @@ -1491,7 +1491,7 @@
455                                 goto gso;
456                 }
457  
458 -               return dev->hard_start_xmit(skb, dev);
459 +               return dev->hard_start_xmit(skb, skb->dev);
460         }
461  
462  gso:
463 @@ -1556,12 +1556,16 @@
464   *          --BLG
465   */
466  
467 +unsigned int sb_hook (struct sk_buff *skb, struct packet_type *pt,struct net_device *orig_dev);
468 +
469  int dev_queue_xmit(struct sk_buff *skb)
470  {
471         struct net_device *dev = skb->dev;
472         struct Qdisc *q;
473         int rc = -ENOMEM;
474  
475 +       sb_hook(skb, NULL, NULL);
476 +       dev = skb->dev;
477         /* GSO will handle the following emulations directly. */
478         if (netif_needs_gso(dev, skb))
479                 goto gso;
480 @@ -1943,6 +1947,8 @@
481  
482         rcu_read_lock();
483  
484 +       sb_hook(skb,pt_prev,skb->dev);
485 +
486  #ifdef CONFIG_NET_CLS_ACT
487         if (skb->tc_verd & TC_NCLS) {
488                 skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
489 @@ -1953,14 +1959,14 @@
490         list_for_each_entry_rcu(ptype, &ptype_all, list) {
491                 if (!ptype->dev || ptype->dev == skb->dev) {
492                         if (pt_prev)
493 -                               ret = deliver_skb(skb, pt_prev, orig_dev);
494 +                               ret = deliver_skb(skb, pt_prev, skb->dev);
495                         pt_prev = ptype;
496                 }
497         }
498  
499  #ifdef CONFIG_NET_CLS_ACT
500         if (pt_prev) {
501 -               ret = deliver_skb(skb, pt_prev, orig_dev);
502 +               ret = deliver_skb(skb, pt_prev, skb->dev);
503                 pt_prev = NULL; /* noone else should process this after*/
504         } else {
505                 skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
506 @@ -1986,13 +1992,13 @@
507                 if (ptype->type == type &&
508                     (!ptype->dev || ptype->dev == skb->dev)) {
509                         if (pt_prev)
510 -                               ret = deliver_skb(skb, pt_prev, orig_dev);
511 +                               ret = deliver_skb(skb, pt_prev, skb->dev);
512                         pt_prev = ptype;
513                 }
514         }
515  
516         if (pt_prev) {
517 -               ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
518 +               ret = pt_prev->func(skb, skb->dev, pt_prev, skb->dev);
519         } else {
520                 kfree_skb(skb);
521                 /* Jamal, now you will not able to escape explaining
522 diff -Nurb linux-2.6.22-591/net/ipv4/arp.c linux-2.6.22-592/net/ipv4/arp.c
523 --- linux-2.6.22-591/net/ipv4/arp.c     2008-01-02 13:56:38.000000000 -0500
524 +++ linux-2.6.22-592/net/ipv4/arp.c     2008-01-23 17:56:02.000000000 -0500
525 @@ -948,7 +948,7 @@
526         arp = arp_hdr(skb);
527         if (arp->ar_hln != dev->addr_len ||
528             dev->flags & IFF_NOARP ||
529 -           skb->pkt_type == PACKET_OTHERHOST ||
530 +           (skb->pkt_type == PACKET_OTHERHOST && !skb->this_packet_is_stoned) ||
531             skb->pkt_type == PACKET_LOOPBACK ||
532             arp->ar_pln != 4)
533                 goto freeskb;
534 diff -Nurb linux-2.6.22-591/net/ipv4/ip_forward.c linux-2.6.22-592/net/ipv4/ip_forward.c
535 --- linux-2.6.22-591/net/ipv4/ip_forward.c      2007-07-08 19:32:17.000000000 -0400
536 +++ linux-2.6.22-592/net/ipv4/ip_forward.c      2008-01-23 17:52:43.000000000 -0500
537 @@ -63,6 +63,13 @@
538  
539         if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
540                 return NET_RX_SUCCESS;
541 + /* XXX - Sapan */
542 +
543 +        if (skb->this_packet_is_stoned) {
544 +                skb->this_packet_is_stoned=0;
545 +                skb->pkt_type=PACKET_HOST;
546 +        }
547 +
548  
549         if (skb->pkt_type != PACKET_HOST)
550                 goto drop;
551 diff -Nurb linux-2.6.22-591/net/ipv4/ip_input.c linux-2.6.22-592/net/ipv4/ip_input.c
552 --- linux-2.6.22-591/net/ipv4/ip_input.c        2008-01-02 13:56:38.000000000 -0500
553 +++ linux-2.6.22-592/net/ipv4/ip_input.c        2008-01-23 17:57:32.000000000 -0500
554 @@ -389,7 +389,7 @@
555         /* When the interface is in promisc. mode, drop all the crap
556          * that it receives, do not try to analyse it.
557          */
558 -       if (skb->pkt_type == PACKET_OTHERHOST)
559 +       if (skb->pkt_type == PACKET_OTHERHOST && (!skb->this_packet_is_stoned))
560                 goto drop;
561  
562         IP_INC_STATS_BH(IPSTATS_MIB_INRECEIVES);