Root/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);
617

Archive Download this file



interactive