]> git.pld-linux.org Git - packages/kernel.git/blob - pom-ng-expire-20060504.patch
- updated to 2.6.16.53
[packages/kernel.git] / pom-ng-expire-20060504.patch
1  include/linux/netfilter_ipv4/ipt_expire.h  |   32 +
2  include/linux/netfilter_ipv6/ip6t_expire.h |   32 +
3  net/ipv4/netfilter/Kconfig                 |   11 
4  net/ipv4/netfilter/Makefile                |    1 
5  net/ipv4/netfilter/ipt_expire.c            |  563 ++++++++++++++++++++++++++++
6  net/ipv6/netfilter/Kconfig                 |   11 
7  net/ipv6/netfilter/Makefile                |    1 
8  net/ipv6/netfilter/ip6t_expire.c           |  566 +++++++++++++++++++++++++++++
9  8 files changed, 1217 insertions(+)
10
11 diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ipt_expire.h linux/include/linux/netfilter_ipv4/ipt_expire.h
12 --- linux.org/include/linux/netfilter_ipv4/ipt_expire.h 1970-01-01 01:00:00.000000000 +0100
13 +++ linux/include/linux/netfilter_ipv4/ipt_expire.h     2006-05-04 10:04:04.000000000 +0200
14 @@ -0,0 +1,32 @@
15 +/* This module matches until it expires, at which point the entire
16 + * rule is deleted
17 + *
18 + * This module is free software; you can redistribute it and/or modify
19 + * it under the terms of the GNU General Public License as published by
20 + * the Free Software Foundation; either version 2 of the License, or
21 + * (at your option) any later version.
22 + *
23 + * This module is distributed in the hope that it will be useful,
24 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26 + * GNU General Public License for more details.
27 + *
28 + * You should have received a copy of the GNU General Public License
29 + * along with this module; if not, write to:
30 + *      The Free Software Foundation, Inc.
31 + *      59 Temple Place, Suite 330
32 + *      Boston, MA  02111-1307  USA
33 + *
34 + * Copyright © 2005 Bryan Cardillo <dillo@seas.upenn.edu>
35 + */
36 +
37 +#ifndef __IPT_EXPIRE_H
38 +#define __IPT_EXPIRE_H
39 +
40 +#include <linux/types.h>
41 +
42 +struct ipt_exp_info {
43 +       time_t expiration;
44 +};
45 +
46 +#endif
47 diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv6/ip6t_expire.h linux/include/linux/netfilter_ipv6/ip6t_expire.h
48 --- linux.org/include/linux/netfilter_ipv6/ip6t_expire.h        1970-01-01 01:00:00.000000000 +0100
49 +++ linux/include/linux/netfilter_ipv6/ip6t_expire.h    2006-05-04 10:04:04.000000000 +0200
50 @@ -0,0 +1,32 @@
51 +/* This module matches until it expires, at which point the entire
52 + * rule is deleted
53 + *
54 + * This module is free software; you can redistribute it and/or modify
55 + * it under the terms of the GNU General Public License as published by
56 + * the Free Software Foundation; either version 2 of the License, or
57 + * (at your option) any later version.
58 + *
59 + * This module is distributed in the hope that it will be useful,
60 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
61 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
62 + * GNU General Public License for more details.
63 + *
64 + * You should have received a copy of the GNU General Public License
65 + * along with this module; if not, write to:
66 + *      The Free Software Foundation, Inc.
67 + *      59 Temple Place, Suite 330
68 + *      Boston, MA  02111-1307  USA
69 + *
70 + * Copyright © 2005 Bryan Cardillo <dillo@seas.upenn.edu>
71 + */
72 +
73 +#ifndef __IP6T_EXPIRE_H
74 +#define __IP6T_EXPIRE_H
75 +
76 +#include <linux/types.h>
77 +
78 +struct ip6t_exp_info {
79 +       time_t expiration;
80 +};
81 +
82 +#endif
83 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
84 --- linux.org/net/ipv4/netfilter/Kconfig        2006-05-02 23:38:44.000000000 +0200
85 +++ linux/net/ipv4/netfilter/Kconfig    2006-05-04 10:04:04.000000000 +0200
86 @@ -606,5 +606,16 @@
87           Allows altering the ARP packet payload: source and destination
88           hardware and network addresses.
89  
90 +config IP_NF_MATCH_EXPIRE
91 +       tristate  'expiring match support'
92 +       depends on IP_NF_IPTABLES
93 +       help
94 +         This option adds an expiring match, which allows you to add
95 +         rules to your iptables ruleset which will later be removed
96 +         automatically.
97 +
98 +         If you want to compile it as a module, say M here and read
99 +         Documentation/modules.txt.  If unsure, say `N'.
100 +
101  endmenu
102  
103 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Makefile linux/net/ipv4/netfilter/Makefile
104 --- linux.org/net/ipv4/netfilter/Makefile       2006-05-02 23:38:44.000000000 +0200
105 +++ linux/net/ipv4/netfilter/Makefile   2006-05-04 10:04:04.000000000 +0200
106 @@ -0,0 +0,1 @@
107 +obj-$(CONFIG_IP_NF_MATCH_EXPIRE) += ipt_expire.o
108 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ipt_expire.c linux/net/ipv4/netfilter/ipt_expire.c
109 --- linux.org/net/ipv4/netfilter/ipt_expire.c   1970-01-01 01:00:00.000000000 +0100
110 +++ linux/net/ipv4/netfilter/ipt_expire.c       2006-05-04 10:04:04.000000000 +0200
111 @@ -0,0 +1,563 @@
112 +/* This module matches until it expires, at which point the entire
113 + * rule is deleted
114 + *
115 + * This module is free software; you can redistribute it and/or modify
116 + * it under the terms of the GNU General Public License as published by
117 + * the Free Software Foundation; either version 2 of the License, or
118 + * (at your option) any later version.
119 + *
120 + * This module is distributed in the hope that it will be useful,
121 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
122 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
123 + * GNU General Public License for more details.
124 + *
125 + * You should have received a copy of the GNU General Public License
126 + * along with this module; if not, write to:
127 + *      The Free Software Foundation, Inc.
128 + *      59 Temple Place, Suite 330
129 + *      Boston, MA  02111-1307  USA
130 + *
131 + * Copyright © 2005 Bryan Cardillo <dillo@seas.upenn.edu>
132 + */
133 +
134 +#include <linux/config.h>
135 +#include <linux/kernel.h>
136 +#include <linux/module.h>
137 +#include <linux/workqueue.h>
138 +#include <linux/vmalloc.h>
139 +#include <linux/time.h>
140 +#include <linux/netfilter_ipv4/ip_tables.h>
141 +#include <linux/netfilter_ipv4/ipt_expire.h>
142 +
143 +#if CONFIG_NETFILTER_DEBUG
144 +#define dprintk(format, args...) \
145 +       printk("ipt_expire[%s]: " format "\n", __FUNCTION__, ## args)
146 +#else
147 +#define dprintk(format, args...)
148 +#endif
149 +
150 +MODULE_AUTHOR("Bryan Cardillo <dillo@seas.upenn.edu>");
151 +MODULE_DESCRIPTION("an iptables expiring match module");
152 +MODULE_LICENSE("GPL");
153 +MODULE_VERSION("1.1");
154 +static int __init ipt_exp_init(void);
155 +static void __exit ipt_exp_exit(void);
156 +module_init(ipt_exp_init);
157 +module_exit(ipt_exp_exit);
158 +
159 +static int ipt_exp_match(const struct sk_buff *,
160 +               const struct net_device *, const struct net_device *,
161 +               const void *, int, unsigned int, int *);
162 +static int ipt_exp_checkentry(const char *, const struct ipt_ip *,
163 +               void *, unsigned int, unsigned int);
164 +static int ipt_exp_add_table(const char *);
165 +static void ipt_exp_remove_table(const char *);
166 +static void ipt_exp_schedule_expiration(time_t);
167 +static void ipt_exp_work_fn(void *);
168 +static int ipt_exp_get_info(const char *, struct ipt_getinfo *);
169 +static int ipt_exp_get_entries(struct ipt_getinfo *, struct ipt_get_entries *);
170 +static int ipt_exp_get_active(struct ipt_getinfo *,
171 +               struct ipt_get_entries *, struct ipt_replace *);
172 +static int ipt_exp_copy_active(struct ipt_entry *, struct ipt_replace *);
173 +static int ipt_exp_is_expired(struct ipt_entry_match *);
174 +static int ipt_exp_replace_expired(struct ipt_replace *);
175 +static int ipt_exp_get_counters(struct ipt_get_entries *,
176 +               struct ipt_replace *, struct ipt_counters_info *);
177 +static int ipt_exp_copy_counter(struct ipt_entry *, struct ipt_replace *,
178 +               struct ipt_counters_info *, int *);
179 +static int ipt_exp_restore_counters(struct ipt_counters_info *);
180 +
181 +/**
182 + * struct for list of tables
183 + */
184 +struct ipt_exp_table {
185 +       /**
186 +        * the table name
187 +        */
188 +       char name[IPT_TABLE_MAXNAMELEN];
189 +       /**
190 +        * a list_head structure enabling list inclusion
191 +        */
192 +       struct list_head list;
193 +};
194 +
195 +/**
196 + * work_struct for scheduling the deletion of expired rules
197 + */
198 +static DECLARE_WORK(ipt_exp_work, &ipt_exp_work_fn, NULL);
199 +
200 +/**
201 + * iptables match
202 + */
203 +static struct ipt_match ipt_expire_match = {
204 +       .name           = "expire",
205 +       .match          = &ipt_exp_match,
206 +       .checkentry     = &ipt_exp_checkentry,
207 +       .me             = THIS_MODULE
208 +};
209 +
210 +/**
211 + * the list of tables contained expiring entries
212 + */
213 +static spinlock_t ipt_exp_tables_lock = SPIN_LOCK_UNLOCKED;
214 +static LIST_HEAD(ipt_exp_tables);
215 +
216 +/**
217 + * initialize module and register iptables match
218 + * @see module_init()
219 + * @see ipt_register_match()
220 + */
221 +static int __init
222 +ipt_exp_init(void)
223 +{
224 +       dprintk("initializing");
225 +       ipt_register_match(&ipt_expire_match);
226 +       return 0;
227 +}
228 +
229 +/**
230 + * cleanup module and unregister iptables match
231 + * @see module_exit()
232 + * @see ipt_unregister_match()
233 + */
234 +static void __exit
235 +ipt_exp_exit(void)
236 +{
237 +       unsigned long flags;
238 +       struct ipt_exp_table *t, *tmp;
239 +
240 +       dprintk("exiting");
241 +
242 +       ipt_unregister_match(&ipt_expire_match);
243 +       cancel_delayed_work(&ipt_exp_work);
244 +       
245 +       spin_lock_irqsave(&ipt_exp_tables_lock, flags);
246 +       list_for_each_entry_safe(t, tmp, &ipt_exp_tables, list)
247 +               kfree(t);
248 +       spin_unlock_irqrestore(&ipt_exp_tables_lock, flags);
249 +}
250 +
251 +/**
252 + * match if the expiration time has't passed
253 + * @param skb socket buffer
254 + * @param in inbound network device
255 + * @param out outbound network device
256 + * @param matchinfo match specific data
257 + * @param offset match offset (?)
258 + * @param hotdrop set to 1 to drop packet immediately when returning false
259 + * @return non-zero for active rules, zero otherwise
260 + * @see struct ipt_match
261 + */
262 +static int
263 +ipt_exp_match(const struct sk_buff *skb,
264 +               const struct net_device *in, const struct net_device *out,
265 +               const void *matchinfo, int offset, unsigned int protoff, int *hotdrop)
266 +{
267 +       const struct ipt_exp_info *info = matchinfo;
268 +
269 +       if (get_seconds() < info->expiration)
270 +               return 1;
271 +
272 +       return 0;
273 +}
274 +
275 +/**
276 + * check a new iptables entry
277 + * @param tablename table name for new entry
278 + * @param ip ip info for new entry
279 + * @param matchinfo match specific data
280 + * @param matchsize size of matchinfo data
281 + * @param hookmask valid netfilter hooks (?)
282 + * @return non-zero for valid entries, zero otherwise
283 + */
284 +static int
285 +ipt_exp_checkentry(const char *tablename, const struct ipt_ip *ip,
286 +               void *matchinfo, unsigned int matchsize, unsigned int hookmask)
287 +{
288 +       struct ipt_exp_info *info = matchinfo;
289 +
290 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_exp_info)))
291 +               return 0;
292 +
293 +       if (info->expiration <= get_seconds())
294 +               return 0;
295 +
296 +       if (ipt_exp_add_table(tablename))
297 +               return 0;
298 +
299 +       ipt_exp_schedule_expiration(info->expiration);
300 +
301 +       return 1;
302 +}
303 +
304 +/**
305 + * add a table to the set of tables to be searched for expired rules
306 + * @param tablename the name of the table
307 + * @return zero on success, non-zero on failure
308 + */
309 +static int
310 +ipt_exp_add_table(const char *tablename)
311 +{
312 +       unsigned long flags;
313 +       struct ipt_exp_table *t;
314 +
315 +       spin_lock_irqsave(&ipt_exp_tables_lock, flags);
316 +       list_for_each_entry(t, &ipt_exp_tables, list)
317 +               if (strncmp(t->name, tablename, IPT_TABLE_MAXNAMELEN) == 0)
318 +                       break;
319 +       spin_unlock_irqrestore(&ipt_exp_tables_lock, flags);
320 +
321 +       if (&t->list == &ipt_exp_tables) {
322 +               if (!(t = kmalloc(sizeof(struct ipt_exp_table), GFP_KERNEL))) {
323 +                       dprintk("error allocating memory");
324 +                       return -ENOMEM;
325 +               }
326 +               strlcpy(t->name, tablename, IPT_TABLE_MAXNAMELEN);
327 +               spin_lock_irqsave(&ipt_exp_tables_lock, flags);
328 +               list_add_tail(&t->list, &ipt_exp_tables);
329 +               spin_unlock_irqrestore(&ipt_exp_tables_lock, flags);
330 +       }
331 +       return 0;
332 +}
333 +
334 +/**
335 + * remove a table from the set of tables to be searched for expired rules
336 + * @param tablename the name of the table to be removed
337 + */
338 +static void
339 +ipt_exp_remove_table(const char *tablename)
340 +{
341 +       unsigned long flags;
342 +       struct ipt_exp_table *t, *tmp;
343 +
344 +       spin_lock_irqsave(&ipt_exp_tables_lock, flags);
345 +       list_for_each_entry_safe(t, tmp, &ipt_exp_tables, list) {
346 +               if (strncmp(t->name, tablename, IPT_TABLE_MAXNAMELEN) == 0) {
347 +                       list_del(&t->list);
348 +                       kfree(t);
349 +               }
350 +       }
351 +       spin_unlock_irqrestore(&ipt_exp_tables_lock, flags);
352 +}
353 +
354 +/**
355 + * schedule the next removal of expired rules
356 + * @param expiration the time to be scheduled
357 + */
358 +static void
359 +ipt_exp_schedule_expiration(time_t expiration)
360 +{
361 +       unsigned long delay = (expiration - get_seconds() < 1) ? HZ :
362 +                                       (expiration - get_seconds()) * HZ;
363 +
364 +       schedule_delayed_work(&ipt_exp_work, delay);
365 +}
366 +
367 +/**
368 + * delete expired iptables rules
369 + * @param __notused
370 + * @see schedule_delayed_work()
371 + */
372 +static void
373 +ipt_exp_work_fn(void *__notused)
374 +{
375 +       struct ipt_exp_table *t;
376 +
377 +       /*
378 +        * FIXME what about locking here?
379 +        */
380 +       list_for_each_entry(t, &ipt_exp_tables, list) {
381 +               size_t sz;
382 +               struct ipt_getinfo info;
383 +               struct ipt_get_entries *entries = NULL;
384 +               struct ipt_replace *replace = NULL;
385 +               struct ipt_counters_info *counters = NULL;
386 +
387 +               dprintk("expiring %s entries", t->name);
388 +
389 +               /* get table info */
390 +               if (ipt_exp_get_info(t->name, &info))
391 +                       continue;
392 +
393 +               /* allocate memory */
394 +               sz = sizeof(struct ipt_get_entries) + info.size;
395 +               if (!(entries = vmalloc(sz))) {
396 +                       dprintk("error allocating entry table");
397 +                       break;
398 +               }
399 +               sz = sizeof(struct ipt_replace) + info.size;
400 +               if (!(replace = vmalloc(sz))) {
401 +                       dprintk("error allocating replacement table");
402 +                       goto out_free_entries;
403 +               }
404 +               memset(replace, 0, sz);
405 +               sz = sizeof(struct ipt_counters) * info.num_entries;
406 +               if (!(replace->counters = vmalloc(sz))) {
407 +                       dprintk("error allocating counters");
408 +                       goto out_free_entries_replace;
409 +               }
410 +               memset(replace->counters, 0, sz);
411 +               sz += sizeof(struct ipt_counters_info);
412 +               if (!(counters = vmalloc(sz))) {
413 +                       dprintk("error allocating new counters");
414 +                       goto out_free_entries_replace_counters;
415 +               }
416 +               memset(counters, 0, sz);
417 +
418 +               /* get all entries, then copy active ones */
419 +               if (ipt_exp_get_entries(&info, entries))
420 +                       goto out_free_entries_replace_counters_info;
421 +               if (ipt_exp_get_active(&info, entries, replace))
422 +                       goto out_free_entries_replace_counters_info;
423 +
424 +               /* replace table */
425 +               if (replace->size < info.size) {
426 +                       if (ipt_exp_get_counters(entries, replace, counters))
427 +                               goto out_free_entries_replace_counters_info;
428 +                       if (ipt_exp_replace_expired(replace))
429 +                               goto out_free_entries_replace_counters_info;
430 +                       if (ipt_exp_restore_counters(counters))
431 +                               goto out_free_entries_replace_counters_info;
432 +               }
433 +
434 +               dprintk("expired %s entries", t->name);
435 +
436 +out_free_entries_replace_counters_info:
437 +               vfree(counters);
438 +out_free_entries_replace_counters:
439 +               vfree(replace->counters);
440 +out_free_entries_replace:
441 +               vfree(replace);
442 +out_free_entries:
443 +               vfree(entries);
444 +       }
445 +}
446 +
447 +/**
448 + * get info on an a table
449 + * @param name the name of the table
450 + * @param info the location to store the retrieved info
451 + * @return zero on success, non-zero otherwise
452 + */
453 +static int
454 +ipt_exp_get_info(const char *name, struct ipt_getinfo *info)
455 +{
456 +       int ret = 0;
457 +       int sz = sizeof(struct ipt_getinfo);
458 +
459 +       dprintk("getting entry info");
460 +
461 +       strlcpy(info->name, name, IPT_TABLE_MAXNAMELEN);
462 +       ret = nf_getsockopt(NULL, PF_INET, IPT_SO_GET_INFO, (char *)info, &sz);
463 +       switch (ret) {
464 +               case 0:
465 +                       break;
466 +               case -ENOENT:
467 +                       /* table is gone */
468 +                       ipt_exp_remove_table(name);
469 +                       break;
470 +               default:
471 +                       dprintk("error getting iptables info");
472 +                       break;
473 +       }
474 +
475 +       return ret;
476 +}
477 +
478 +/**
479 + * get the entries for a table
480 + * @param info the location of info about the table
481 + * @param entries the location to allocate and store the retrieved entries
482 + * @return zero on success, non-zero otherwise
483 + */
484 +static int
485 +ipt_exp_get_entries(struct ipt_getinfo *info, struct ipt_get_entries *entries)
486 +{
487 +       int ret = 0;
488 +       int sz = sizeof(struct ipt_get_entries) + info->size;
489 +
490 +       dprintk("getting existing entries");
491 +
492 +       strlcpy(entries->name, info->name, IPT_TABLE_MAXNAMELEN);
493 +       entries->size = info->size;
494 +       ret = nf_getsockopt(NULL, PF_INET,
495 +                       IPT_SO_GET_ENTRIES, (char *)entries, &sz);
496 +       if (ret)
497 +               dprintk("error getting iptables entries");
498 +
499 +       return ret;
500 +}
501 +
502 +/**
503 + * iterate over a tables entries, copying entries which
504 + * are not expired to the replacement table
505 + * @param info the location of info about the table
506 + * @param entries the location of the table entries
507 + * @param replace the location to allocate and store the replacement entries
508 + * @return zero on success, non-zero otherwise
509 + */
510 +static int
511 +ipt_exp_get_active(struct ipt_getinfo *info,
512 +               struct ipt_get_entries *entries, struct ipt_replace *replace)
513 +{
514 +       dprintk("copying active entries");
515 +
516 +       /* copy stuff */
517 +       strlcpy(replace->name, info->name, IPT_TABLE_MAXNAMELEN);
518 +       memcpy(replace->hook_entry, info->hook_entry, sizeof(info->hook_entry));
519 +       memcpy(replace->underflow, info->underflow, sizeof(info->underflow));
520 +       replace->valid_hooks = info->valid_hooks;
521 +       replace->num_counters = info->num_entries;
522 +
523 +       /* set size and entry count */
524 +       replace->size = 0;
525 +       replace->num_entries = 0;
526 +
527 +       return IPT_ENTRY_ITERATE(entries->entrytable, entries->size, 
528 +                                       ipt_exp_copy_active, replace);
529 +}
530 +
531 +/**
532 + * copy a table entry if it is not expired
533 + * @param entry the source entry
534 + * @param replace the replacement table
535 + * @return zero;
536 + */
537 +static int
538 +ipt_exp_copy_active(struct ipt_entry *entry, struct ipt_replace *replace)
539 +{
540 +       if (!(IPT_MATCH_ITERATE(entry, ipt_exp_is_expired))) {
541 +               struct ipt_entry *dest =
542 +                               (void *)replace->entries + replace->size;
543 +               memcpy(dest, entry, entry->next_offset);
544 +               replace->size += entry->next_offset;
545 +               replace->num_entries++;
546 +       }
547 +
548 +       return 0;
549 +}
550 +
551 +/**
552 + * determine if an entry is expired
553 + * @param match the entry match to check for expiration
554 + * @return non-zero for expired entries, zero otherwise
555 + */
556 +static int
557 +ipt_exp_is_expired(struct ipt_entry_match *match)
558 +{
559 +       if (strcmp(match->u.user.name, "expire") == 0) {
560 +               struct ipt_exp_info *info = (struct ipt_exp_info *)match->data;
561 +               if (info->expiration <= get_seconds())
562 +                       return 1;
563 +       }
564 +       return 0;
565 +}
566 +
567 +/**
568 + * update a table
569 + * @param replace the replacement table
570 + * @return zero on success, non-zero otherwise
571 + */
572 +static int
573 +ipt_exp_replace_expired(struct ipt_replace *replace)
574 +{
575 +       int ret = 0;
576 +       int sz = sizeof(struct ipt_replace) + replace->size;
577 +
578 +       dprintk("replacing table %s", replace->name);
579 +
580 +       ret = nf_setsockopt(NULL, PF_INET,
581 +                       IPT_SO_SET_REPLACE, (char *)replace, sz);
582 +       /*
583 +        * FIXME remove this verbosity once tested?
584 +        */
585 +       switch (ret) {
586 +               case 0:
587 +                       break;
588 +               case -EFAULT:
589 +                       dprintk("EFAULT replacing iptables");
590 +                       break;
591 +               case -ENOPROTOOPT:
592 +                       dprintk("ENOPROTOOPT replacing iptables");
593 +                       break;
594 +               case -ENOMEM:
595 +                       dprintk("ENOMEM replacing iptables");
596 +                       break;
597 +               case -ENOENT:
598 +                       dprintk("ENOENT replacing iptables");
599 +                       break;
600 +               case -ELOOP:
601 +                       dprintk("ELOOP replacing iptables");
602 +                       break;
603 +               case -EINVAL:
604 +                       dprintk("EINVAL replacing iptables");
605 +                       break;
606 +               default:
607 +                       dprintk("unknown error (%d) replacing iptables", ret);
608 +                       break;
609 +       }
610 +       return ret;
611 +}
612 +
613 +/**
614 + * get counters for unexpired entries
615 + * @param entries the entries info
616 + * @param replace the replacement structure, containing the old counters
617 + * @param counters the new counter info
618 + * @return zero on success, non-zero on failure
619 + */
620 +static int
621 +ipt_exp_get_counters(struct ipt_get_entries *entries,
622 +               struct ipt_replace *replace,
623 +               struct ipt_counters_info *counters)
624 +{
625 +       int index = 0;
626 +       dprintk("copying active counters");
627 +
628 +       /* init stuff */
629 +       strlcpy(counters->name, replace->name, IPT_TABLE_MAXNAMELEN);
630 +       counters->num_counters = 0;
631 +
632 +       return IPT_ENTRY_ITERATE(entries->entrytable, entries->size, 
633 +                       ipt_exp_copy_counter, replace, counters, &index);
634 +}
635 +
636 +/**
637 + * copy a rule counter if the rule is still active
638 + * @param entry the entry
639 + * @param replace the replacement structure containing the old counters
640 + * @param counter the new counter info
641 + * @param index the current entry index
642 + * @return zero
643 + */
644 +static int
645 +ipt_exp_copy_counter(struct ipt_entry *entry, struct ipt_replace *replace,
646 +               struct ipt_counters_info *counters, int *index)
647 +{
648 +       if (!(IPT_MATCH_ITERATE(entry, ipt_exp_is_expired)))
649 +               counters->counters[counters->num_counters++] =
650 +                               replace->counters[*index];
651 +       (*index)++;
652 +       return 0;
653 +}
654 +
655 +/**
656 + * restore the counters for a table
657 + * @param counter the counters
658 + * @return zero on success, non-zero otherwise
659 + */
660 +static int
661 +ipt_exp_restore_counters(struct ipt_counters_info *counters)
662 +{
663 +       int ret = 0;
664 +       int sz = sizeof(struct ipt_counters_info) +
665 +                       sizeof(struct ipt_counters) * counters->num_counters;
666 +
667 +       dprintk("restoring counters for %s", counters->name);
668 +
669 +       ret = nf_setsockopt(NULL, PF_INET,
670 +                       IPT_SO_SET_ADD_COUNTERS, (char *)counters, sz);
671 +       if (ret)
672 +               dprintk("error restoring counters (%d)", ret);
673 +       return ret;
674 +}
675 diff -Nur --exclude '*.orig' linux.org/net/ipv6/netfilter/Kconfig linux/net/ipv6/netfilter/Kconfig
676 --- linux.org/net/ipv6/netfilter/Kconfig        2006-05-02 23:38:44.000000000 +0200
677 +++ linux/net/ipv6/netfilter/Kconfig    2006-05-04 10:04:04.000000000 +0200
678 @@ -210,5 +210,16 @@
679           If you want to compile it as a module, say M here and read
680           <file:Documentation/modules.txt>.  If unsure, say `N'.
681  
682 +config IP6_NF_MATCH_EXPIRE
683 +       tristate  'expiring match support'
684 +       depends on IP6_NF_IPTABLES
685 +       help
686 +         This option adds an expiring match, which allows you to add
687 +         rules to your iptables ruleset which will later be removed
688 +         automatically.
689 +
690 +         If you want to compile it as a module, say M here and read
691 +         Documentation/modules.txt.  If unsure, say `N'.
692 +
693  endmenu
694  
695 diff -Nur --exclude '*.orig' linux.org/net/ipv6/netfilter/Makefile linux/net/ipv6/netfilter/Makefile
696 --- linux.org/net/ipv6/netfilter/Makefile       2006-05-02 23:38:44.000000000 +0200
697 +++ linux/net/ipv6/netfilter/Makefile   2006-05-04 10:04:04.000000000 +0200
698 @@ -0,0 +0,1 @@
699 +obj-$(CONFIG_IP6_NF_MATCH_EXPIRE) += ip6t_expire.o
700 diff -Nur --exclude '*.orig' linux.org/net/ipv6/netfilter/ip6t_expire.c linux/net/ipv6/netfilter/ip6t_expire.c
701 --- linux.org/net/ipv6/netfilter/ip6t_expire.c  1970-01-01 01:00:00.000000000 +0100
702 +++ linux/net/ipv6/netfilter/ip6t_expire.c      2006-05-04 10:04:04.000000000 +0200
703 @@ -0,0 +1,566 @@
704 +/* This module matches until it expires, at which point the entire
705 + * rule is deleted
706 + *
707 + * This module is free software; you can redistribute it and/or modify
708 + * it under the terms of the GNU General Public License as published by
709 + * the Free Software Foundation; either version 2 of the License, or
710 + * (at your option) any later version.
711 + *
712 + * This module is distributed in the hope that it will be useful,
713 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
714 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
715 + * GNU General Public License for more details.
716 + *
717 + * You should have received a copy of the GNU General Public License
718 + * along with this module; if not, write to:
719 + *      The Free Software Foundation, Inc.
720 + *      59 Temple Place, Suite 330
721 + *      Boston, MA  02111-1307  USA
722 + *
723 + * Copyright © 2005 Bryan Cardillo <dillo@seas.upenn.edu>
724 + */
725 +
726 +#include <linux/config.h>
727 +#include <linux/kernel.h>
728 +#include <linux/module.h>
729 +#include <linux/workqueue.h>
730 +#include <linux/vmalloc.h>
731 +#include <linux/time.h>
732 +#include <linux/netfilter_ipv6/ip6_tables.h>
733 +#include <linux/netfilter_ipv6/ip6t_expire.h>
734 +
735 +#if CONFIG_NETFILTER_DEBUG
736 +#define dprintk(format, args...) \
737 +       printk("ip6t_expire[%s]: " format "\n", __FUNCTION__, ## args)
738 +#else
739 +#define dprintk(format, args...)
740 +#endif
741 +
742 +MODULE_AUTHOR("Bryan Cardillo <dillo@seas.upenn.edu>");
743 +MODULE_DESCRIPTION("an ip6tables expiring match module");
744 +MODULE_LICENSE("GPL");
745 +MODULE_VERSION("1.1");
746 +static int __init ip6t_exp_init(void);
747 +static void __exit ip6t_exp_exit(void);
748 +module_init(ip6t_exp_init);
749 +module_exit(ip6t_exp_exit);
750 +
751 +static int ip6t_exp_match(const struct sk_buff *,
752 +               const struct net_device *, const struct net_device *,
753 +               const void *, int, unsigned int, int *);
754 +static int ip6t_exp_checkentry(const char *, const struct ip6t_ip6 *,
755 +               void *, unsigned int, unsigned int);
756 +static int ip6t_exp_add_table(const char *);
757 +static void ip6t_exp_remove_table(const char *);
758 +static void ip6t_exp_schedule_expiration(time_t);
759 +static void ip6t_exp_work_fn(void *);
760 +static int ip6t_exp_get_info(const char *, struct ip6t_getinfo *);
761 +static int ip6t_exp_get_entries(struct ip6t_getinfo *, struct ip6t_get_entries *);
762 +static int ip6t_exp_get_active(struct ip6t_getinfo *,
763 +               struct ip6t_get_entries *, struct ip6t_replace *);
764 +static int ip6t_exp_copy_active(struct ip6t_entry *, struct ip6t_replace *);
765 +static int ip6t_exp_is_expired(struct ip6t_entry_match *);
766 +static int ip6t_exp_replace_expired(struct ip6t_replace *);
767 +static int ip6t_exp_get_counters(struct ip6t_get_entries *,
768 +               struct ip6t_replace *, struct ip6t_counters_info *);
769 +static int ip6t_exp_copy_counter(struct ip6t_entry *, struct ip6t_replace *,
770 +               struct ip6t_counters_info *, int *);
771 +static int ip6t_exp_restore_counters(struct ip6t_counters_info *);
772 +
773 +/**
774 + * struct for list of tables
775 + */
776 +struct ip6t_exp_table {
777 +       /**
778 +        * the table name
779 +        */
780 +       char name[IP6T_TABLE_MAXNAMELEN];
781 +       /**
782 +        * a list_head structure enabling list inclusion
783 +        */
784 +       struct list_head list;
785 +};
786 +
787 +/**
788 + * work_struct for scheduling the deletion of expired rules
789 + */
790 +static DECLARE_WORK(ip6t_exp_work, &ip6t_exp_work_fn, NULL);
791 +
792 +/**
793 + * ip6tables match
794 + */
795 +static struct ip6t_match ip6t_expire_match = {
796 +       .name           = "expire",
797 +       .match          = &ip6t_exp_match,
798 +       .checkentry     = &ip6t_exp_checkentry,
799 +       .me             = THIS_MODULE
800 +};
801 +
802 +/**
803 + * the list of tables contained expiring entries
804 + */
805 +static spinlock_t ip6t_exp_tables_lock = SPIN_LOCK_UNLOCKED;
806 +static LIST_HEAD(ip6t_exp_tables);
807 +
808 +/**
809 + * initialize module and register ip6tables match
810 + * @see module_init()
811 + * @see ip6t_register_match()
812 + */
813 +static int __init
814 +ip6t_exp_init(void)
815 +{
816 +       dprintk("initializing");
817 +       ip6t_register_match(&ip6t_expire_match);
818 +       return 0;
819 +}
820 +
821 +/**
822 + * cleanup module and unregister ip6tables match
823 + * @see module_exit()
824 + * @see ip6t_unregister_match()
825 + */
826 +static void __exit
827 +ip6t_exp_exit(void)
828 +{
829 +       unsigned long flags;
830 +       struct ip6t_exp_table *t, *tmp;
831 +
832 +       dprintk("exiting");
833 +
834 +       ip6t_unregister_match(&ip6t_expire_match);
835 +       cancel_delayed_work(&ip6t_exp_work);
836 +       
837 +       spin_lock_irqsave(&ip6t_exp_tables_lock, flags);
838 +       list_for_each_entry_safe(t, tmp, &ip6t_exp_tables, list)
839 +               kfree(t);
840 +       spin_unlock_irqrestore(&ip6t_exp_tables_lock, flags);
841 +}
842 +
843 +/**
844 + * match if the expiration time has't passed
845 + * @param skb socket buffer
846 + * @param in inbound network device
847 + * @param out outbound network device
848 + * @param matchinfo match specific data
849 + * @param offset match offset (?)
850 + * @param header (?)
851 + * @param len (?)
852 + * @param hotdrop set to 1 to drop packet immediately when returning false
853 + * @return non-zero for active rules, zero otherwise
854 + * @see struct ip6t_match
855 + */
856 +static int
857 +ip6t_exp_match(const struct sk_buff *skb,
858 +               const struct net_device *in, const struct net_device *out,
859 +               const void *matchinfo, int offset,
860 +               unsigned int protoff, int *hotdrop)
861 +{
862 +       const struct ip6t_exp_info *info = matchinfo;
863 +
864 +       if (get_seconds() < info->expiration)
865 +               return 1;
866 +
867 +       return 0;
868 +}
869 +
870 +/**
871 + * check a new ip6tables entry
872 + * @param tablename table name for new entry
873 + * @param ip ip info for new entry
874 + * @param matchinfo match specific data
875 + * @param matchsize size of matchinfo data
876 + * @param hookmask valid netfilter hooks (?)
877 + * @return non-zero for valid entries, zero otherwise
878 + */
879 +static int
880 +ip6t_exp_checkentry(const char *tablename, const struct ip6t_ip6 *ip,
881 +               void *matchinfo, unsigned int matchsize, unsigned int hookmask)
882 +{
883 +       struct ip6t_exp_info *info = matchinfo;
884 +
885 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_exp_info)))
886 +               return 0;
887 +
888 +       if (info->expiration <= get_seconds())
889 +               return 0;
890 +
891 +       if (ip6t_exp_add_table(tablename))
892 +               return 0;
893 +
894 +       ip6t_exp_schedule_expiration(info->expiration);
895 +
896 +       return 1;
897 +}
898 +
899 +/**
900 + * add a table to the set of tables to be searched for expired rules
901 + * @param tablename the name of the table
902 + * @return zero on success, non-zero on failure
903 + */
904 +static int
905 +ip6t_exp_add_table(const char *tablename)
906 +{
907 +       unsigned long flags;
908 +       struct ip6t_exp_table *t;
909 +
910 +       spin_lock_irqsave(&ip6t_exp_tables_lock, flags);
911 +       list_for_each_entry(t, &ip6t_exp_tables, list)
912 +               if (strncmp(t->name, tablename, IP6T_TABLE_MAXNAMELEN) == 0)
913 +                       break;
914 +       spin_unlock_irqrestore(&ip6t_exp_tables_lock, flags);
915 +
916 +       if (&t->list == &ip6t_exp_tables) {
917 +               if (!(t = kmalloc(sizeof(struct ip6t_exp_table), GFP_KERNEL))) {
918 +                       dprintk("error allocating memory");
919 +                       return -ENOMEM;
920 +               }
921 +               strlcpy(t->name, tablename, IP6T_TABLE_MAXNAMELEN);
922 +               spin_lock_irqsave(&ip6t_exp_tables_lock, flags);
923 +               list_add_tail(&t->list, &ip6t_exp_tables);
924 +               spin_unlock_irqrestore(&ip6t_exp_tables_lock, flags);
925 +       }
926 +       return 0;
927 +}
928 +
929 +/**
930 + * remove a table from the set of tables to be searched for expired rules
931 + * @param tablename the name of the table to be removed
932 + */
933 +static void
934 +ip6t_exp_remove_table(const char *tablename)
935 +{
936 +       unsigned long flags;
937 +       struct ip6t_exp_table *t, *tmp;
938 +
939 +       spin_lock_irqsave(&ip6t_exp_tables_lock, flags);
940 +       list_for_each_entry_safe(t, tmp, &ip6t_exp_tables, list) {
941 +               if (strncmp(t->name, tablename, IP6T_TABLE_MAXNAMELEN) == 0) {
942 +                       list_del(&t->list);
943 +                       kfree(t);
944 +               }
945 +       }
946 +       spin_unlock_irqrestore(&ip6t_exp_tables_lock, flags);
947 +}
948 +
949 +/**
950 + * schedule the next removal of expired rules
951 + * @param expiration the time to be scheduled
952 + */
953 +static void
954 +ip6t_exp_schedule_expiration(time_t expiration)
955 +{
956 +       unsigned long delay = (expiration - get_seconds() < 1) ? HZ :
957 +                                       (expiration - get_seconds()) * HZ;
958 +
959 +       schedule_delayed_work(&ip6t_exp_work, delay);
960 +}
961 +
962 +/**
963 + * delete expired ip6tables rules
964 + * @param __notused
965 + * @see schedule_delayed_work()
966 + */
967 +static void
968 +ip6t_exp_work_fn(void *__notused)
969 +{
970 +       struct ip6t_exp_table *t;
971 +
972 +       /*
973 +        * FIXME what about locking here?
974 +        */
975 +       list_for_each_entry(t, &ip6t_exp_tables, list) {
976 +               size_t sz;
977 +               struct ip6t_getinfo info;
978 +               struct ip6t_get_entries *entries = NULL;
979 +               struct ip6t_replace *replace = NULL;
980 +               struct ip6t_counters_info *counters = NULL;
981 +
982 +               dprintk("expiring %s entries", t->name);
983 +
984 +               /* get table info */
985 +               if (ip6t_exp_get_info(t->name, &info))
986 +                       continue;
987 +
988 +               /* allocate memory */
989 +               sz = sizeof(struct ip6t_get_entries) + info.size;
990 +               if (!(entries = vmalloc(sz))) {
991 +                       dprintk("error allocating entry table");
992 +                       break;
993 +               }
994 +               sz = sizeof(struct ip6t_replace) + info.size;
995 +               if (!(replace = vmalloc(sz))) {
996 +                       dprintk("error allocating replacement table");
997 +                       goto out_free_entries;
998 +               }
999 +               memset(replace, 0, sz);
1000 +               sz = sizeof(struct ip6t_counters) * info.num_entries;
1001 +               if (!(replace->counters = vmalloc(sz))) {
1002 +                       dprintk("error allocating counters");
1003 +                       goto out_free_entries_replace;
1004 +               }
1005 +               memset(replace->counters, 0, sz);
1006 +               sz += sizeof(struct ip6t_counters_info);
1007 +               if (!(counters = vmalloc(sz))) {
1008 +                       dprintk("error allocating new counters");
1009 +                       goto out_free_entries_replace_counters;
1010 +               }
1011 +               memset(counters, 0, sz);
1012 +
1013 +               /* get all entries, then copy active ones */
1014 +               if (ip6t_exp_get_entries(&info, entries))
1015 +                       goto out_free_entries_replace_counters_info;
1016 +               if (ip6t_exp_get_active(&info, entries, replace))
1017 +                       goto out_free_entries_replace_counters_info;
1018 +
1019 +               /* replace table */
1020 +               if (replace->size < info.size) {
1021 +                       if (ip6t_exp_get_counters(entries, replace, counters))
1022 +                               goto out_free_entries_replace_counters_info;
1023 +                       if (ip6t_exp_replace_expired(replace))
1024 +                               goto out_free_entries_replace_counters_info;
1025 +                       if (ip6t_exp_restore_counters(counters))
1026 +                               goto out_free_entries_replace_counters_info;
1027 +               }
1028 +
1029 +               dprintk("expired %s entries", t->name);
1030 +
1031 +out_free_entries_replace_counters_info:
1032 +               vfree(counters);
1033 +out_free_entries_replace_counters:
1034 +               vfree(replace->counters);
1035 +out_free_entries_replace:
1036 +               vfree(replace);
1037 +out_free_entries:
1038 +               vfree(entries);
1039 +       }
1040 +}
1041 +
1042 +/**
1043 + * get info on an a table
1044 + * @param name the name of the table
1045 + * @param info the location to store the retrieved info
1046 + * @return zero on success, non-zero otherwise
1047 + */
1048 +static int
1049 +ip6t_exp_get_info(const char *name, struct ip6t_getinfo *info)
1050 +{
1051 +       int ret = 0;
1052 +       int sz = sizeof(struct ip6t_getinfo);
1053 +
1054 +       dprintk("getting entry info");
1055 +
1056 +       strlcpy(info->name, name, IP6T_TABLE_MAXNAMELEN);
1057 +       ret = nf_getsockopt(NULL, PF_INET, IP6T_SO_GET_INFO, (char *)info, &sz);
1058 +       switch (ret) {
1059 +               case 0:
1060 +                       break;
1061 +               case -ENOENT:
1062 +                       /* table is gone */
1063 +                       ip6t_exp_remove_table(name);
1064 +                       break;
1065 +               default:
1066 +                       dprintk("error getting ip6tables info");
1067 +                       break;
1068 +       }
1069 +
1070 +       return ret;
1071 +}
1072 +
1073 +/**
1074 + * get the entries for a table
1075 + * @param info the location of info about the table
1076 + * @param entries the location to allocate and store the retrieved entries
1077 + * @return zero on success, non-zero otherwise
1078 + */
1079 +static int
1080 +ip6t_exp_get_entries(struct ip6t_getinfo *info, struct ip6t_get_entries *entries)
1081 +{
1082 +       int ret = 0;
1083 +       int sz = sizeof(struct ip6t_get_entries) + info->size;
1084 +
1085 +       dprintk("getting existing entries");
1086 +
1087 +       strlcpy(entries->name, info->name, IP6T_TABLE_MAXNAMELEN);
1088 +       entries->size = info->size;
1089 +       ret = nf_getsockopt(NULL, PF_INET,
1090 +                       IP6T_SO_GET_ENTRIES, (char *)entries, &sz);
1091 +       if (ret)
1092 +               dprintk("error getting ip6tables entries");
1093 +
1094 +       return ret;
1095 +}
1096 +
1097 +/**
1098 + * iterate over a tables entries, copying entries which
1099 + * are not expired to the replacement table
1100 + * @param info the location of info about the table
1101 + * @param entries the location of the table entries
1102 + * @param replace the location to allocate and store the replacement entries
1103 + * @return zero on success, non-zero otherwise
1104 + */
1105 +static int
1106 +ip6t_exp_get_active(struct ip6t_getinfo *info,
1107 +               struct ip6t_get_entries *entries, struct ip6t_replace *replace)
1108 +{
1109 +       dprintk("copying active entries");
1110 +
1111 +       /* copy stuff */
1112 +       strlcpy(replace->name, info->name, IP6T_TABLE_MAXNAMELEN);
1113 +       memcpy(replace->hook_entry, info->hook_entry, sizeof(info->hook_entry));
1114 +       memcpy(replace->underflow, info->underflow, sizeof(info->underflow));
1115 +       replace->valid_hooks = info->valid_hooks;
1116 +       replace->num_counters = info->num_entries;
1117 +
1118 +       /* set size and entry count */
1119 +       replace->size = 0;
1120 +       replace->num_entries = 0;
1121 +
1122 +       return IP6T_ENTRY_ITERATE(entries->entrytable, entries->size, 
1123 +                                       ip6t_exp_copy_active, replace);
1124 +}
1125 +
1126 +/**
1127 + * copy a table entry if it is not expired
1128 + * @param entry the source entry
1129 + * @param replace the replacement table
1130 + * @return zero;
1131 + */
1132 +static int
1133 +ip6t_exp_copy_active(struct ip6t_entry *entry, struct ip6t_replace *replace)
1134 +{
1135 +       if (!(IP6T_MATCH_ITERATE(entry, ip6t_exp_is_expired))) {
1136 +               struct ip6t_entry *dest =
1137 +                               (void *)replace->entries + replace->size;
1138 +               memcpy(dest, entry, entry->next_offset);
1139 +               replace->size += entry->next_offset;
1140 +               replace->num_entries++;
1141 +       }
1142 +
1143 +       return 0;
1144 +}
1145 +
1146 +/**
1147 + * determine if an entry is expired
1148 + * @param match the entry match to check for expiration
1149 + * @return non-zero for expired entries, zero otherwise
1150 + */
1151 +static int
1152 +ip6t_exp_is_expired(struct ip6t_entry_match *match)
1153 +{
1154 +       if (strcmp(match->u.user.name, "expire") == 0) {
1155 +               struct ip6t_exp_info *info = (struct ip6t_exp_info *)match->data;
1156 +               if (info->expiration <= get_seconds())
1157 +                       return 1;
1158 +       }
1159 +       return 0;
1160 +}
1161 +
1162 +/**
1163 + * update a table
1164 + * @param replace the replacement table
1165 + * @return zero on success, non-zero otherwise
1166 + */
1167 +static int
1168 +ip6t_exp_replace_expired(struct ip6t_replace *replace)
1169 +{
1170 +       int ret = 0;
1171 +       int sz = sizeof(struct ip6t_replace) + replace->size;
1172 +
1173 +       dprintk("replacing table %s", replace->name);
1174 +
1175 +       ret = nf_setsockopt(NULL, PF_INET,
1176 +                       IP6T_SO_SET_REPLACE, (char *)replace, sz);
1177 +       /*
1178 +        * FIXME remove this verbosity once tested?
1179 +        */
1180 +       switch (ret) {
1181 +               case 0:
1182 +                       break;
1183 +               case -EFAULT:
1184 +                       dprintk("EFAULT replacing ip6tables");
1185 +                       break;
1186 +               case -ENOPROTOOPT:
1187 +                       dprintk("ENOPROTOOPT replacing ip6tables");
1188 +                       break;
1189 +               case -ENOMEM:
1190 +                       dprintk("ENOMEM replacing ip6tables");
1191 +                       break;
1192 +               case -ENOENT:
1193 +                       dprintk("ENOENT replacing ip6tables");
1194 +                       break;
1195 +               case -ELOOP:
1196 +                       dprintk("ELOOP replacing ip6tables");
1197 +                       break;
1198 +               case -EINVAL:
1199 +                       dprintk("EINVAL replacing ip6tables");
1200 +                       break;
1201 +               default:
1202 +                       dprintk("unknown error (%d) replacing ip6tables", ret);
1203 +                       break;
1204 +       }
1205 +       return ret;
1206 +}
1207 +
1208 +/**
1209 + * get counters for unexpired entries
1210 + * @param entries the entries info
1211 + * @param replace the replacement structure, containing the old counters
1212 + * @param counters the new counter info
1213 + * @return zero on success, non-zero on failure
1214 + */
1215 +static int
1216 +ip6t_exp_get_counters(struct ip6t_get_entries *entries,
1217 +               struct ip6t_replace *replace,
1218 +               struct ip6t_counters_info *counters)
1219 +{
1220 +       int index = 0;
1221 +       dprintk("copying active counters");
1222 +
1223 +       /* init stuff */
1224 +       strlcpy(counters->name, replace->name, IP6T_TABLE_MAXNAMELEN);
1225 +       counters->num_counters = 0;
1226 +
1227 +       return IP6T_ENTRY_ITERATE(entries->entrytable, entries->size, 
1228 +                       ip6t_exp_copy_counter, replace, counters, &index);
1229 +}
1230 +
1231 +/**
1232 + * copy a rule counter if the rule is still active
1233 + * @param entry the entry
1234 + * @param replace the replacement structure containing the old counters
1235 + * @param counter the new counter info
1236 + * @param index the current entry index
1237 + * @return zero
1238 + */
1239 +static int
1240 +ip6t_exp_copy_counter(struct ip6t_entry *entry, struct ip6t_replace *replace,
1241 +               struct ip6t_counters_info *counters, int *index)
1242 +{
1243 +       if (!(IP6T_MATCH_ITERATE(entry, ip6t_exp_is_expired)))
1244 +               counters->counters[counters->num_counters++] =
1245 +                               replace->counters[*index];
1246 +       (*index)++;
1247 +       return 0;
1248 +}
1249 +
1250 +/**
1251 + * restore the counters for a table
1252 + * @param counter the counters
1253 + * @return zero on success, non-zero otherwise
1254 + */
1255 +static int
1256 +ip6t_exp_restore_counters(struct ip6t_counters_info *counters)
1257 +{
1258 +       int ret = 0;
1259 +       int sz = sizeof(struct ip6t_counters_info) +
1260 +                       sizeof(struct ip6t_counters) * counters->num_counters;
1261 +
1262 +       dprintk("restoring counters for %s", counters->name);
1263 +
1264 +       ret = nf_setsockopt(NULL, PF_INET,
1265 +                       IP6T_SO_SET_ADD_COUNTERS, (char *)counters, sz);
1266 +       if (ret)
1267 +               dprintk("error restoring counters (%d)", ret);
1268 +       return ret;
1269 +}
This page took 0.269108 seconds and 3 git commands to generate.