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