remove the old broadcom wl driver for linux 2.4
[openwrt.git] / target / linux / generic-2.4 / patches / 611-netfilter_condition.patch
1 --- a/Documentation/Configure.help
2 +++ b/Documentation/Configure.help
3 @@ -2979,6 +2979,14 @@ CONFIG_IP_NF_MATCH_TOS
4    If you want to compile it as a module, say M here and read
5    <file:Documentation/modules.txt>.  If unsure, say `N'.
6  
7 +Condition variable match support
8 +CONFIG_IP_NF_MATCH_CONDITION
9 +  This option allows you to match firewall rules against condition
10 +  variables stored in the /proc/net/ipt_condition directory.
11 +
12 +  If you want to compile it as a module, say M here and read
13 +  Documentation/modules.txt.  If unsure, say `N'.
14 +
15  conntrack match support
16  CONFIG_IP_NF_MATCH_CONNTRACK
17    This is a general conntrack match module, a superset of the state match.
18 @@ -3296,6 +3304,14 @@ CONFIG_IP6_NF_MATCH_MARK
19    If you want to compile it as a module, say M here and read
20    <file:Documentation/modules.txt>.  If unsure, say `N'.
21  
22 +Condition variable match support
23 +CONFIG_IP6_NF_MATCH_CONDITION
24 +  This option allows you to match firewall rules against condition
25 +  variables stored in the /proc/net/ipt_condition directory.
26 +
27 +  If you want to compile it as a module, say M here and read
28 +  Documentation/modules.txt.  If unsure, say `N'.
29 +
30  Multiple port match support
31  CONFIG_IP6_NF_MATCH_MULTIPORT
32    Multiport matching allows you to match TCP or UDP packets based on
33 --- /dev/null
34 +++ b/include/linux/netfilter_ipv4/ipt_condition.h
35 @@ -0,0 +1,11 @@
36 +#ifndef __IPT_CONDITION_MATCH__
37 +#define __IPT_CONDITION_MATCH__
38 +
39 +#define CONDITION_NAME_LEN  32
40 +
41 +struct condition_info {
42 +       char name[CONDITION_NAME_LEN];
43 +       int  invert;
44 +};
45 +
46 +#endif
47 --- /dev/null
48 +++ b/include/linux/netfilter_ipv6/ip6t_condition.h
49 @@ -0,0 +1,11 @@
50 +#ifndef __IP6T_CONDITION_MATCH__
51 +#define __IP6T_CONDITION_MATCH__
52 +
53 +#define CONDITION6_NAME_LEN  32
54 +
55 +struct condition6_info {
56 +       char name[CONDITION6_NAME_LEN];
57 +       int  invert;
58 +};
59 +
60 +#endif
61 --- a/net/ipv4/netfilter/Config.in
62 +++ b/net/ipv4/netfilter/Config.in
63 @@ -27,6 +27,7 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; 
64    dep_tristate '  netfilter MARK match support' CONFIG_IP_NF_MATCH_MARK $CONFIG_IP_NF_IPTABLES
65    dep_tristate '  Multiple port match support' CONFIG_IP_NF_MATCH_MULTIPORT $CONFIG_IP_NF_IPTABLES
66    dep_tristate '  TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
67 +  dep_tristate '  condition match support' CONFIG_IP_NF_MATCH_CONDITION $CONFIG_IP_NF_IPTABLES
68    dep_tristate '  recent match support' CONFIG_IP_NF_MATCH_RECENT $CONFIG_IP_NF_IPTABLES
69    dep_tristate '  ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES
70    dep_tristate '  peer to peer traffic match support' CONFIG_IP_NF_MATCH_IPP2P $CONFIG_IP_NF_IPTABLES
71 --- a/net/ipv4/netfilter/Makefile
72 +++ b/net/ipv4/netfilter/Makefile
73 @@ -73,6 +73,7 @@ obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt
74  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
75  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
76  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
77 +obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
78  
79  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
80  
81 --- /dev/null
82 +++ b/net/ipv4/netfilter/ipt_condition.c
83 @@ -0,0 +1,256 @@
84 +/*-------------------------------------------*\
85 +|          Netfilter Condition Module         |
86 +|                                             |
87 +|  Description: This module allows firewall   |
88 +|    rules to match using condition variables |
89 +|    stored in /proc files.                   |
90 +|                                             |
91 +|  Author: Stephane Ouellette     2002-10-22  |
92 +|          <ouellettes@videotron.ca>          |
93 +|                                             |
94 +|  History:                                   |
95 +|    2003-02-10  Second version with improved |
96 +|                locking and simplified code. |
97 +|                                             |
98 +|  This software is distributed under the     |
99 +|  terms of the GNU GPL.                      |
100 +\*-------------------------------------------*/
101 +
102 +#include<linux/module.h>
103 +#include<linux/proc_fs.h>
104 +#include<linux/spinlock.h>
105 +#include<linux/string.h>
106 +#include<asm/atomic.h>
107 +#include<linux/netfilter_ipv4/ip_tables.h>
108 +#include<linux/netfilter_ipv4/ipt_condition.h>
109 +
110 +
111 +#ifndef CONFIG_PROC_FS
112 +#error  "Proc file system support is required for this module"
113 +#endif
114 +
115 +
116 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
117 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
118 +MODULE_LICENSE("GPL");
119 +
120 +
121 +struct condition_variable {
122 +       struct condition_variable *next;
123 +       struct proc_dir_entry *status_proc;
124 +       atomic_t refcount;
125 +        int enabled;   /* TRUE == 1, FALSE == 0 */
126 +};
127 +
128 +
129 +static rwlock_t list_lock;
130 +static struct condition_variable *head = NULL;
131 +static struct proc_dir_entry *proc_net_condition = NULL;
132 +
133 +
134 +static int
135 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
136 +                       int length, int *eof, void *data)
137 +{
138 +       struct condition_variable *var =
139 +           (struct condition_variable *) data;
140 +
141 +       if (offset == 0) {
142 +               *start = buffer;
143 +               buffer[0] = (var->enabled) ? '1' : '0';
144 +               buffer[1] = '\n';
145 +               return 2;
146 +       }
147 +
148 +       *eof = 1;
149 +       return 0;
150 +}
151 +
152 +
153 +static int
154 +ipt_condition_write_info(struct file *file, const char *buffer,
155 +                        unsigned long length, void *data)
156 +{
157 +       struct condition_variable *var =
158 +           (struct condition_variable *) data;
159 +
160 +       if (length) {
161 +               /* Match only on the first character */
162 +               switch (buffer[0]) {
163 +               case '0':
164 +                       var->enabled = 0;
165 +                       break;
166 +               case '1':
167 +                       var->enabled = 1;
168 +               }
169 +       }
170 +
171 +       return (int) length;
172 +}
173 +
174 +
175 +static int
176 +match(const struct sk_buff *skb, const struct net_device *in,
177 +      const struct net_device *out, const void *matchinfo, int offset,
178 +      const void *hdr, u_int16_t datalen, int *hotdrop)
179 +{
180 +       const struct condition_info *info =
181 +           (const struct condition_info *) matchinfo;
182 +       struct condition_variable *var;
183 +       int condition_status = 0;
184 +
185 +       read_lock(&list_lock);
186 +
187 +       for (var = head; var; var = var->next) {
188 +               if (strcmp(info->name, var->status_proc->name) == 0) {
189 +                       condition_status = var->enabled;
190 +                       break;
191 +               }
192 +       }
193 +
194 +       read_unlock(&list_lock);
195 +
196 +       return condition_status ^ info->invert;
197 +}
198 +
199 +
200 +
201 +static int
202 +checkentry(const char *tablename, const struct ipt_ip *ip,
203 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
204 +{
205 +       struct condition_info *info = (struct condition_info *) matchinfo;
206 +       struct condition_variable *var, *newvar;
207 +
208 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
209 +               return 0;
210 +
211 +       /* The first step is to check if the condition variable already exists. */
212 +       /* Here, a read lock is sufficient because we won't change the list */
213 +       read_lock(&list_lock);
214 +
215 +       for (var = head; var; var = var->next) {
216 +               if (strcmp(info->name, var->status_proc->name) == 0) {
217 +                       atomic_inc(&var->refcount);
218 +                       read_unlock(&list_lock);
219 +                       return 1;
220 +               }
221 +       }
222 +
223 +       read_unlock(&list_lock);
224 +
225 +       /* At this point, we need to allocate a new condition variable */
226 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
227 +
228 +       if (!newvar)
229 +               return -ENOMEM;
230 +
231 +       /* Create the condition variable's proc file entry */
232 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
233 +
234 +       if (!newvar->status_proc) {
235 +         /*
236 +          * There are two possibilities:
237 +          *  1- Another condition variable with the same name has been created, which is valid.
238 +          *  2- There was a memory allocation error.
239 +          */
240 +               kfree(newvar);
241 +               read_lock(&list_lock);
242 +
243 +               for (var = head; var; var = var->next) {
244 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
245 +                               atomic_inc(&var->refcount);
246 +                               read_unlock(&list_lock);
247 +                               return 1;
248 +                       }
249 +               }
250 +
251 +               read_unlock(&list_lock);
252 +               return -ENOMEM;
253 +       }
254 +
255 +       atomic_set(&newvar->refcount, 1);
256 +       newvar->enabled = 0;
257 +       newvar->status_proc->owner = THIS_MODULE;
258 +       newvar->status_proc->data = newvar;
259 +       wmb();
260 +       newvar->status_proc->read_proc = ipt_condition_read_info;
261 +       newvar->status_proc->write_proc = ipt_condition_write_info;
262 +
263 +       write_lock(&list_lock);
264 +
265 +       newvar->next = head;
266 +       head = newvar;
267 +
268 +       write_unlock(&list_lock);
269 +
270 +       return 1;
271 +}
272 +
273 +
274 +static void
275 +destroy(void *matchinfo, unsigned int matchsize)
276 +{
277 +       struct condition_info *info = (struct condition_info *) matchinfo;
278 +       struct condition_variable *var, *prev = NULL;
279 +
280 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
281 +               return;
282 +
283 +       write_lock(&list_lock);
284 +
285 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
286 +            prev = var, var = var->next);
287 +
288 +       if (var && atomic_dec_and_test(&var->refcount)) {
289 +               if (prev)
290 +                       prev->next = var->next;
291 +               else
292 +                       head = var->next;
293 +
294 +               write_unlock(&list_lock);
295 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
296 +               kfree(var);
297 +       } else
298 +               write_unlock(&list_lock);
299 +}
300 +
301 +
302 +static struct ipt_match condition_match = {
303 +       .name = "condition",
304 +       .match = &match,
305 +       .checkentry = &checkentry,
306 +       .destroy = &destroy,
307 +       .me = THIS_MODULE
308 +};
309 +
310 +
311 +static int __init
312 +init(void)
313 +{
314 +       int errorcode;
315 +
316 +       rwlock_init(&list_lock);
317 +       proc_net_condition = proc_mkdir("ipt_condition", proc_net);
318 +
319 +       if (proc_net_condition) {
320 +               errorcode = ipt_register_match(&condition_match);
321 +
322 +               if (errorcode)
323 +                       remove_proc_entry("ipt_condition", proc_net);
324 +       } else
325 +               errorcode = -EACCES;
326 +
327 +       return errorcode;
328 +}
329 +
330 +
331 +static void __exit
332 +fini(void)
333 +{
334 +       ipt_unregister_match(&condition_match);
335 +       remove_proc_entry("ipt_condition", proc_net);
336 +}
337 +
338 +module_init(init);
339 +module_exit(fini);
340 --- a/net/ipv6/netfilter/Config.in
341 +++ b/net/ipv6/netfilter/Config.in
342 @@ -17,6 +17,7 @@ tristate 'IP6 tables support (required f
343  if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then
344  # The simple matches.
345    dep_tristate '  limit match support' CONFIG_IP6_NF_MATCH_LIMIT $CONFIG_IP6_NF_IPTABLES
346 +  dep_tristate '  condition match support' CONFIG_IP6_NF_MATCH_CONDITION $CONFIG_IP6_NF_IPTABLES
347    dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
348    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
349      dep_tristate '  Routing header match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_RT $CONFIG_IP6_NF_IPTABLES
350 --- a/net/ipv6/netfilter/Makefile
351 +++ b/net/ipv6/netfilter/Makefile
352 @@ -14,6 +14,7 @@ export-objs := ip6_tables.o
353  # Link order matters here.
354  obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
355  obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
356 +obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
357  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
358  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
359  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
360 --- /dev/null
361 +++ b/net/ipv6/netfilter/ip6t_condition.c
362 @@ -0,0 +1,254 @@
363 +/*-------------------------------------------*\
364 +|    Netfilter Condition Module for IPv6      |
365 +|                                             |
366 +|  Description: This module allows firewall   |
367 +|    rules to match using condition variables |
368 +|    stored in /proc files.                   |
369 +|                                             |
370 +|  Author: Stephane Ouellette     2003-02-10  |
371 +|          <ouellettes@videotron.ca>          |
372 +|                                             |
373 +|  This software is distributed under the     |
374 +|  terms of the GNU GPL.                      |
375 +\*-------------------------------------------*/
376 +
377 +#include<linux/module.h>
378 +#include<linux/proc_fs.h>
379 +#include<linux/spinlock.h>
380 +#include<linux/string.h>
381 +#include<asm/atomic.h>
382 +#include<linux/netfilter_ipv6/ip6_tables.h>
383 +#include<linux/netfilter_ipv6/ip6t_condition.h>
384 +
385 +
386 +#ifndef CONFIG_PROC_FS
387 +#error  "Proc file system support is required for this module"
388 +#endif
389 +
390 +
391 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
392 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
393 +MODULE_LICENSE("GPL");
394 +
395 +
396 +struct condition_variable {
397 +       struct condition_variable *next;
398 +       struct proc_dir_entry *status_proc;
399 +       atomic_t refcount;
400 +        int enabled; /* TRUE == 1, FALSE == 0 */
401 +};
402 +
403 +
404 +static rwlock_t list_lock;
405 +static struct condition_variable *head = NULL;
406 +static struct proc_dir_entry *proc_net_condition = NULL;
407 +
408 +
409 +static int
410 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
411 +                       int length, int *eof, void *data)
412 +{
413 +       struct condition_variable *var =
414 +           (struct condition_variable *) data;
415 +
416 +       if (offset == 0) {
417 +               *start = buffer;
418 +               buffer[0] = (var->enabled) ? '1' : '0';
419 +               buffer[1] = '\n';
420 +               return 2;
421 +       }
422 +
423 +       *eof = 1;
424 +       return 0;
425 +}
426 +
427 +
428 +static int
429 +ipt_condition_write_info(struct file *file, const char *buffer,
430 +                        unsigned long length, void *data)
431 +{
432 +       struct condition_variable *var =
433 +           (struct condition_variable *) data;
434 +
435 +       if (length) {
436 +               /* Match only on the first character */
437 +               switch (buffer[0]) {
438 +               case '0':
439 +                       var->enabled = 0;
440 +                       break;
441 +               case '1':
442 +                       var->enabled = 1;
443 +               }
444 +       }
445 +
446 +       return (int) length;
447 +}
448 +
449 +
450 +static int
451 +match(const struct sk_buff *skb, const struct net_device *in,
452 +      const struct net_device *out, const void *matchinfo, int offset,
453 +      const void *hdr, u_int16_t datalen, int *hotdrop)
454 +{
455 +       const struct condition6_info *info =
456 +           (const struct condition6_info *) matchinfo;
457 +       struct condition_variable *var;
458 +       int condition_status = 0;
459 +
460 +       read_lock(&list_lock);
461 +
462 +       for (var = head; var; var = var->next) {
463 +               if (strcmp(info->name, var->status_proc->name) == 0) {
464 +                       condition_status = var->enabled;
465 +                       break;
466 +               }
467 +       }
468 +
469 +       read_unlock(&list_lock);
470 +
471 +       return condition_status ^ info->invert;
472 +}
473 +
474 +
475 +
476 +static int
477 +checkentry(const char *tablename, const struct ip6t_ip6 *ip,
478 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
479 +{
480 +       struct condition6_info *info =
481 +           (struct condition6_info *) matchinfo;
482 +       struct condition_variable *var, *newvar;
483 +
484 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
485 +               return 0;
486 +
487 +       /* The first step is to check if the condition variable already exists. */
488 +       /* Here, a read lock is sufficient because we won't change the list */
489 +       read_lock(&list_lock);
490 +
491 +       for (var = head; var; var = var->next) {
492 +               if (strcmp(info->name, var->status_proc->name) == 0) {
493 +                       atomic_inc(&var->refcount);
494 +                       read_unlock(&list_lock);
495 +                       return 1;
496 +               }
497 +       }
498 +
499 +       read_unlock(&list_lock);
500 +
501 +       /* At this point, we need to allocate a new condition variable */
502 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
503 +
504 +       if (!newvar)
505 +               return -ENOMEM;
506 +
507 +       /* Create the condition variable's proc file entry */
508 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
509 +
510 +       if (!newvar->status_proc) {
511 +         /*
512 +          * There are two possibilities:
513 +          *  1- Another condition variable with the same name has been created, which is valid.
514 +          *  2- There was a memory allocation error.
515 +          */
516 +               kfree(newvar);
517 +               read_lock(&list_lock);
518 +
519 +               for (var = head; var; var = var->next) {
520 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
521 +                               atomic_inc(&var->refcount);
522 +                               read_unlock(&list_lock);
523 +                               return 1;
524 +                       }
525 +               }
526 +
527 +               read_unlock(&list_lock);
528 +               return -ENOMEM;
529 +       }
530 +
531 +       atomic_set(&newvar->refcount, 1);
532 +       newvar->enabled = 0;
533 +       newvar->status_proc->owner = THIS_MODULE;
534 +       newvar->status_proc->data = newvar;
535 +       wmb();
536 +       newvar->status_proc->read_proc = ipt_condition_read_info;
537 +       newvar->status_proc->write_proc = ipt_condition_write_info;
538 +
539 +       write_lock(&list_lock);
540 +
541 +       newvar->next = head;
542 +       head = newvar;
543 +
544 +       write_unlock(&list_lock);
545 +
546 +       return 1;
547 +}
548 +
549 +
550 +static void
551 +destroy(void *matchinfo, unsigned int matchsize)
552 +{
553 +       struct condition6_info *info =
554 +           (struct condition6_info *) matchinfo;
555 +       struct condition_variable *var, *prev = NULL;
556 +
557 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
558 +               return;
559 +
560 +       write_lock(&list_lock);
561 +
562 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
563 +            prev = var, var = var->next);
564 +
565 +       if (var && atomic_dec_and_test(&var->refcount)) {
566 +               if (prev)
567 +                       prev->next = var->next;
568 +               else
569 +                       head = var->next;
570 +
571 +               write_unlock(&list_lock);
572 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
573 +               kfree(var);
574 +       } else
575 +               write_unlock(&list_lock);
576 +}
577 +
578 +
579 +static struct ip6t_match condition_match = {
580 +       .name = "condition",
581 +       .match = &match,
582 +       .checkentry = &checkentry,
583 +       .destroy = &destroy,
584 +       .me = THIS_MODULE
585 +};
586 +
587 +
588 +static int __init
589 +init(void)
590 +{
591 +       int errorcode;
592 +
593 +       rwlock_init(&list_lock);
594 +       proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
595 +
596 +       if (proc_net_condition) {
597 +               errorcode = ipt_register_match(&condition_match);
598 +
599 +               if (errorcode)
600 +                       remove_proc_entry("ip6t_condition", proc_net);
601 +       } else
602 +               errorcode = -EACCES;
603 +
604 +       return errorcode;
605 +}
606 +
607 +
608 +static void __exit
609 +fini(void)
610 +{
611 +       ipt_unregister_match(&condition_match);
612 +       remove_proc_entry("ip6t_condition", proc_net);
613 +}
614 +
615 +module_init(init);
616 +module_exit(fini);