]> git.pld-linux.org Git - packages/kernel.git/blob - pom-ng-condition-20060829.patch
- ppc configs updated, rel 0.7
[packages/kernel.git] / pom-ng-condition-20060829.patch
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(+)
6
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
10 @@ -0,0 +1,11 @@
11 +#ifndef _XT_CONDITION_H
12 +#define _XT_CONDITION_H
13 +
14 +#define CONDITION_NAME_LEN  32
15 +
16 +struct condition_info {
17 +       char name[CONDITION_NAME_LEN];
18 +       int  invert;
19 +};
20 +
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
25 @@ -388,5 +388,18 @@
26  
27           To compile it as a module, choose M here.  If unsure, say N.
28  
29 +config NETFILTER_XT_MATCH_CONDITION
30 +        tristate  '"condition" match support'
31 +        depends on NETFILTER_XTABLES
32 +        help
33 +          This option allows you to match firewall rules against condition
34 +          variables stored in the /proc/net/nf_condition directory.
35 +
36 +          N.B.: older versions used /proc/net/ipt_condition. You can
37 +          reenable it with "compat_dir_name".
38 +
39 +          If you want to compile it as a module, say M here and read
40 +          Documentation/modules.txt.  If unsure, say `N'.
41 +
42  endmenu
43  
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
47 @@ -0,0 +0,1 @@
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
52 @@ -0,0 +1,315 @@
53 +/*-------------------------------------------*\
54 +|          Netfilter Condition Module         |
55 +|                                             |
56 +|  Description: This module allows firewall   |
57 +|    rules to match using condition variables |
58 +|    stored in /proc files.                   |
59 +|                                             |
60 +|  Author: Stephane Ouellette     2002-10-22  |
61 +|          <ouellettes@videotron.ca>          |
62 +|          Massimiliano Hofer     2006-05-15  |
63 +|          <max@nucleus.it>                   |
64 +|                                             |
65 +|  History:                                   |
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.           |
71 +|                                             |
72 +|  This software is distributed under the     |
73 +|  terms of the GNU GPL.                      |
74 +\*-------------------------------------------*/
75 +
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>
87 +
88 +#ifndef CONFIG_PROC_FS
89 +#error  "Proc file system support is required for this module"
90 +#endif
91 +
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;
97 +
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");
111 +
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 */
117 +};
118 +
119 +/* proc_lock is a user context only semaphore used for write access */
120 +/*           to the conditions' list.                               */
121 +static DECLARE_MUTEX(proc_lock);
122 +
123 +static LIST_HEAD(conditions_list);
124 +static struct proc_dir_entry *proc_net_condition = NULL;
125 +static const char *dir_name;
126 +
127 +static int
128 +xt_condition_read_info(char __user *buffer, char **start, off_t offset,
129 +                       int length, int *eof, void *data)
130 +{
131 +       struct condition_variable *var =
132 +           (struct condition_variable *) data;
133 +
134 +       buffer[0] = (var->enabled) ? '1' : '0';
135 +       buffer[1] = '\n';
136 +       if (length>=2)
137 +               *eof = 1;
138 +
139 +       return 2;
140 +}
141 +
142 +
143 +static int
144 +xt_condition_write_info(struct file *file, const char __user *buffer,
145 +                        unsigned long length, void *data)
146 +{
147 +       struct condition_variable *var =
148 +           (struct condition_variable *) data;
149 +       char newval;
150 +
151 +       if (length>0) {
152 +               if (get_user(newval, buffer))
153 +                       return -EFAULT;
154 +               /* Match only on the first character */
155 +               switch (newval) {
156 +               case '0':
157 +                       var->enabled = 0;
158 +                       break;
159 +               case '1':
160 +                       var->enabled = 1;
161 +                       break;
162 +               }
163 +       }
164 +
165 +       return (int) length;
166 +}
167 +
168 +
169 +static int
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)
174 +{
175 +       const struct condition_info *info =
176 +           (const struct condition_info *) matchinfo;
177 +       struct condition_variable *var;
178 +       int condition_status = 0;
179 +
180 +       rcu_read_lock();
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;
184 +                       break;
185 +               }
186 +       }
187 +       rcu_read_unlock();
188 +
189 +       return condition_status ^ info->invert;
190 +}
191 +
192 +
193 +
194 +static int
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)
199 +{
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;
204 +
205 +       int i;
206 +
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] == '/')
210 +                       return 0;
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)
214 +               return 0;
215 +
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)
219 +                       return 0;
220 +
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))
224 +          return -EINTR;
225 +
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) {
229 +                       var->refcount++;
230 +                       up(&proc_lock);
231 +                       return 1;
232 +               }
233 +       }
234 +
235 +       /* At this point, we need to allocate a new condition variable. */
236 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
237 +
238 +       if (!newvar) {
239 +               up(&proc_lock);
240 +               return -ENOMEM;
241 +       }
242 +
243 +       /* Create the condition variable's proc file entry. */
244 +       newvar->status_proc = create_proc_entry(info->name, condition_list_perms, proc_net_condition);
245 +
246 +       if (!newvar->status_proc) {
247 +               kfree(newvar);
248 +               up(&proc_lock);
249 +               return -ENOMEM;
250 +       }
251 +
252 +       newvar->refcount = 1;
253 +       newvar->enabled = 0;
254 +       newvar->status_proc->owner = THIS_MODULE;
255 +       newvar->status_proc->data = newvar;
256 +       wmb();
257 +       newvar->status_proc->read_proc = xt_condition_read_info;
258 +       newvar->status_proc->write_proc = xt_condition_write_info;
259 +
260 +       list_add_rcu(&newvar->list, &conditions_list);
261 +
262 +       newvar->status_proc->uid = condition_uid_perms;
263 +       newvar->status_proc->gid = condition_gid_perms;
264 +
265 +       up(&proc_lock);
266 +
267 +       return 1;
268 +}
269 +
270 +
271 +static void
272 +destroy(const struct xt_match *match, void *matchinfo,
273 +       unsigned int matchsize)
274 +{
275 +       struct condition_info *info = (struct condition_info *) matchinfo;
276 +       struct list_head *pos;
277 +       struct condition_variable *var;
278 +
279 +       if (matchsize != XT_ALIGN(sizeof(struct condition_info)))
280 +               return;
281 +
282 +       down(&proc_lock);
283 +
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) {
288 +                               list_del_rcu(pos);
289 +                               remove_proc_entry(var->status_proc->name, proc_net_condition);
290 +                               up(&proc_lock);
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.                                            */
294 +                               synchronize_net();
295 +                               kfree(var);
296 +                               return;
297 +                       }
298 +                       break;
299 +               }
300 +       }
301 +
302 +       up(&proc_lock);
303 +}
304 +
305 +
306 +static struct xt_match condition_match = {
307 +       .name = "condition",
308 +       .family = AF_INET,
309 +       .matchsize = sizeof(struct condition_info),
310 +       .match = &match,
311 +       .checkentry = &checkentry,
312 +       .destroy = &destroy,
313 +       .me = THIS_MODULE
314 +};
315 +
316 +static struct xt_match condition6_match = {
317 +       .name = "condition",
318 +       .family = AF_INET6,
319 +       .matchsize = sizeof(struct condition_info),
320 +       .match = &match,
321 +       .checkentry = &checkentry,
322 +       .destroy = &destroy,
323 +       .me = THIS_MODULE
324 +};
325 +
326 +static int __init
327 +init(void)
328 +{
329 +       int errorcode;
330 +
331 +       dir_name = compat_dir_name? "ipt_condition": "nf_condition";
332 +
333 +       proc_net_condition = proc_mkdir(dir_name, proc_net);
334 +       if (!proc_net_condition) {
335 +               remove_proc_entry(dir_name, proc_net);
336 +               return -EACCES;
337 +       }
338 +
339 +        errorcode = xt_register_match(&condition_match);
340 +       if (errorcode) {
341 +               xt_unregister_match(&condition_match);
342 +               remove_proc_entry(dir_name, proc_net);
343 +               return errorcode;
344 +       }
345 +
346 +       errorcode = xt_register_match(&condition6_match);
347 +       if (errorcode) {
348 +               xt_unregister_match(&condition6_match);
349 +               xt_unregister_match(&condition_match);
350 +               remove_proc_entry(dir_name, proc_net);
351 +               return errorcode;
352 +       }
353 +
354 +       return 0;
355 +}
356 +
357 +
358 +static void __exit
359 +fini(void)
360 +{
361 +       xt_unregister_match(&condition6_match);
362 +       xt_unregister_match(&condition_match);
363 +       remove_proc_entry(dir_name, proc_net);
364 +}
365 +
366 +module_init(init);
367 +module_exit(fini);
This page took 0.047022 seconds and 3 git commands to generate.