1 include/linux/netfilter/xt_condition.h | 11 +
2 net/netfilter/Kconfig | 13 +
3 net/netfilter/Makefile | 1
4 net/netfilter/xt_condition.c | 315 +++++++++++++++++++++++++++++++++
5 4 files changed, 340 insertions(+)
7 diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter/xt_condition.h linux/include/linux/netfilter/xt_condition.h
8 --- linux.org/include/linux/netfilter/xt_condition.h 1970-01-01 00:00:00.000000000 +0000
9 +++ linux/include/linux/netfilter/xt_condition.h 2006-08-29 12:30:00.000000000 +0000
11 +#ifndef _XT_CONDITION_H
12 +#define _XT_CONDITION_H
14 +#define CONDITION_NAME_LEN 32
16 +struct condition_info {
17 + char name[CONDITION_NAME_LEN];
21 +#endif /* _XT_CONDITION_H */
22 diff -Nur --exclude '*.orig' linux.org/net/netfilter/Kconfig linux/net/netfilter/Kconfig
23 --- linux.org/net/netfilter/Kconfig 2006-06-18 01:49:35.000000000 +0000
24 +++ linux/net/netfilter/Kconfig 2006-08-29 12:30:00.000000000 +0000
27 To compile it as a module, choose M here. If unsure, say N.
29 +config NETFILTER_XT_MATCH_CONDITION
30 + tristate '"condition" match support'
31 + depends on NETFILTER_XTABLES
33 + This option allows you to match firewall rules against condition
34 + variables stored in the /proc/net/nf_condition directory.
36 + N.B.: older versions used /proc/net/ipt_condition. You can
37 + reenable it with "compat_dir_name".
39 + If you want to compile it as a module, say M here and read
40 + Documentation/modules.txt. If unsure, say `N'.
44 diff -Nur --exclude '*.orig' linux.org/net/netfilter/Makefile linux/net/netfilter/Makefile
45 --- linux.org/net/netfilter/Makefile 2006-06-18 01:49:35.000000000 +0000
46 +++ linux/net/netfilter/Makefile 2006-08-29 12:30:00.000000000 +0000
48 +obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_condition.o
49 diff -Nur --exclude '*.orig' linux.org/net/netfilter/xt_condition.c linux/net/netfilter/xt_condition.c
50 --- linux.org/net/netfilter/xt_condition.c 1970-01-01 00:00:00.000000000 +0000
51 +++ linux/net/netfilter/xt_condition.c 2006-08-29 12:30:00.000000000 +0000
53 +/*-------------------------------------------*\
54 +| Netfilter Condition Module |
56 +| Description: This module allows firewall |
57 +| rules to match using condition variables |
58 +| stored in /proc files. |
60 +| Author: Stephane Ouellette 2002-10-22 |
61 +| <ouellettes@videotron.ca> |
62 +| Massimiliano Hofer 2006-05-15 |
66 +| 2003-02-10 Second version with improved |
67 +| locking and simplified code. |
68 +| 2006-05-15 2.6.16 adaptations. |
69 +| Locking overhaul. |
70 +| Various bug fixes. |
72 +| This software is distributed under the |
73 +| terms of the GNU GPL. |
74 +\*-------------------------------------------*/
76 +#include <linux/kernel.h>
77 +#include <linux/module.h>
78 +#include <linux/proc_fs.h>
79 +#include <linux/spinlock.h>
80 +#include <asm/semaphore.h>
81 +#include <linux/string.h>
82 +#include <linux/list.h>
83 +#include <asm/atomic.h>
84 +#include <asm/uaccess.h>
85 +#include <linux/netfilter/x_tables.h>
86 +#include <linux/netfilter/xt_condition.h>
88 +#ifndef CONFIG_PROC_FS
89 +#error "Proc file system support is required for this module"
92 +/* Defaults, these can be overridden on the module command-line. */
93 +static unsigned int condition_list_perms = 0644;
94 +static unsigned int compat_dir_name = 0;
95 +static unsigned int condition_uid_perms = 0;
96 +static unsigned int condition_gid_perms = 0;
98 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca> and Massimiliano Hofer <max@nucleus.it>");
99 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
100 +MODULE_LICENSE("GPL");
101 +module_param(condition_list_perms, uint, 0600);
102 +MODULE_PARM_DESC(condition_list_perms,"permissions on /proc/net/nf_condition/* files");
103 +module_param(condition_uid_perms, uint, 0600);
104 +MODULE_PARM_DESC(condition_uid_perms,"user owner of /proc/net/nf_condition/* files");
105 +module_param(condition_gid_perms, uint, 0600);
106 +MODULE_PARM_DESC(condition_gid_perms,"group owner of /proc/net/nf_condition/* files");
107 +module_param(compat_dir_name, bool, 0400);
108 +MODULE_PARM_DESC(compat_dir_name,"use old style /proc/net/ipt_condition/* files");
109 +MODULE_ALIAS("ipt_condition");
110 +MODULE_ALIAS("ip6t_condition");
112 +struct condition_variable {
113 + struct list_head list;
114 + struct proc_dir_entry *status_proc;
115 + unsigned int refcount;
116 + int enabled; /* TRUE == 1, FALSE == 0 */
119 +/* proc_lock is a user context only semaphore used for write access */
120 +/* to the conditions' list. */
121 +static DECLARE_MUTEX(proc_lock);
123 +static LIST_HEAD(conditions_list);
124 +static struct proc_dir_entry *proc_net_condition = NULL;
125 +static const char *dir_name;
128 +xt_condition_read_info(char __user *buffer, char **start, off_t offset,
129 + int length, int *eof, void *data)
131 + struct condition_variable *var =
132 + (struct condition_variable *) data;
134 + buffer[0] = (var->enabled) ? '1' : '0';
144 +xt_condition_write_info(struct file *file, const char __user *buffer,
145 + unsigned long length, void *data)
147 + struct condition_variable *var =
148 + (struct condition_variable *) data;
152 + if (get_user(newval, buffer))
154 + /* Match only on the first character */
165 + return (int) length;
170 +match(const struct sk_buff *skb, const struct net_device *in,
171 + const struct net_device *out, const struct xt_match *match,
172 + const void *matchinfo, int offset,
173 + unsigned int protoff, int *hotdrop)
175 + const struct condition_info *info =
176 + (const struct condition_info *) matchinfo;
177 + struct condition_variable *var;
178 + int condition_status = 0;
181 + list_for_each_entry_rcu(var, &conditions_list, list) {
182 + if (strcmp(info->name, var->status_proc->name) == 0) {
183 + condition_status = var->enabled;
189 + return condition_status ^ info->invert;
195 +checkentry(const char *tablename, const void *ip,
196 + const struct xt_match *match,
197 + void *matchinfo, unsigned int matchsize,
198 + unsigned int hook_mask)
200 + static const char * const forbidden_names[]={ "", ".", ".." };
201 + struct condition_info *info = (struct condition_info *) matchinfo;
202 + struct list_head *pos;
203 + struct condition_variable *var, *newvar;
207 + /* We don't want a '/' in a proc file name. */
208 + for (i=0; i < CONDITION_NAME_LEN && info->name[i] != '\0'; i++)
209 + if (info->name[i] == '/')
211 + /* We can't handle file names longer than CONDITION_NAME_LEN and */
212 + /* we want a NULL terminated string. */
213 + if (i == CONDITION_NAME_LEN)
216 + /* We don't want certain reserved names. */
217 + for (i=0; i < sizeof(forbidden_names)/sizeof(char *); i++)
218 + if(strcmp(info->name, forbidden_names[i])==0)
221 + /* Let's acquire the lock, check for the condition and add it */
222 + /* or increase the reference counter. */
223 + if (down_interruptible(&proc_lock))
226 + list_for_each(pos, &conditions_list) {
227 + var = list_entry(pos, struct condition_variable, list);
228 + if (strcmp(info->name, var->status_proc->name) == 0) {
235 + /* At this point, we need to allocate a new condition variable. */
236 + newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
243 + /* Create the condition variable's proc file entry. */
244 + newvar->status_proc = create_proc_entry(info->name, condition_list_perms, proc_net_condition);
246 + if (!newvar->status_proc) {
252 + newvar->refcount = 1;
253 + newvar->enabled = 0;
254 + newvar->status_proc->owner = THIS_MODULE;
255 + newvar->status_proc->data = newvar;
257 + newvar->status_proc->read_proc = xt_condition_read_info;
258 + newvar->status_proc->write_proc = xt_condition_write_info;
260 + list_add_rcu(&newvar->list, &conditions_list);
262 + newvar->status_proc->uid = condition_uid_perms;
263 + newvar->status_proc->gid = condition_gid_perms;
272 +destroy(const struct xt_match *match, void *matchinfo,
273 + unsigned int matchsize)
275 + struct condition_info *info = (struct condition_info *) matchinfo;
276 + struct list_head *pos;
277 + struct condition_variable *var;
279 + if (matchsize != XT_ALIGN(sizeof(struct condition_info)))
284 + list_for_each(pos, &conditions_list) {
285 + var = list_entry(pos, struct condition_variable, list);
286 + if (strcmp(info->name, var->status_proc->name) == 0) {
287 + if (--var->refcount == 0) {
289 + remove_proc_entry(var->status_proc->name, proc_net_condition);
291 + /* synchronize_rcu() would be goog enough, but synchronize_net() */
292 + /* guarantees that no packet will go out with the old rule after */
293 + /* succesful removal. */
306 +static struct xt_match condition_match = {
307 + .name = "condition",
309 + .matchsize = sizeof(struct condition_info),
311 + .checkentry = &checkentry,
312 + .destroy = &destroy,
316 +static struct xt_match condition6_match = {
317 + .name = "condition",
318 + .family = AF_INET6,
319 + .matchsize = sizeof(struct condition_info),
321 + .checkentry = &checkentry,
322 + .destroy = &destroy,
331 + dir_name = compat_dir_name? "ipt_condition": "nf_condition";
333 + proc_net_condition = proc_mkdir(dir_name, proc_net);
334 + if (!proc_net_condition) {
335 + remove_proc_entry(dir_name, proc_net);
339 + errorcode = xt_register_match(&condition_match);
341 + xt_unregister_match(&condition_match);
342 + remove_proc_entry(dir_name, proc_net);
346 + errorcode = xt_register_match(&condition6_match);
348 + xt_unregister_match(&condition6_match);
349 + xt_unregister_match(&condition_match);
350 + remove_proc_entry(dir_name, proc_net);
361 + xt_unregister_match(&condition6_match);
362 + xt_unregister_match(&condition_match);
363 + remove_proc_entry(dir_name, proc_net);