aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-02-24 21:23:37 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-24 21:23:37 -0500
commit54831a83bfe656c4c54e287c734c6b0ccaa3719b (patch)
treeabd5bef16d1a6011f629a36d4e245a2ed4f3df3c
parentfb977e2ca607a7e74946a1de798f474d1b80b9d6 (diff)
parent0f234214d15fa914436d304ecf5c3e43449e79f9 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
-rw-r--r--include/linux/netfilter/x_tables.h17
-rw-r--r--include/linux/netfilter_arp/arp_tables.h10
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h15
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h14
-rw-r--r--net/ipv4/netfilter/arp_tables.c301
-rw-r--r--net/ipv4/netfilter/ip_tables.c436
-rw-r--r--net/ipv6/netfilter/ip6_tables.c436
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c8
-rw-r--r--net/netfilter/xt_TCPMSS.c12
-rw-r--r--net/netfilter/xt_recent.c4
10 files changed, 597 insertions, 656 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index a18119fb88f0..84c7c928e9eb 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -120,6 +120,7 @@ struct xt_counters_info {
120 120
121#define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ 121#define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */
122 122
123#ifndef __KERNEL__
123/* fn returns 0 to continue iteration */ 124/* fn returns 0 to continue iteration */
124#define XT_MATCH_ITERATE(type, e, fn, args...) \ 125#define XT_MATCH_ITERATE(type, e, fn, args...) \
125({ \ 126({ \
@@ -163,6 +164,22 @@ struct xt_counters_info {
163#define XT_ENTRY_ITERATE(type, entries, size, fn, args...) \ 164#define XT_ENTRY_ITERATE(type, entries, size, fn, args...) \
164 XT_ENTRY_ITERATE_CONTINUE(type, entries, size, 0, fn, args) 165 XT_ENTRY_ITERATE_CONTINUE(type, entries, size, 0, fn, args)
165 166
167#endif /* !__KERNEL__ */
168
169/* pos is normally a struct ipt_entry/ip6t_entry/etc. */
170#define xt_entry_foreach(pos, ehead, esize) \
171 for ((pos) = (typeof(pos))(ehead); \
172 (pos) < (typeof(pos))((char *)(ehead) + (esize)); \
173 (pos) = (typeof(pos))((char *)(pos) + (pos)->next_offset))
174
175/* can only be xt_entry_match, so no use of typeof here */
176#define xt_ematch_foreach(pos, entry) \
177 for ((pos) = (struct xt_entry_match *)entry->elems; \
178 (pos) < (struct xt_entry_match *)((char *)(entry) + \
179 (entry)->target_offset); \
180 (pos) = (struct xt_entry_match *)((char *)(pos) + \
181 (pos)->u.match_size))
182
166#ifdef __KERNEL__ 183#ifdef __KERNEL__
167 184
168#include <linux/netdevice.h> 185#include <linux/netdevice.h>
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 0b33980611b2..e9948c0560f6 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -211,9 +211,11 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e
211 return (void *)e + e->target_offset; 211 return (void *)e + e->target_offset;
212} 212}
213 213
214#ifndef __KERNEL__
214/* fn returns 0 to continue iteration */ 215/* fn returns 0 to continue iteration */
215#define ARPT_ENTRY_ITERATE(entries, size, fn, args...) \ 216#define ARPT_ENTRY_ITERATE(entries, size, fn, args...) \
216 XT_ENTRY_ITERATE(struct arpt_entry, entries, size, fn, ## args) 217 XT_ENTRY_ITERATE(struct arpt_entry, entries, size, fn, ## args)
218#endif
217 219
218/* 220/*
219 * Main firewall chains definitions and global var's definitions. 221 * Main firewall chains definitions and global var's definitions.
@@ -291,14 +293,6 @@ compat_arpt_get_target(struct compat_arpt_entry *e)
291 293
292#define COMPAT_ARPT_ALIGN(s) COMPAT_XT_ALIGN(s) 294#define COMPAT_ARPT_ALIGN(s) COMPAT_XT_ALIGN(s)
293 295
294/* fn returns 0 to continue iteration */
295#define COMPAT_ARPT_ENTRY_ITERATE(entries, size, fn, args...) \
296 XT_ENTRY_ITERATE(struct compat_arpt_entry, entries, size, fn, ## args)
297
298#define COMPAT_ARPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
299 XT_ENTRY_ITERATE_CONTINUE(struct compat_arpt_entry, entries, size, n, \
300 fn, ## args)
301
302#endif /* CONFIG_COMPAT */ 296#endif /* CONFIG_COMPAT */
303#endif /*__KERNEL__*/ 297#endif /*__KERNEL__*/
304#endif /* _ARPTABLES_H */ 298#endif /* _ARPTABLES_H */
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 364973b42133..704a7b6e8169 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -223,6 +223,7 @@ ipt_get_target(struct ipt_entry *e)
223 return (void *)e + e->target_offset; 223 return (void *)e + e->target_offset;
224} 224}
225 225
226#ifndef __KERNEL__
226/* fn returns 0 to continue iteration */ 227/* fn returns 0 to continue iteration */
227#define IPT_MATCH_ITERATE(e, fn, args...) \ 228#define IPT_MATCH_ITERATE(e, fn, args...) \
228 XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args) 229 XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)
@@ -230,6 +231,7 @@ ipt_get_target(struct ipt_entry *e)
230/* fn returns 0 to continue iteration */ 231/* fn returns 0 to continue iteration */
231#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ 232#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
232 XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args) 233 XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
234#endif
233 235
234/* 236/*
235 * Main firewall chains definitions and global var's definitions. 237 * Main firewall chains definitions and global var's definitions.
@@ -313,19 +315,6 @@ compat_ipt_get_target(struct compat_ipt_entry *e)
313 315
314#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s) 316#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s)
315 317
316/* fn returns 0 to continue iteration */
317#define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \
318 XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args)
319
320/* fn returns 0 to continue iteration */
321#define COMPAT_IPT_ENTRY_ITERATE(entries, size, fn, args...) \
322 XT_ENTRY_ITERATE(struct compat_ipt_entry, entries, size, fn, ## args)
323
324/* fn returns 0 to continue iteration */
325#define COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
326 XT_ENTRY_ITERATE_CONTINUE(struct compat_ipt_entry, entries, size, n, \
327 fn, ## args)
328
329#endif /* CONFIG_COMPAT */ 318#endif /* CONFIG_COMPAT */
330#endif /*__KERNEL__*/ 319#endif /*__KERNEL__*/
331#endif /* _IPTABLES_H */ 320#endif /* _IPTABLES_H */
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 8031eb486a10..e5ba03d783c6 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -280,6 +280,7 @@ ip6t_get_target(struct ip6t_entry *e)
280 return (void *)e + e->target_offset; 280 return (void *)e + e->target_offset;
281} 281}
282 282
283#ifndef __KERNEL__
283/* fn returns 0 to continue iteration */ 284/* fn returns 0 to continue iteration */
284#define IP6T_MATCH_ITERATE(e, fn, args...) \ 285#define IP6T_MATCH_ITERATE(e, fn, args...) \
285 XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args) 286 XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args)
@@ -287,6 +288,7 @@ ip6t_get_target(struct ip6t_entry *e)
287/* fn returns 0 to continue iteration */ 288/* fn returns 0 to continue iteration */
288#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ 289#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
289 XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args) 290 XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args)
291#endif
290 292
291/* 293/*
292 * Main firewall chains definitions and global var's definitions. 294 * Main firewall chains definitions and global var's definitions.
@@ -341,18 +343,6 @@ compat_ip6t_get_target(struct compat_ip6t_entry *e)
341 343
342#define COMPAT_IP6T_ALIGN(s) COMPAT_XT_ALIGN(s) 344#define COMPAT_IP6T_ALIGN(s) COMPAT_XT_ALIGN(s)
343 345
344/* fn returns 0 to continue iteration */
345#define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \
346 XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args)
347
348/* fn returns 0 to continue iteration */
349#define COMPAT_IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
350 XT_ENTRY_ITERATE(struct compat_ip6t_entry, entries, size, fn, ## args)
351
352#define COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
353 XT_ENTRY_ITERATE_CONTINUE(struct compat_ip6t_entry, entries, size, n, \
354 fn, ## args)
355
356#endif /* CONFIG_COMPAT */ 346#endif /* CONFIG_COMPAT */
357#endif /*__KERNEL__*/ 347#endif /*__KERNEL__*/
358#endif /* _IP6_TABLES_H */ 348#endif /* _IP6_TABLES_H */
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 4db5c1ece0f9..57098dcda294 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -512,8 +512,7 @@ static inline int check_target(struct arpt_entry *e, const char *name)
512} 512}
513 513
514static inline int 514static inline int
515find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, 515find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
516 unsigned int *i)
517{ 516{
518 struct arpt_entry_target *t; 517 struct arpt_entry_target *t;
519 struct xt_target *target; 518 struct xt_target *target;
@@ -538,8 +537,6 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
538 ret = check_target(e, name); 537 ret = check_target(e, name);
539 if (ret) 538 if (ret)
540 goto err; 539 goto err;
541
542 (*i)++;
543 return 0; 540 return 0;
544err: 541err:
545 module_put(t->u.kernel.target->me); 542 module_put(t->u.kernel.target->me);
@@ -568,8 +565,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
568 const unsigned char *limit, 565 const unsigned char *limit,
569 const unsigned int *hook_entries, 566 const unsigned int *hook_entries,
570 const unsigned int *underflows, 567 const unsigned int *underflows,
571 unsigned int valid_hooks, 568 unsigned int valid_hooks)
572 unsigned int *i)
573{ 569{
574 unsigned int h; 570 unsigned int h;
575 571
@@ -606,19 +602,14 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
606 /* Clear counters and comefrom */ 602 /* Clear counters and comefrom */
607 e->counters = ((struct xt_counters) { 0, 0 }); 603 e->counters = ((struct xt_counters) { 0, 0 });
608 e->comefrom = 0; 604 e->comefrom = 0;
609
610 (*i)++;
611 return 0; 605 return 0;
612} 606}
613 607
614static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) 608static inline void cleanup_entry(struct arpt_entry *e)
615{ 609{
616 struct xt_tgdtor_param par; 610 struct xt_tgdtor_param par;
617 struct arpt_entry_target *t; 611 struct arpt_entry_target *t;
618 612
619 if (i && (*i)-- == 0)
620 return 1;
621
622 t = arpt_get_target(e); 613 t = arpt_get_target(e);
623 par.target = t->u.kernel.target; 614 par.target = t->u.kernel.target;
624 par.targinfo = t->data; 615 par.targinfo = t->data;
@@ -626,26 +617,20 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i)
626 if (par.target->destroy != NULL) 617 if (par.target->destroy != NULL)
627 par.target->destroy(&par); 618 par.target->destroy(&par);
628 module_put(par.target->me); 619 module_put(par.target->me);
629 return 0;
630} 620}
631 621
632/* Checks and translates the user-supplied table segment (held in 622/* Checks and translates the user-supplied table segment (held in
633 * newinfo). 623 * newinfo).
634 */ 624 */
635static int translate_table(const char *name, 625static int translate_table(struct xt_table_info *newinfo, void *entry0,
636 unsigned int valid_hooks, 626 const struct arpt_replace *repl)
637 struct xt_table_info *newinfo,
638 void *entry0,
639 unsigned int size,
640 unsigned int number,
641 const unsigned int *hook_entries,
642 const unsigned int *underflows)
643{ 627{
628 struct arpt_entry *iter;
644 unsigned int i; 629 unsigned int i;
645 int ret; 630 int ret = 0;
646 631
647 newinfo->size = size; 632 newinfo->size = repl->size;
648 newinfo->number = number; 633 newinfo->number = repl->num_entries;
649 634
650 /* Init all hooks to impossible value. */ 635 /* Init all hooks to impossible value. */
651 for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 636 for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
@@ -657,52 +642,61 @@ static int translate_table(const char *name,
657 i = 0; 642 i = 0;
658 643
659 /* Walk through entries, checking offsets. */ 644 /* Walk through entries, checking offsets. */
660 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, 645 xt_entry_foreach(iter, entry0, newinfo->size) {
661 check_entry_size_and_hooks, 646 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
662 newinfo, 647 entry0 + repl->size, repl->hook_entry, repl->underflow,
663 entry0, 648 repl->valid_hooks);
664 entry0 + size, 649 if (ret != 0)
665 hook_entries, underflows, valid_hooks, &i); 650 break;
651 ++i;
652 }
666 duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); 653 duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret);
667 if (ret != 0) 654 if (ret != 0)
668 return ret; 655 return ret;
669 656
670 if (i != number) { 657 if (i != repl->num_entries) {
671 duprintf("translate_table: %u not %u entries\n", 658 duprintf("translate_table: %u not %u entries\n",
672 i, number); 659 i, repl->num_entries);
673 return -EINVAL; 660 return -EINVAL;
674 } 661 }
675 662
676 /* Check hooks all assigned */ 663 /* Check hooks all assigned */
677 for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 664 for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
678 /* Only hooks which are valid */ 665 /* Only hooks which are valid */
679 if (!(valid_hooks & (1 << i))) 666 if (!(repl->valid_hooks & (1 << i)))
680 continue; 667 continue;
681 if (newinfo->hook_entry[i] == 0xFFFFFFFF) { 668 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
682 duprintf("Invalid hook entry %u %u\n", 669 duprintf("Invalid hook entry %u %u\n",
683 i, hook_entries[i]); 670 i, repl->hook_entry[i]);
684 return -EINVAL; 671 return -EINVAL;
685 } 672 }
686 if (newinfo->underflow[i] == 0xFFFFFFFF) { 673 if (newinfo->underflow[i] == 0xFFFFFFFF) {
687 duprintf("Invalid underflow %u %u\n", 674 duprintf("Invalid underflow %u %u\n",
688 i, underflows[i]); 675 i, repl->underflow[i]);
689 return -EINVAL; 676 return -EINVAL;
690 } 677 }
691 } 678 }
692 679
693 if (!mark_source_chains(newinfo, valid_hooks, entry0)) { 680 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) {
694 duprintf("Looping hook\n"); 681 duprintf("Looping hook\n");
695 return -ELOOP; 682 return -ELOOP;
696 } 683 }
697 684
698 /* Finally, each sanity check must pass */ 685 /* Finally, each sanity check must pass */
699 i = 0; 686 i = 0;
700 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, 687 xt_entry_foreach(iter, entry0, newinfo->size) {
701 find_check_entry, name, size, &i); 688 ret = find_check_entry(iter, repl->name, repl->size);
689 if (ret != 0)
690 break;
691 ++i;
692 }
702 693
703 if (ret != 0) { 694 if (ret != 0) {
704 ARPT_ENTRY_ITERATE(entry0, newinfo->size, 695 xt_entry_foreach(iter, entry0, newinfo->size) {
705 cleanup_entry, &i); 696 if (i-- == 0)
697 break;
698 cleanup_entry(iter);
699 }
706 return ret; 700 return ret;
707 } 701 }
708 702
@@ -715,30 +709,10 @@ static int translate_table(const char *name,
715 return ret; 709 return ret;
716} 710}
717 711
718/* Gets counters. */
719static inline int add_entry_to_counter(const struct arpt_entry *e,
720 struct xt_counters total[],
721 unsigned int *i)
722{
723 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
724
725 (*i)++;
726 return 0;
727}
728
729static inline int set_entry_to_counter(const struct arpt_entry *e,
730 struct xt_counters total[],
731 unsigned int *i)
732{
733 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
734
735 (*i)++;
736 return 0;
737}
738
739static void get_counters(const struct xt_table_info *t, 712static void get_counters(const struct xt_table_info *t,
740 struct xt_counters counters[]) 713 struct xt_counters counters[])
741{ 714{
715 struct arpt_entry *iter;
742 unsigned int cpu; 716 unsigned int cpu;
743 unsigned int i; 717 unsigned int i;
744 unsigned int curcpu; 718 unsigned int curcpu;
@@ -754,22 +728,22 @@ static void get_counters(const struct xt_table_info *t,
754 curcpu = smp_processor_id(); 728 curcpu = smp_processor_id();
755 729
756 i = 0; 730 i = 0;
757 ARPT_ENTRY_ITERATE(t->entries[curcpu], 731 xt_entry_foreach(iter, t->entries[curcpu], t->size) {
758 t->size, 732 SET_COUNTER(counters[i], iter->counters.bcnt,
759 set_entry_to_counter, 733 iter->counters.pcnt);
760 counters, 734 ++i;
761 &i); 735 }
762 736
763 for_each_possible_cpu(cpu) { 737 for_each_possible_cpu(cpu) {
764 if (cpu == curcpu) 738 if (cpu == curcpu)
765 continue; 739 continue;
766 i = 0; 740 i = 0;
767 xt_info_wrlock(cpu); 741 xt_info_wrlock(cpu);
768 ARPT_ENTRY_ITERATE(t->entries[cpu], 742 xt_entry_foreach(iter, t->entries[cpu], t->size) {
769 t->size, 743 ADD_COUNTER(counters[i], iter->counters.bcnt,
770 add_entry_to_counter, 744 iter->counters.pcnt);
771 counters, 745 ++i;
772 &i); 746 }
773 xt_info_wrunlock(cpu); 747 xt_info_wrunlock(cpu);
774 } 748 }
775 local_bh_enable(); 749 local_bh_enable();
@@ -899,7 +873,9 @@ static int compat_calc_entry(const struct arpt_entry *e,
899static int compat_table_info(const struct xt_table_info *info, 873static int compat_table_info(const struct xt_table_info *info,
900 struct xt_table_info *newinfo) 874 struct xt_table_info *newinfo)
901{ 875{
876 struct arpt_entry *iter;
902 void *loc_cpu_entry; 877 void *loc_cpu_entry;
878 int ret;
903 879
904 if (!newinfo || !info) 880 if (!newinfo || !info)
905 return -EINVAL; 881 return -EINVAL;
@@ -908,9 +884,12 @@ static int compat_table_info(const struct xt_table_info *info,
908 memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); 884 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
909 newinfo->initial_entries = 0; 885 newinfo->initial_entries = 0;
910 loc_cpu_entry = info->entries[raw_smp_processor_id()]; 886 loc_cpu_entry = info->entries[raw_smp_processor_id()];
911 return ARPT_ENTRY_ITERATE(loc_cpu_entry, info->size, 887 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
912 compat_calc_entry, info, loc_cpu_entry, 888 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
913 newinfo); 889 if (ret != 0)
890 return ret;
891 }
892 return 0;
914} 893}
915#endif 894#endif
916 895
@@ -1025,6 +1004,7 @@ static int __do_replace(struct net *net, const char *name,
1025 struct xt_table_info *oldinfo; 1004 struct xt_table_info *oldinfo;
1026 struct xt_counters *counters; 1005 struct xt_counters *counters;
1027 void *loc_cpu_old_entry; 1006 void *loc_cpu_old_entry;
1007 struct arpt_entry *iter;
1028 1008
1029 ret = 0; 1009 ret = 0;
1030 counters = vmalloc_node(num_counters * sizeof(struct xt_counters), 1010 counters = vmalloc_node(num_counters * sizeof(struct xt_counters),
@@ -1068,8 +1048,8 @@ static int __do_replace(struct net *net, const char *name,
1068 1048
1069 /* Decrease module usage counts and free resource */ 1049 /* Decrease module usage counts and free resource */
1070 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1050 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1071 ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, 1051 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1072 NULL); 1052 cleanup_entry(iter);
1073 1053
1074 xt_free_table_info(oldinfo); 1054 xt_free_table_info(oldinfo);
1075 if (copy_to_user(counters_ptr, counters, 1055 if (copy_to_user(counters_ptr, counters,
@@ -1095,6 +1075,7 @@ static int do_replace(struct net *net, const void __user *user,
1095 struct arpt_replace tmp; 1075 struct arpt_replace tmp;
1096 struct xt_table_info *newinfo; 1076 struct xt_table_info *newinfo;
1097 void *loc_cpu_entry; 1077 void *loc_cpu_entry;
1078 struct arpt_entry *iter;
1098 1079
1099 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1080 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1100 return -EFAULT; 1081 return -EFAULT;
@@ -1115,9 +1096,7 @@ static int do_replace(struct net *net, const void __user *user,
1115 goto free_newinfo; 1096 goto free_newinfo;
1116 } 1097 }
1117 1098
1118 ret = translate_table(tmp.name, tmp.valid_hooks, 1099 ret = translate_table(newinfo, loc_cpu_entry, &tmp);
1119 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1120 tmp.hook_entry, tmp.underflow);
1121 if (ret != 0) 1100 if (ret != 0)
1122 goto free_newinfo; 1101 goto free_newinfo;
1123 1102
@@ -1130,25 +1109,13 @@ static int do_replace(struct net *net, const void __user *user,
1130 return 0; 1109 return 0;
1131 1110
1132 free_newinfo_untrans: 1111 free_newinfo_untrans:
1133 ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 1112 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1113 cleanup_entry(iter);
1134 free_newinfo: 1114 free_newinfo:
1135 xt_free_table_info(newinfo); 1115 xt_free_table_info(newinfo);
1136 return ret; 1116 return ret;
1137} 1117}
1138 1118
1139/* We're lazy, and add to the first CPU; overflow works its fey magic
1140 * and everything is OK. */
1141static int
1142add_counter_to_entry(struct arpt_entry *e,
1143 const struct xt_counters addme[],
1144 unsigned int *i)
1145{
1146 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1147
1148 (*i)++;
1149 return 0;
1150}
1151
1152static int do_add_counters(struct net *net, const void __user *user, 1119static int do_add_counters(struct net *net, const void __user *user,
1153 unsigned int len, int compat) 1120 unsigned int len, int compat)
1154{ 1121{
@@ -1163,6 +1130,7 @@ static int do_add_counters(struct net *net, const void __user *user,
1163 const struct xt_table_info *private; 1130 const struct xt_table_info *private;
1164 int ret = 0; 1131 int ret = 0;
1165 void *loc_cpu_entry; 1132 void *loc_cpu_entry;
1133 struct arpt_entry *iter;
1166#ifdef CONFIG_COMPAT 1134#ifdef CONFIG_COMPAT
1167 struct compat_xt_counters_info compat_tmp; 1135 struct compat_xt_counters_info compat_tmp;
1168 1136
@@ -1220,11 +1188,10 @@ static int do_add_counters(struct net *net, const void __user *user,
1220 curcpu = smp_processor_id(); 1188 curcpu = smp_processor_id();
1221 loc_cpu_entry = private->entries[curcpu]; 1189 loc_cpu_entry = private->entries[curcpu];
1222 xt_info_wrlock(curcpu); 1190 xt_info_wrlock(curcpu);
1223 ARPT_ENTRY_ITERATE(loc_cpu_entry, 1191 xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1224 private->size, 1192 ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
1225 add_counter_to_entry, 1193 ++i;
1226 paddc, 1194 }
1227 &i);
1228 xt_info_wrunlock(curcpu); 1195 xt_info_wrunlock(curcpu);
1229 unlock_up_free: 1196 unlock_up_free:
1230 local_bh_enable(); 1197 local_bh_enable();
@@ -1237,17 +1204,12 @@ static int do_add_counters(struct net *net, const void __user *user,
1237} 1204}
1238 1205
1239#ifdef CONFIG_COMPAT 1206#ifdef CONFIG_COMPAT
1240static inline int 1207static inline void compat_release_entry(struct compat_arpt_entry *e)
1241compat_release_entry(struct compat_arpt_entry *e, unsigned int *i)
1242{ 1208{
1243 struct arpt_entry_target *t; 1209 struct arpt_entry_target *t;
1244 1210
1245 if (i && (*i)-- == 0)
1246 return 1;
1247
1248 t = compat_arpt_get_target(e); 1211 t = compat_arpt_get_target(e);
1249 module_put(t->u.kernel.target->me); 1212 module_put(t->u.kernel.target->me);
1250 return 0;
1251} 1213}
1252 1214
1253static inline int 1215static inline int
@@ -1258,7 +1220,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
1258 const unsigned char *limit, 1220 const unsigned char *limit,
1259 const unsigned int *hook_entries, 1221 const unsigned int *hook_entries,
1260 const unsigned int *underflows, 1222 const unsigned int *underflows,
1261 unsigned int *i,
1262 const char *name) 1223 const char *name)
1263{ 1224{
1264 struct arpt_entry_target *t; 1225 struct arpt_entry_target *t;
@@ -1318,8 +1279,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
1318 /* Clear counters and comefrom */ 1279 /* Clear counters and comefrom */
1319 memset(&e->counters, 0, sizeof(e->counters)); 1280 memset(&e->counters, 0, sizeof(e->counters));
1320 e->comefrom = 0; 1281 e->comefrom = 0;
1321
1322 (*i)++;
1323 return 0; 1282 return 0;
1324 1283
1325release_target: 1284release_target:
@@ -1363,19 +1322,6 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
1363 return ret; 1322 return ret;
1364} 1323}
1365 1324
1366static inline int compat_check_entry(struct arpt_entry *e, const char *name,
1367 unsigned int *i)
1368{
1369 int ret;
1370
1371 ret = check_target(e, name);
1372 if (ret)
1373 return ret;
1374
1375 (*i)++;
1376 return 0;
1377}
1378
1379static int translate_compat_table(const char *name, 1325static int translate_compat_table(const char *name,
1380 unsigned int valid_hooks, 1326 unsigned int valid_hooks,
1381 struct xt_table_info **pinfo, 1327 struct xt_table_info **pinfo,
@@ -1388,8 +1334,10 @@ static int translate_compat_table(const char *name,
1388 unsigned int i, j; 1334 unsigned int i, j;
1389 struct xt_table_info *newinfo, *info; 1335 struct xt_table_info *newinfo, *info;
1390 void *pos, *entry0, *entry1; 1336 void *pos, *entry0, *entry1;
1337 struct compat_arpt_entry *iter0;
1338 struct arpt_entry *iter1;
1391 unsigned int size; 1339 unsigned int size;
1392 int ret; 1340 int ret = 0;
1393 1341
1394 info = *pinfo; 1342 info = *pinfo;
1395 entry0 = *pentry0; 1343 entry0 = *pentry0;
@@ -1406,13 +1354,14 @@ static int translate_compat_table(const char *name,
1406 j = 0; 1354 j = 0;
1407 xt_compat_lock(NFPROTO_ARP); 1355 xt_compat_lock(NFPROTO_ARP);
1408 /* Walk through entries, checking offsets. */ 1356 /* Walk through entries, checking offsets. */
1409 ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, 1357 xt_entry_foreach(iter0, entry0, total_size) {
1410 check_compat_entry_size_and_hooks, 1358 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1411 info, &size, entry0, 1359 entry0, entry0 + total_size, hook_entries, underflows,
1412 entry0 + total_size, 1360 name);
1413 hook_entries, underflows, &j, name); 1361 if (ret != 0)
1414 if (ret != 0) 1362 goto out_unlock;
1415 goto out_unlock; 1363 ++j;
1364 }
1416 1365
1417 ret = -EINVAL; 1366 ret = -EINVAL;
1418 if (j != number) { 1367 if (j != number) {
@@ -1451,9 +1400,12 @@ static int translate_compat_table(const char *name,
1451 entry1 = newinfo->entries[raw_smp_processor_id()]; 1400 entry1 = newinfo->entries[raw_smp_processor_id()];
1452 pos = entry1; 1401 pos = entry1;
1453 size = total_size; 1402 size = total_size;
1454 ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, 1403 xt_entry_foreach(iter0, entry0, total_size) {
1455 compat_copy_entry_from_user, 1404 ret = compat_copy_entry_from_user(iter0, &pos,
1456 &pos, &size, name, newinfo, entry1); 1405 &size, name, newinfo, entry1);
1406 if (ret != 0)
1407 break;
1408 }
1457 xt_compat_flush_offsets(NFPROTO_ARP); 1409 xt_compat_flush_offsets(NFPROTO_ARP);
1458 xt_compat_unlock(NFPROTO_ARP); 1410 xt_compat_unlock(NFPROTO_ARP);
1459 if (ret) 1411 if (ret)
@@ -1464,13 +1416,32 @@ static int translate_compat_table(const char *name,
1464 goto free_newinfo; 1416 goto free_newinfo;
1465 1417
1466 i = 0; 1418 i = 0;
1467 ret = ARPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, 1419 xt_entry_foreach(iter1, entry1, newinfo->size) {
1468 name, &i); 1420 ret = check_target(iter1, name);
1421 if (ret != 0)
1422 break;
1423 ++i;
1424 }
1469 if (ret) { 1425 if (ret) {
1426 /*
1427 * The first i matches need cleanup_entry (calls ->destroy)
1428 * because they had called ->check already. The other j-i
1429 * entries need only release.
1430 */
1431 int skip = i;
1470 j -= i; 1432 j -= i;
1471 COMPAT_ARPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, 1433 xt_entry_foreach(iter0, entry0, newinfo->size) {
1472 compat_release_entry, &j); 1434 if (skip-- > 0)
1473 ARPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); 1435 continue;
1436 if (j-- == 0)
1437 break;
1438 compat_release_entry(iter0);
1439 }
1440 xt_entry_foreach(iter1, entry1, newinfo->size) {
1441 if (i-- == 0)
1442 break;
1443 cleanup_entry(iter1);
1444 }
1474 xt_free_table_info(newinfo); 1445 xt_free_table_info(newinfo);
1475 return ret; 1446 return ret;
1476 } 1447 }
@@ -1488,7 +1459,11 @@ static int translate_compat_table(const char *name,
1488free_newinfo: 1459free_newinfo:
1489 xt_free_table_info(newinfo); 1460 xt_free_table_info(newinfo);
1490out: 1461out:
1491 COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); 1462 xt_entry_foreach(iter0, entry0, total_size) {
1463 if (j-- == 0)
1464 break;
1465 compat_release_entry(iter0);
1466 }
1492 return ret; 1467 return ret;
1493out_unlock: 1468out_unlock:
1494 xt_compat_flush_offsets(NFPROTO_ARP); 1469 xt_compat_flush_offsets(NFPROTO_ARP);
@@ -1515,6 +1490,7 @@ static int compat_do_replace(struct net *net, void __user *user,
1515 struct compat_arpt_replace tmp; 1490 struct compat_arpt_replace tmp;
1516 struct xt_table_info *newinfo; 1491 struct xt_table_info *newinfo;
1517 void *loc_cpu_entry; 1492 void *loc_cpu_entry;
1493 struct arpt_entry *iter;
1518 1494
1519 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1495 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1520 return -EFAULT; 1496 return -EFAULT;
@@ -1552,7 +1528,8 @@ static int compat_do_replace(struct net *net, void __user *user,
1552 return 0; 1528 return 0;
1553 1529
1554 free_newinfo_untrans: 1530 free_newinfo_untrans:
1555 ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 1531 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1532 cleanup_entry(iter);
1556 free_newinfo: 1533 free_newinfo:
1557 xt_free_table_info(newinfo); 1534 xt_free_table_info(newinfo);
1558 return ret; 1535 return ret;
@@ -1586,7 +1563,7 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user,
1586static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr, 1563static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr,
1587 compat_uint_t *size, 1564 compat_uint_t *size,
1588 struct xt_counters *counters, 1565 struct xt_counters *counters,
1589 unsigned int *i) 1566 unsigned int i)
1590{ 1567{
1591 struct arpt_entry_target *t; 1568 struct arpt_entry_target *t;
1592 struct compat_arpt_entry __user *ce; 1569 struct compat_arpt_entry __user *ce;
@@ -1594,14 +1571,12 @@ static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr,
1594 compat_uint_t origsize; 1571 compat_uint_t origsize;
1595 int ret; 1572 int ret;
1596 1573
1597 ret = -EFAULT;
1598 origsize = *size; 1574 origsize = *size;
1599 ce = (struct compat_arpt_entry __user *)*dstptr; 1575 ce = (struct compat_arpt_entry __user *)*dstptr;
1600 if (copy_to_user(ce, e, sizeof(struct arpt_entry))) 1576 if (copy_to_user(ce, e, sizeof(struct arpt_entry)) != 0 ||
1601 goto out; 1577 copy_to_user(&ce->counters, &counters[i],
1602 1578 sizeof(counters[i])) != 0)
1603 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i]))) 1579 return -EFAULT;
1604 goto out;
1605 1580
1606 *dstptr += sizeof(struct compat_arpt_entry); 1581 *dstptr += sizeof(struct compat_arpt_entry);
1607 *size -= sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); 1582 *size -= sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry);
@@ -1611,18 +1586,12 @@ static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr,
1611 t = arpt_get_target(e); 1586 t = arpt_get_target(e);
1612 ret = xt_compat_target_to_user(t, dstptr, size); 1587 ret = xt_compat_target_to_user(t, dstptr, size);
1613 if (ret) 1588 if (ret)
1614 goto out; 1589 return ret;
1615 ret = -EFAULT;
1616 next_offset = e->next_offset - (origsize - *size); 1590 next_offset = e->next_offset - (origsize - *size);
1617 if (put_user(target_offset, &ce->target_offset)) 1591 if (put_user(target_offset, &ce->target_offset) != 0 ||
1618 goto out; 1592 put_user(next_offset, &ce->next_offset) != 0)
1619 if (put_user(next_offset, &ce->next_offset)) 1593 return -EFAULT;
1620 goto out;
1621
1622 (*i)++;
1623 return 0; 1594 return 0;
1624out:
1625 return ret;
1626} 1595}
1627 1596
1628static int compat_copy_entries_to_user(unsigned int total_size, 1597static int compat_copy_entries_to_user(unsigned int total_size,
@@ -1636,6 +1605,7 @@ static int compat_copy_entries_to_user(unsigned int total_size,
1636 int ret = 0; 1605 int ret = 0;
1637 void *loc_cpu_entry; 1606 void *loc_cpu_entry;
1638 unsigned int i = 0; 1607 unsigned int i = 0;
1608 struct arpt_entry *iter;
1639 1609
1640 counters = alloc_counters(table); 1610 counters = alloc_counters(table);
1641 if (IS_ERR(counters)) 1611 if (IS_ERR(counters))
@@ -1645,9 +1615,12 @@ static int compat_copy_entries_to_user(unsigned int total_size,
1645 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 1615 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1646 pos = userptr; 1616 pos = userptr;
1647 size = total_size; 1617 size = total_size;
1648 ret = ARPT_ENTRY_ITERATE(loc_cpu_entry, total_size, 1618 xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1649 compat_copy_entry_to_user, 1619 ret = compat_copy_entry_to_user(iter, &pos,
1650 &pos, &size, counters, &i); 1620 &size, counters, i++);
1621 if (ret != 0)
1622 break;
1623 }
1651 vfree(counters); 1624 vfree(counters);
1652 return ret; 1625 return ret;
1653} 1626}
@@ -1815,12 +1788,7 @@ struct xt_table *arpt_register_table(struct net *net,
1815 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; 1788 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1816 memcpy(loc_cpu_entry, repl->entries, repl->size); 1789 memcpy(loc_cpu_entry, repl->entries, repl->size);
1817 1790
1818 ret = translate_table(table->name, table->valid_hooks, 1791 ret = translate_table(newinfo, loc_cpu_entry, repl);
1819 newinfo, loc_cpu_entry, repl->size,
1820 repl->num_entries,
1821 repl->hook_entry,
1822 repl->underflow);
1823
1824 duprintf("arpt_register_table: translate table gives %d\n", ret); 1792 duprintf("arpt_register_table: translate table gives %d\n", ret);
1825 if (ret != 0) 1793 if (ret != 0)
1826 goto out_free; 1794 goto out_free;
@@ -1843,13 +1811,14 @@ void arpt_unregister_table(struct xt_table *table)
1843 struct xt_table_info *private; 1811 struct xt_table_info *private;
1844 void *loc_cpu_entry; 1812 void *loc_cpu_entry;
1845 struct module *table_owner = table->me; 1813 struct module *table_owner = table->me;
1814 struct arpt_entry *iter;
1846 1815
1847 private = xt_unregister_table(table); 1816 private = xt_unregister_table(table);
1848 1817
1849 /* Decrease module usage counts and free resources */ 1818 /* Decrease module usage counts and free resources */
1850 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 1819 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1851 ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size, 1820 xt_entry_foreach(iter, loc_cpu_entry, private->size)
1852 cleanup_entry, NULL); 1821 cleanup_entry(iter);
1853 if (private->number > private->initial_entries) 1822 if (private->number > private->initial_entries)
1854 module_put(table_owner); 1823 module_put(table_owner);
1855 xt_free_table_info(private); 1824 xt_free_table_info(private);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index e94c18bdfc68..c92f4e541cf6 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -288,6 +288,7 @@ static void trace_packet(const struct sk_buff *skb,
288 const void *table_base; 288 const void *table_base;
289 const struct ipt_entry *root; 289 const struct ipt_entry *root;
290 const char *hookname, *chainname, *comment; 290 const char *hookname, *chainname, *comment;
291 const struct ipt_entry *iter;
291 unsigned int rulenum = 0; 292 unsigned int rulenum = 0;
292 293
293 table_base = private->entries[smp_processor_id()]; 294 table_base = private->entries[smp_processor_id()];
@@ -296,10 +297,10 @@ static void trace_packet(const struct sk_buff *skb,
296 hookname = chainname = hooknames[hook]; 297 hookname = chainname = hooknames[hook];
297 comment = comments[NF_IP_TRACE_COMMENT_RULE]; 298 comment = comments[NF_IP_TRACE_COMMENT_RULE];
298 299
299 IPT_ENTRY_ITERATE(root, 300 xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
300 private->size - private->hook_entry[hook], 301 if (get_chainname_rulenum(iter, e, hookname,
301 get_chainname_rulenum, 302 &chainname, &comment, &rulenum) != 0)
302 e, hookname, &chainname, &comment, &rulenum); 303 break;
303 304
304 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo, 305 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
305 "TRACE: %s:%s:%s:%u ", 306 "TRACE: %s:%s:%s:%u ",
@@ -365,16 +366,21 @@ ipt_do_table(struct sk_buff *skb,
365 366
366 do { 367 do {
367 const struct ipt_entry_target *t; 368 const struct ipt_entry_target *t;
369 const struct xt_entry_match *ematch;
368 370
369 IP_NF_ASSERT(e); 371 IP_NF_ASSERT(e);
370 IP_NF_ASSERT(back); 372 IP_NF_ASSERT(back);
371 if (!ip_packet_match(ip, indev, outdev, 373 if (!ip_packet_match(ip, indev, outdev,
372 &e->ip, mtpar.fragoff) || 374 &e->ip, mtpar.fragoff)) {
373 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { 375 no_match:
374 e = ipt_next_entry(e); 376 e = ipt_next_entry(e);
375 continue; 377 continue;
376 } 378 }
377 379
380 xt_ematch_foreach(ematch, e)
381 if (do_match(ematch, skb, &mtpar) != 0)
382 goto no_match;
383
378 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); 384 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
379 385
380 t = ipt_get_target(e); 386 t = ipt_get_target(e);
@@ -566,14 +572,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
566 return 1; 572 return 1;
567} 573}
568 574
569static int 575static void cleanup_match(struct ipt_entry_match *m, struct net *net)
570cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i)
571{ 576{
572 struct xt_mtdtor_param par; 577 struct xt_mtdtor_param par;
573 578
574 if (i && (*i)-- == 0)
575 return 1;
576
577 par.net = net; 579 par.net = net;
578 par.match = m->u.kernel.match; 580 par.match = m->u.kernel.match;
579 par.matchinfo = m->data; 581 par.matchinfo = m->data;
@@ -581,7 +583,6 @@ cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i)
581 if (par.match->destroy != NULL) 583 if (par.match->destroy != NULL)
582 par.match->destroy(&par); 584 par.match->destroy(&par);
583 module_put(par.match->me); 585 module_put(par.match->me);
584 return 0;
585} 586}
586 587
587static int 588static int
@@ -606,8 +607,7 @@ check_entry(const struct ipt_entry *e, const char *name)
606} 607}
607 608
608static int 609static int
609check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, 610check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
610 unsigned int *i)
611{ 611{
612 const struct ipt_ip *ip = par->entryinfo; 612 const struct ipt_ip *ip = par->entryinfo;
613 int ret; 613 int ret;
@@ -622,13 +622,11 @@ check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
622 par.match->name); 622 par.match->name);
623 return ret; 623 return ret;
624 } 624 }
625 ++*i;
626 return 0; 625 return 0;
627} 626}
628 627
629static int 628static int
630find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, 629find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
631 unsigned int *i)
632{ 630{
633 struct xt_match *match; 631 struct xt_match *match;
634 int ret; 632 int ret;
@@ -642,7 +640,7 @@ find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
642 } 640 }
643 m->u.kernel.match = match; 641 m->u.kernel.match = match;
644 642
645 ret = check_match(m, par, i); 643 ret = check_match(m, par);
646 if (ret) 644 if (ret)
647 goto err; 645 goto err;
648 646
@@ -678,13 +676,14 @@ static int check_target(struct ipt_entry *e, struct net *net, const char *name)
678 676
679static int 677static int
680find_check_entry(struct ipt_entry *e, struct net *net, const char *name, 678find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
681 unsigned int size, unsigned int *i) 679 unsigned int size)
682{ 680{
683 struct ipt_entry_target *t; 681 struct ipt_entry_target *t;
684 struct xt_target *target; 682 struct xt_target *target;
685 int ret; 683 int ret;
686 unsigned int j; 684 unsigned int j;
687 struct xt_mtchk_param mtpar; 685 struct xt_mtchk_param mtpar;
686 struct xt_entry_match *ematch;
688 687
689 ret = check_entry(e, name); 688 ret = check_entry(e, name);
690 if (ret) 689 if (ret)
@@ -696,9 +695,12 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
696 mtpar.entryinfo = &e->ip; 695 mtpar.entryinfo = &e->ip;
697 mtpar.hook_mask = e->comefrom; 696 mtpar.hook_mask = e->comefrom;
698 mtpar.family = NFPROTO_IPV4; 697 mtpar.family = NFPROTO_IPV4;
699 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j); 698 xt_ematch_foreach(ematch, e) {
700 if (ret != 0) 699 ret = find_check_match(ematch, &mtpar);
701 goto cleanup_matches; 700 if (ret != 0)
701 goto cleanup_matches;
702 ++j;
703 }
702 704
703 t = ipt_get_target(e); 705 t = ipt_get_target(e);
704 target = try_then_request_module(xt_find_target(AF_INET, 706 target = try_then_request_module(xt_find_target(AF_INET,
@@ -715,13 +717,15 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
715 ret = check_target(e, net, name); 717 ret = check_target(e, net, name);
716 if (ret) 718 if (ret)
717 goto err; 719 goto err;
718
719 (*i)++;
720 return 0; 720 return 0;
721 err: 721 err:
722 module_put(t->u.kernel.target->me); 722 module_put(t->u.kernel.target->me);
723 cleanup_matches: 723 cleanup_matches:
724 IPT_MATCH_ITERATE(e, cleanup_match, net, &j); 724 xt_ematch_foreach(ematch, e) {
725 if (j-- == 0)
726 break;
727 cleanup_match(ematch, net);
728 }
725 return ret; 729 return ret;
726} 730}
727 731
@@ -747,8 +751,7 @@ check_entry_size_and_hooks(struct ipt_entry *e,
747 const unsigned char *limit, 751 const unsigned char *limit,
748 const unsigned int *hook_entries, 752 const unsigned int *hook_entries,
749 const unsigned int *underflows, 753 const unsigned int *underflows,
750 unsigned int valid_hooks, 754 unsigned int valid_hooks)
751 unsigned int *i)
752{ 755{
753 unsigned int h; 756 unsigned int h;
754 757
@@ -785,22 +788,19 @@ check_entry_size_and_hooks(struct ipt_entry *e,
785 /* Clear counters and comefrom */ 788 /* Clear counters and comefrom */
786 e->counters = ((struct xt_counters) { 0, 0 }); 789 e->counters = ((struct xt_counters) { 0, 0 });
787 e->comefrom = 0; 790 e->comefrom = 0;
788
789 (*i)++;
790 return 0; 791 return 0;
791} 792}
792 793
793static int 794static void
794cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i) 795cleanup_entry(struct ipt_entry *e, struct net *net)
795{ 796{
796 struct xt_tgdtor_param par; 797 struct xt_tgdtor_param par;
797 struct ipt_entry_target *t; 798 struct ipt_entry_target *t;
798 799 struct xt_entry_match *ematch;
799 if (i && (*i)-- == 0)
800 return 1;
801 800
802 /* Cleanup all matches */ 801 /* Cleanup all matches */
803 IPT_MATCH_ITERATE(e, cleanup_match, net, NULL); 802 xt_ematch_foreach(ematch, e)
803 cleanup_match(ematch, net);
804 t = ipt_get_target(e); 804 t = ipt_get_target(e);
805 805
806 par.net = net; 806 par.net = net;
@@ -810,27 +810,20 @@ cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i)
810 if (par.target->destroy != NULL) 810 if (par.target->destroy != NULL)
811 par.target->destroy(&par); 811 par.target->destroy(&par);
812 module_put(par.target->me); 812 module_put(par.target->me);
813 return 0;
814} 813}
815 814
816/* Checks and translates the user-supplied table segment (held in 815/* Checks and translates the user-supplied table segment (held in
817 newinfo) */ 816 newinfo) */
818static int 817static int
819translate_table(struct net *net, 818translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
820 const char *name, 819 const struct ipt_replace *repl)
821 unsigned int valid_hooks,
822 struct xt_table_info *newinfo,
823 void *entry0,
824 unsigned int size,
825 unsigned int number,
826 const unsigned int *hook_entries,
827 const unsigned int *underflows)
828{ 820{
821 struct ipt_entry *iter;
829 unsigned int i; 822 unsigned int i;
830 int ret; 823 int ret = 0;
831 824
832 newinfo->size = size; 825 newinfo->size = repl->size;
833 newinfo->number = number; 826 newinfo->number = repl->num_entries;
834 827
835 /* Init all hooks to impossible value. */ 828 /* Init all hooks to impossible value. */
836 for (i = 0; i < NF_INET_NUMHOOKS; i++) { 829 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
@@ -841,49 +834,56 @@ translate_table(struct net *net,
841 duprintf("translate_table: size %u\n", newinfo->size); 834 duprintf("translate_table: size %u\n", newinfo->size);
842 i = 0; 835 i = 0;
843 /* Walk through entries, checking offsets. */ 836 /* Walk through entries, checking offsets. */
844 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 837 xt_entry_foreach(iter, entry0, newinfo->size) {
845 check_entry_size_and_hooks, 838 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
846 newinfo, 839 entry0 + repl->size, repl->hook_entry, repl->underflow,
847 entry0, 840 repl->valid_hooks);
848 entry0 + size, 841 if (ret != 0)
849 hook_entries, underflows, valid_hooks, &i); 842 return ret;
850 if (ret != 0) 843 ++i;
851 return ret; 844 }
852 845
853 if (i != number) { 846 if (i != repl->num_entries) {
854 duprintf("translate_table: %u not %u entries\n", 847 duprintf("translate_table: %u not %u entries\n",
855 i, number); 848 i, repl->num_entries);
856 return -EINVAL; 849 return -EINVAL;
857 } 850 }
858 851
859 /* Check hooks all assigned */ 852 /* Check hooks all assigned */
860 for (i = 0; i < NF_INET_NUMHOOKS; i++) { 853 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
861 /* Only hooks which are valid */ 854 /* Only hooks which are valid */
862 if (!(valid_hooks & (1 << i))) 855 if (!(repl->valid_hooks & (1 << i)))
863 continue; 856 continue;
864 if (newinfo->hook_entry[i] == 0xFFFFFFFF) { 857 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
865 duprintf("Invalid hook entry %u %u\n", 858 duprintf("Invalid hook entry %u %u\n",
866 i, hook_entries[i]); 859 i, repl->hook_entry[i]);
867 return -EINVAL; 860 return -EINVAL;
868 } 861 }
869 if (newinfo->underflow[i] == 0xFFFFFFFF) { 862 if (newinfo->underflow[i] == 0xFFFFFFFF) {
870 duprintf("Invalid underflow %u %u\n", 863 duprintf("Invalid underflow %u %u\n",
871 i, underflows[i]); 864 i, repl->underflow[i]);
872 return -EINVAL; 865 return -EINVAL;
873 } 866 }
874 } 867 }
875 868
876 if (!mark_source_chains(newinfo, valid_hooks, entry0)) 869 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
877 return -ELOOP; 870 return -ELOOP;
878 871
879 /* Finally, each sanity check must pass */ 872 /* Finally, each sanity check must pass */
880 i = 0; 873 i = 0;
881 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 874 xt_entry_foreach(iter, entry0, newinfo->size) {
882 find_check_entry, net, name, size, &i); 875 ret = find_check_entry(iter, net, repl->name, repl->size);
876 if (ret != 0)
877 break;
878 ++i;
879 }
883 880
884 if (ret != 0) { 881 if (ret != 0) {
885 IPT_ENTRY_ITERATE(entry0, newinfo->size, 882 xt_entry_foreach(iter, entry0, newinfo->size) {
886 cleanup_entry, net, &i); 883 if (i-- == 0)
884 break;
885 cleanup_entry(iter, net);
886 }
887 return ret; 887 return ret;
888 } 888 }
889 889
@@ -896,33 +896,11 @@ translate_table(struct net *net,
896 return ret; 896 return ret;
897} 897}
898 898
899/* Gets counters. */
900static inline int
901add_entry_to_counter(const struct ipt_entry *e,
902 struct xt_counters total[],
903 unsigned int *i)
904{
905 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
906
907 (*i)++;
908 return 0;
909}
910
911static inline int
912set_entry_to_counter(const struct ipt_entry *e,
913 struct ipt_counters total[],
914 unsigned int *i)
915{
916 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
917
918 (*i)++;
919 return 0;
920}
921
922static void 899static void
923get_counters(const struct xt_table_info *t, 900get_counters(const struct xt_table_info *t,
924 struct xt_counters counters[]) 901 struct xt_counters counters[])
925{ 902{
903 struct ipt_entry *iter;
926 unsigned int cpu; 904 unsigned int cpu;
927 unsigned int i; 905 unsigned int i;
928 unsigned int curcpu; 906 unsigned int curcpu;
@@ -938,22 +916,22 @@ get_counters(const struct xt_table_info *t,
938 curcpu = smp_processor_id(); 916 curcpu = smp_processor_id();
939 917
940 i = 0; 918 i = 0;
941 IPT_ENTRY_ITERATE(t->entries[curcpu], 919 xt_entry_foreach(iter, t->entries[curcpu], t->size) {
942 t->size, 920 SET_COUNTER(counters[i], iter->counters.bcnt,
943 set_entry_to_counter, 921 iter->counters.pcnt);
944 counters, 922 ++i;
945 &i); 923 }
946 924
947 for_each_possible_cpu(cpu) { 925 for_each_possible_cpu(cpu) {
948 if (cpu == curcpu) 926 if (cpu == curcpu)
949 continue; 927 continue;
950 i = 0; 928 i = 0;
951 xt_info_wrlock(cpu); 929 xt_info_wrlock(cpu);
952 IPT_ENTRY_ITERATE(t->entries[cpu], 930 xt_entry_foreach(iter, t->entries[cpu], t->size) {
953 t->size, 931 ADD_COUNTER(counters[i], iter->counters.bcnt,
954 add_entry_to_counter, 932 iter->counters.pcnt);
955 counters, 933 ++i; /* macro does multi eval of i */
956 &i); 934 }
957 xt_info_wrunlock(cpu); 935 xt_info_wrunlock(cpu);
958 } 936 }
959 local_bh_enable(); 937 local_bh_enable();
@@ -1072,24 +1050,19 @@ static int compat_standard_to_user(void __user *dst, const void *src)
1072 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; 1050 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1073} 1051}
1074 1052
1075static inline int
1076compat_calc_match(const struct ipt_entry_match *m, int *size)
1077{
1078 *size += xt_compat_match_offset(m->u.kernel.match);
1079 return 0;
1080}
1081
1082static int compat_calc_entry(const struct ipt_entry *e, 1053static int compat_calc_entry(const struct ipt_entry *e,
1083 const struct xt_table_info *info, 1054 const struct xt_table_info *info,
1084 const void *base, struct xt_table_info *newinfo) 1055 const void *base, struct xt_table_info *newinfo)
1085{ 1056{
1057 const struct xt_entry_match *ematch;
1086 const struct ipt_entry_target *t; 1058 const struct ipt_entry_target *t;
1087 unsigned int entry_offset; 1059 unsigned int entry_offset;
1088 int off, i, ret; 1060 int off, i, ret;
1089 1061
1090 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); 1062 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1091 entry_offset = (void *)e - base; 1063 entry_offset = (void *)e - base;
1092 IPT_MATCH_ITERATE(e, compat_calc_match, &off); 1064 xt_ematch_foreach(ematch, e)
1065 off += xt_compat_match_offset(ematch->u.kernel.match);
1093 t = ipt_get_target_c(e); 1066 t = ipt_get_target_c(e);
1094 off += xt_compat_target_offset(t->u.kernel.target); 1067 off += xt_compat_target_offset(t->u.kernel.target);
1095 newinfo->size -= off; 1068 newinfo->size -= off;
@@ -1111,7 +1084,9 @@ static int compat_calc_entry(const struct ipt_entry *e,
1111static int compat_table_info(const struct xt_table_info *info, 1084static int compat_table_info(const struct xt_table_info *info,
1112 struct xt_table_info *newinfo) 1085 struct xt_table_info *newinfo)
1113{ 1086{
1087 struct ipt_entry *iter;
1114 void *loc_cpu_entry; 1088 void *loc_cpu_entry;
1089 int ret;
1115 1090
1116 if (!newinfo || !info) 1091 if (!newinfo || !info)
1117 return -EINVAL; 1092 return -EINVAL;
@@ -1120,9 +1095,12 @@ static int compat_table_info(const struct xt_table_info *info,
1120 memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); 1095 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1121 newinfo->initial_entries = 0; 1096 newinfo->initial_entries = 0;
1122 loc_cpu_entry = info->entries[raw_smp_processor_id()]; 1097 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1123 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size, 1098 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1124 compat_calc_entry, info, loc_cpu_entry, 1099 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1125 newinfo); 1100 if (ret != 0)
1101 return ret;
1102 }
1103 return 0;
1126} 1104}
1127#endif 1105#endif
1128 1106
@@ -1236,6 +1214,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1236 struct xt_table_info *oldinfo; 1214 struct xt_table_info *oldinfo;
1237 struct xt_counters *counters; 1215 struct xt_counters *counters;
1238 void *loc_cpu_old_entry; 1216 void *loc_cpu_old_entry;
1217 struct ipt_entry *iter;
1239 1218
1240 ret = 0; 1219 ret = 0;
1241 counters = vmalloc(num_counters * sizeof(struct xt_counters)); 1220 counters = vmalloc(num_counters * sizeof(struct xt_counters));
@@ -1278,8 +1257,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1278 1257
1279 /* Decrease module usage counts and free resource */ 1258 /* Decrease module usage counts and free resource */
1280 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1259 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1281 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, 1260 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1282 net, NULL); 1261 cleanup_entry(iter, net);
1262
1283 xt_free_table_info(oldinfo); 1263 xt_free_table_info(oldinfo);
1284 if (copy_to_user(counters_ptr, counters, 1264 if (copy_to_user(counters_ptr, counters,
1285 sizeof(struct xt_counters) * num_counters) != 0) 1265 sizeof(struct xt_counters) * num_counters) != 0)
@@ -1304,6 +1284,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1304 struct ipt_replace tmp; 1284 struct ipt_replace tmp;
1305 struct xt_table_info *newinfo; 1285 struct xt_table_info *newinfo;
1306 void *loc_cpu_entry; 1286 void *loc_cpu_entry;
1287 struct ipt_entry *iter;
1307 1288
1308 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1289 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1309 return -EFAULT; 1290 return -EFAULT;
@@ -1324,9 +1305,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1324 goto free_newinfo; 1305 goto free_newinfo;
1325 } 1306 }
1326 1307
1327 ret = translate_table(net, tmp.name, tmp.valid_hooks, 1308 ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
1328 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1329 tmp.hook_entry, tmp.underflow);
1330 if (ret != 0) 1309 if (ret != 0)
1331 goto free_newinfo; 1310 goto free_newinfo;
1332 1311
@@ -1339,25 +1318,13 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1339 return 0; 1318 return 0;
1340 1319
1341 free_newinfo_untrans: 1320 free_newinfo_untrans:
1342 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); 1321 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1322 cleanup_entry(iter, net);
1343 free_newinfo: 1323 free_newinfo:
1344 xt_free_table_info(newinfo); 1324 xt_free_table_info(newinfo);
1345 return ret; 1325 return ret;
1346} 1326}
1347 1327
1348/* We're lazy, and add to the first CPU; overflow works its fey magic
1349 * and everything is OK. */
1350static int
1351add_counter_to_entry(struct ipt_entry *e,
1352 const struct xt_counters addme[],
1353 unsigned int *i)
1354{
1355 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1356
1357 (*i)++;
1358 return 0;
1359}
1360
1361static int 1328static int
1362do_add_counters(struct net *net, const void __user *user, 1329do_add_counters(struct net *net, const void __user *user,
1363 unsigned int len, int compat) 1330 unsigned int len, int compat)
@@ -1373,6 +1340,7 @@ do_add_counters(struct net *net, const void __user *user,
1373 const struct xt_table_info *private; 1340 const struct xt_table_info *private;
1374 int ret = 0; 1341 int ret = 0;
1375 void *loc_cpu_entry; 1342 void *loc_cpu_entry;
1343 struct ipt_entry *iter;
1376#ifdef CONFIG_COMPAT 1344#ifdef CONFIG_COMPAT
1377 struct compat_xt_counters_info compat_tmp; 1345 struct compat_xt_counters_info compat_tmp;
1378 1346
@@ -1430,11 +1398,10 @@ do_add_counters(struct net *net, const void __user *user,
1430 curcpu = smp_processor_id(); 1398 curcpu = smp_processor_id();
1431 loc_cpu_entry = private->entries[curcpu]; 1399 loc_cpu_entry = private->entries[curcpu];
1432 xt_info_wrlock(curcpu); 1400 xt_info_wrlock(curcpu);
1433 IPT_ENTRY_ITERATE(loc_cpu_entry, 1401 xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1434 private->size, 1402 ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
1435 add_counter_to_entry, 1403 ++i;
1436 paddc, 1404 }
1437 &i);
1438 xt_info_wrunlock(curcpu); 1405 xt_info_wrunlock(curcpu);
1439 unlock_up_free: 1406 unlock_up_free:
1440 local_bh_enable(); 1407 local_bh_enable();
@@ -1462,45 +1429,40 @@ struct compat_ipt_replace {
1462static int 1429static int
1463compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, 1430compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1464 unsigned int *size, struct xt_counters *counters, 1431 unsigned int *size, struct xt_counters *counters,
1465 unsigned int *i) 1432 unsigned int i)
1466{ 1433{
1467 struct ipt_entry_target *t; 1434 struct ipt_entry_target *t;
1468 struct compat_ipt_entry __user *ce; 1435 struct compat_ipt_entry __user *ce;
1469 u_int16_t target_offset, next_offset; 1436 u_int16_t target_offset, next_offset;
1470 compat_uint_t origsize; 1437 compat_uint_t origsize;
1471 int ret; 1438 const struct xt_entry_match *ematch;
1439 int ret = 0;
1472 1440
1473 ret = -EFAULT;
1474 origsize = *size; 1441 origsize = *size;
1475 ce = (struct compat_ipt_entry __user *)*dstptr; 1442 ce = (struct compat_ipt_entry __user *)*dstptr;
1476 if (copy_to_user(ce, e, sizeof(struct ipt_entry))) 1443 if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
1477 goto out; 1444 copy_to_user(&ce->counters, &counters[i],
1478 1445 sizeof(counters[i])) != 0)
1479 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i]))) 1446 return -EFAULT;
1480 goto out;
1481 1447
1482 *dstptr += sizeof(struct compat_ipt_entry); 1448 *dstptr += sizeof(struct compat_ipt_entry);
1483 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); 1449 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1484 1450
1485 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); 1451 xt_ematch_foreach(ematch, e) {
1452 ret = xt_compat_match_to_user(ematch, dstptr, size);
1453 if (ret != 0)
1454 return ret;
1455 }
1486 target_offset = e->target_offset - (origsize - *size); 1456 target_offset = e->target_offset - (origsize - *size);
1487 if (ret)
1488 goto out;
1489 t = ipt_get_target(e); 1457 t = ipt_get_target(e);
1490 ret = xt_compat_target_to_user(t, dstptr, size); 1458 ret = xt_compat_target_to_user(t, dstptr, size);
1491 if (ret) 1459 if (ret)
1492 goto out; 1460 return ret;
1493 ret = -EFAULT;
1494 next_offset = e->next_offset - (origsize - *size); 1461 next_offset = e->next_offset - (origsize - *size);
1495 if (put_user(target_offset, &ce->target_offset)) 1462 if (put_user(target_offset, &ce->target_offset) != 0 ||
1496 goto out; 1463 put_user(next_offset, &ce->next_offset) != 0)
1497 if (put_user(next_offset, &ce->next_offset)) 1464 return -EFAULT;
1498 goto out;
1499
1500 (*i)++;
1501 return 0; 1465 return 0;
1502out:
1503 return ret;
1504} 1466}
1505 1467
1506static int 1468static int
@@ -1508,7 +1470,7 @@ compat_find_calc_match(struct ipt_entry_match *m,
1508 const char *name, 1470 const char *name,
1509 const struct ipt_ip *ip, 1471 const struct ipt_ip *ip,
1510 unsigned int hookmask, 1472 unsigned int hookmask,
1511 int *size, unsigned int *i) 1473 int *size)
1512{ 1474{
1513 struct xt_match *match; 1475 struct xt_match *match;
1514 1476
@@ -1522,34 +1484,19 @@ compat_find_calc_match(struct ipt_entry_match *m,
1522 } 1484 }
1523 m->u.kernel.match = match; 1485 m->u.kernel.match = match;
1524 *size += xt_compat_match_offset(match); 1486 *size += xt_compat_match_offset(match);
1525
1526 (*i)++;
1527 return 0; 1487 return 0;
1528} 1488}
1529 1489
1530static int 1490static void compat_release_entry(struct compat_ipt_entry *e)
1531compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1532{
1533 if (i && (*i)-- == 0)
1534 return 1;
1535
1536 module_put(m->u.kernel.match->me);
1537 return 0;
1538}
1539
1540static int
1541compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1542{ 1491{
1543 struct ipt_entry_target *t; 1492 struct ipt_entry_target *t;
1544 1493 struct xt_entry_match *ematch;
1545 if (i && (*i)-- == 0)
1546 return 1;
1547 1494
1548 /* Cleanup all matches */ 1495 /* Cleanup all matches */
1549 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL); 1496 xt_ematch_foreach(ematch, e)
1497 module_put(ematch->u.kernel.match->me);
1550 t = compat_ipt_get_target(e); 1498 t = compat_ipt_get_target(e);
1551 module_put(t->u.kernel.target->me); 1499 module_put(t->u.kernel.target->me);
1552 return 0;
1553} 1500}
1554 1501
1555static int 1502static int
@@ -1560,9 +1507,9 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1560 const unsigned char *limit, 1507 const unsigned char *limit,
1561 const unsigned int *hook_entries, 1508 const unsigned int *hook_entries,
1562 const unsigned int *underflows, 1509 const unsigned int *underflows,
1563 unsigned int *i,
1564 const char *name) 1510 const char *name)
1565{ 1511{
1512 struct xt_entry_match *ematch;
1566 struct ipt_entry_target *t; 1513 struct ipt_entry_target *t;
1567 struct xt_target *target; 1514 struct xt_target *target;
1568 unsigned int entry_offset; 1515 unsigned int entry_offset;
@@ -1591,10 +1538,13 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1591 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); 1538 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1592 entry_offset = (void *)e - (void *)base; 1539 entry_offset = (void *)e - (void *)base;
1593 j = 0; 1540 j = 0;
1594 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name, 1541 xt_ematch_foreach(ematch, e) {
1595 &e->ip, e->comefrom, &off, &j); 1542 ret = compat_find_calc_match(ematch, name,
1596 if (ret != 0) 1543 &e->ip, e->comefrom, &off);
1597 goto release_matches; 1544 if (ret != 0)
1545 goto release_matches;
1546 ++j;
1547 }
1598 1548
1599 t = compat_ipt_get_target(e); 1549 t = compat_ipt_get_target(e);
1600 target = try_then_request_module(xt_find_target(AF_INET, 1550 target = try_then_request_module(xt_find_target(AF_INET,
@@ -1626,14 +1576,16 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1626 /* Clear counters and comefrom */ 1576 /* Clear counters and comefrom */
1627 memset(&e->counters, 0, sizeof(e->counters)); 1577 memset(&e->counters, 0, sizeof(e->counters));
1628 e->comefrom = 0; 1578 e->comefrom = 0;
1629
1630 (*i)++;
1631 return 0; 1579 return 0;
1632 1580
1633out: 1581out:
1634 module_put(t->u.kernel.target->me); 1582 module_put(t->u.kernel.target->me);
1635release_matches: 1583release_matches:
1636 IPT_MATCH_ITERATE(e, compat_release_match, &j); 1584 xt_ematch_foreach(ematch, e) {
1585 if (j-- == 0)
1586 break;
1587 module_put(ematch->u.kernel.match->me);
1588 }
1637 return ret; 1589 return ret;
1638} 1590}
1639 1591
@@ -1647,6 +1599,7 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1647 struct ipt_entry *de; 1599 struct ipt_entry *de;
1648 unsigned int origsize; 1600 unsigned int origsize;
1649 int ret, h; 1601 int ret, h;
1602 struct xt_entry_match *ematch;
1650 1603
1651 ret = 0; 1604 ret = 0;
1652 origsize = *size; 1605 origsize = *size;
@@ -1657,10 +1610,11 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1657 *dstptr += sizeof(struct ipt_entry); 1610 *dstptr += sizeof(struct ipt_entry);
1658 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); 1611 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1659 1612
1660 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user, 1613 xt_ematch_foreach(ematch, e) {
1661 dstptr, size); 1614 ret = xt_compat_match_from_user(ematch, dstptr, size);
1662 if (ret) 1615 if (ret != 0)
1663 return ret; 1616 return ret;
1617 }
1664 de->target_offset = e->target_offset - (origsize - *size); 1618 de->target_offset = e->target_offset - (origsize - *size);
1665 t = compat_ipt_get_target(e); 1619 t = compat_ipt_get_target(e);
1666 target = t->u.kernel.target; 1620 target = t->u.kernel.target;
@@ -1677,12 +1631,12 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1677} 1631}
1678 1632
1679static int 1633static int
1680compat_check_entry(struct ipt_entry *e, struct net *net, const char *name, 1634compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
1681 unsigned int *i)
1682{ 1635{
1636 struct xt_entry_match *ematch;
1683 struct xt_mtchk_param mtpar; 1637 struct xt_mtchk_param mtpar;
1684 unsigned int j; 1638 unsigned int j;
1685 int ret; 1639 int ret = 0;
1686 1640
1687 j = 0; 1641 j = 0;
1688 mtpar.net = net; 1642 mtpar.net = net;
@@ -1690,19 +1644,24 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name,
1690 mtpar.entryinfo = &e->ip; 1644 mtpar.entryinfo = &e->ip;
1691 mtpar.hook_mask = e->comefrom; 1645 mtpar.hook_mask = e->comefrom;
1692 mtpar.family = NFPROTO_IPV4; 1646 mtpar.family = NFPROTO_IPV4;
1693 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j); 1647 xt_ematch_foreach(ematch, e) {
1694 if (ret) 1648 ret = check_match(ematch, &mtpar);
1695 goto cleanup_matches; 1649 if (ret != 0)
1650 goto cleanup_matches;
1651 ++j;
1652 }
1696 1653
1697 ret = check_target(e, net, name); 1654 ret = check_target(e, net, name);
1698 if (ret) 1655 if (ret)
1699 goto cleanup_matches; 1656 goto cleanup_matches;
1700
1701 (*i)++;
1702 return 0; 1657 return 0;
1703 1658
1704 cleanup_matches: 1659 cleanup_matches:
1705 IPT_MATCH_ITERATE(e, cleanup_match, net, &j); 1660 xt_ematch_foreach(ematch, e) {
1661 if (j-- == 0)
1662 break;
1663 cleanup_match(ematch, net);
1664 }
1706 return ret; 1665 return ret;
1707} 1666}
1708 1667
@@ -1720,6 +1679,8 @@ translate_compat_table(struct net *net,
1720 unsigned int i, j; 1679 unsigned int i, j;
1721 struct xt_table_info *newinfo, *info; 1680 struct xt_table_info *newinfo, *info;
1722 void *pos, *entry0, *entry1; 1681 void *pos, *entry0, *entry1;
1682 struct compat_ipt_entry *iter0;
1683 struct ipt_entry *iter1;
1723 unsigned int size; 1684 unsigned int size;
1724 int ret; 1685 int ret;
1725 1686
@@ -1738,13 +1699,14 @@ translate_compat_table(struct net *net,
1738 j = 0; 1699 j = 0;
1739 xt_compat_lock(AF_INET); 1700 xt_compat_lock(AF_INET);
1740 /* Walk through entries, checking offsets. */ 1701 /* Walk through entries, checking offsets. */
1741 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, 1702 xt_entry_foreach(iter0, entry0, total_size) {
1742 check_compat_entry_size_and_hooks, 1703 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1743 info, &size, entry0, 1704 entry0, entry0 + total_size, hook_entries, underflows,
1744 entry0 + total_size, 1705 name);
1745 hook_entries, underflows, &j, name); 1706 if (ret != 0)
1746 if (ret != 0) 1707 goto out_unlock;
1747 goto out_unlock; 1708 ++j;
1709 }
1748 1710
1749 ret = -EINVAL; 1711 ret = -EINVAL;
1750 if (j != number) { 1712 if (j != number) {
@@ -1783,9 +1745,12 @@ translate_compat_table(struct net *net,
1783 entry1 = newinfo->entries[raw_smp_processor_id()]; 1745 entry1 = newinfo->entries[raw_smp_processor_id()];
1784 pos = entry1; 1746 pos = entry1;
1785 size = total_size; 1747 size = total_size;
1786 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, 1748 xt_entry_foreach(iter0, entry0, total_size) {
1787 compat_copy_entry_from_user, 1749 ret = compat_copy_entry_from_user(iter0, &pos,
1788 &pos, &size, name, newinfo, entry1); 1750 &size, name, newinfo, entry1);
1751 if (ret != 0)
1752 break;
1753 }
1789 xt_compat_flush_offsets(AF_INET); 1754 xt_compat_flush_offsets(AF_INET);
1790 xt_compat_unlock(AF_INET); 1755 xt_compat_unlock(AF_INET);
1791 if (ret) 1756 if (ret)
@@ -1796,13 +1761,32 @@ translate_compat_table(struct net *net,
1796 goto free_newinfo; 1761 goto free_newinfo;
1797 1762
1798 i = 0; 1763 i = 0;
1799 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, 1764 xt_entry_foreach(iter1, entry1, newinfo->size) {
1800 net, name, &i); 1765 ret = compat_check_entry(iter1, net, name);
1766 if (ret != 0)
1767 break;
1768 ++i;
1769 }
1801 if (ret) { 1770 if (ret) {
1771 /*
1772 * The first i matches need cleanup_entry (calls ->destroy)
1773 * because they had called ->check already. The other j-i
1774 * entries need only release.
1775 */
1776 int skip = i;
1802 j -= i; 1777 j -= i;
1803 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, 1778 xt_entry_foreach(iter0, entry0, newinfo->size) {
1804 compat_release_entry, &j); 1779 if (skip-- > 0)
1805 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i); 1780 continue;
1781 if (j-- == 0)
1782 break;
1783 compat_release_entry(iter0);
1784 }
1785 xt_entry_foreach(iter1, entry1, newinfo->size) {
1786 if (i-- == 0)
1787 break;
1788 cleanup_entry(iter1, net);
1789 }
1806 xt_free_table_info(newinfo); 1790 xt_free_table_info(newinfo);
1807 return ret; 1791 return ret;
1808 } 1792 }
@@ -1820,7 +1804,11 @@ translate_compat_table(struct net *net,
1820free_newinfo: 1804free_newinfo:
1821 xt_free_table_info(newinfo); 1805 xt_free_table_info(newinfo);
1822out: 1806out:
1823 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); 1807 xt_entry_foreach(iter0, entry0, total_size) {
1808 if (j-- == 0)
1809 break;
1810 compat_release_entry(iter0);
1811 }
1824 return ret; 1812 return ret;
1825out_unlock: 1813out_unlock:
1826 xt_compat_flush_offsets(AF_INET); 1814 xt_compat_flush_offsets(AF_INET);
@@ -1835,6 +1823,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1835 struct compat_ipt_replace tmp; 1823 struct compat_ipt_replace tmp;
1836 struct xt_table_info *newinfo; 1824 struct xt_table_info *newinfo;
1837 void *loc_cpu_entry; 1825 void *loc_cpu_entry;
1826 struct ipt_entry *iter;
1838 1827
1839 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1828 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1840 return -EFAULT; 1829 return -EFAULT;
@@ -1873,7 +1862,8 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1873 return 0; 1862 return 0;
1874 1863
1875 free_newinfo_untrans: 1864 free_newinfo_untrans:
1876 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); 1865 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1866 cleanup_entry(iter, net);
1877 free_newinfo: 1867 free_newinfo:
1878 xt_free_table_info(newinfo); 1868 xt_free_table_info(newinfo);
1879 return ret; 1869 return ret;
@@ -1922,6 +1912,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1922 int ret = 0; 1912 int ret = 0;
1923 const void *loc_cpu_entry; 1913 const void *loc_cpu_entry;
1924 unsigned int i = 0; 1914 unsigned int i = 0;
1915 struct ipt_entry *iter;
1925 1916
1926 counters = alloc_counters(table); 1917 counters = alloc_counters(table);
1927 if (IS_ERR(counters)) 1918 if (IS_ERR(counters))
@@ -1934,9 +1925,12 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1934 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 1925 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1935 pos = userptr; 1926 pos = userptr;
1936 size = total_size; 1927 size = total_size;
1937 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size, 1928 xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1938 compat_copy_entry_to_user, 1929 ret = compat_copy_entry_to_user(iter, &pos,
1939 &pos, &size, counters, &i); 1930 &size, counters, i++);
1931 if (ret != 0)
1932 break;
1933 }
1940 1934
1941 vfree(counters); 1935 vfree(counters);
1942 return ret; 1936 return ret;
@@ -2110,11 +2104,7 @@ struct xt_table *ipt_register_table(struct net *net,
2110 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; 2104 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2111 memcpy(loc_cpu_entry, repl->entries, repl->size); 2105 memcpy(loc_cpu_entry, repl->entries, repl->size);
2112 2106
2113 ret = translate_table(net, table->name, table->valid_hooks, 2107 ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2114 newinfo, loc_cpu_entry, repl->size,
2115 repl->num_entries,
2116 repl->hook_entry,
2117 repl->underflow);
2118 if (ret != 0) 2108 if (ret != 0)
2119 goto out_free; 2109 goto out_free;
2120 2110
@@ -2137,12 +2127,14 @@ void ipt_unregister_table(struct net *net, struct xt_table *table)
2137 struct xt_table_info *private; 2127 struct xt_table_info *private;
2138 void *loc_cpu_entry; 2128 void *loc_cpu_entry;
2139 struct module *table_owner = table->me; 2129 struct module *table_owner = table->me;
2130 struct ipt_entry *iter;
2140 2131
2141 private = xt_unregister_table(table); 2132 private = xt_unregister_table(table);
2142 2133
2143 /* Decrease module usage counts and free resources */ 2134 /* Decrease module usage counts and free resources */
2144 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 2135 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2145 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL); 2136 xt_entry_foreach(iter, loc_cpu_entry, private->size)
2137 cleanup_entry(iter, net);
2146 if (private->number > private->initial_entries) 2138 if (private->number > private->initial_entries)
2147 module_put(table_owner); 2139 module_put(table_owner);
2148 xt_free_table_info(private); 2140 xt_free_table_info(private);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4185099c2943..f7042869198e 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -318,6 +318,7 @@ static void trace_packet(const struct sk_buff *skb,
318 const void *table_base; 318 const void *table_base;
319 const struct ip6t_entry *root; 319 const struct ip6t_entry *root;
320 const char *hookname, *chainname, *comment; 320 const char *hookname, *chainname, *comment;
321 const struct ip6t_entry *iter;
321 unsigned int rulenum = 0; 322 unsigned int rulenum = 0;
322 323
323 table_base = private->entries[smp_processor_id()]; 324 table_base = private->entries[smp_processor_id()];
@@ -326,10 +327,10 @@ static void trace_packet(const struct sk_buff *skb,
326 hookname = chainname = hooknames[hook]; 327 hookname = chainname = hooknames[hook];
327 comment = comments[NF_IP6_TRACE_COMMENT_RULE]; 328 comment = comments[NF_IP6_TRACE_COMMENT_RULE];
328 329
329 IP6T_ENTRY_ITERATE(root, 330 xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
330 private->size - private->hook_entry[hook], 331 if (get_chainname_rulenum(iter, e, hookname,
331 get_chainname_rulenum, 332 &chainname, &comment, &rulenum) != 0)
332 e, hookname, &chainname, &comment, &rulenum); 333 break;
333 334
334 nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo, 335 nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
335 "TRACE: %s:%s:%s:%u ", 336 "TRACE: %s:%s:%s:%u ",
@@ -392,16 +393,21 @@ ip6t_do_table(struct sk_buff *skb,
392 393
393 do { 394 do {
394 const struct ip6t_entry_target *t; 395 const struct ip6t_entry_target *t;
396 const struct xt_entry_match *ematch;
395 397
396 IP_NF_ASSERT(e); 398 IP_NF_ASSERT(e);
397 IP_NF_ASSERT(back); 399 IP_NF_ASSERT(back);
398 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, 400 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
399 &mtpar.thoff, &mtpar.fragoff, &hotdrop) || 401 &mtpar.thoff, &mtpar.fragoff, &hotdrop)) {
400 IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { 402 no_match:
401 e = ip6t_next_entry(e); 403 e = ip6t_next_entry(e);
402 continue; 404 continue;
403 } 405 }
404 406
407 xt_ematch_foreach(ematch, e)
408 if (do_match(ematch, skb, &mtpar) != 0)
409 goto no_match;
410
405 ADD_COUNTER(e->counters, 411 ADD_COUNTER(e->counters,
406 ntohs(ipv6_hdr(skb)->payload_len) + 412 ntohs(ipv6_hdr(skb)->payload_len) +
407 sizeof(struct ipv6hdr), 1); 413 sizeof(struct ipv6hdr), 1);
@@ -597,14 +603,10 @@ mark_source_chains(const struct xt_table_info *newinfo,
597 return 1; 603 return 1;
598} 604}
599 605
600static int 606static void cleanup_match(struct ip6t_entry_match *m, struct net *net)
601cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i)
602{ 607{
603 struct xt_mtdtor_param par; 608 struct xt_mtdtor_param par;
604 609
605 if (i && (*i)-- == 0)
606 return 1;
607
608 par.net = net; 610 par.net = net;
609 par.match = m->u.kernel.match; 611 par.match = m->u.kernel.match;
610 par.matchinfo = m->data; 612 par.matchinfo = m->data;
@@ -612,7 +614,6 @@ cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i)
612 if (par.match->destroy != NULL) 614 if (par.match->destroy != NULL)
613 par.match->destroy(&par); 615 par.match->destroy(&par);
614 module_put(par.match->me); 616 module_put(par.match->me);
615 return 0;
616} 617}
617 618
618static int 619static int
@@ -636,8 +637,7 @@ check_entry(const struct ip6t_entry *e, const char *name)
636 return 0; 637 return 0;
637} 638}
638 639
639static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, 640static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
640 unsigned int *i)
641{ 641{
642 const struct ip6t_ip6 *ipv6 = par->entryinfo; 642 const struct ip6t_ip6 *ipv6 = par->entryinfo;
643 int ret; 643 int ret;
@@ -652,13 +652,11 @@ static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par,
652 par.match->name); 652 par.match->name);
653 return ret; 653 return ret;
654 } 654 }
655 ++*i;
656 return 0; 655 return 0;
657} 656}
658 657
659static int 658static int
660find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, 659find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
661 unsigned int *i)
662{ 660{
663 struct xt_match *match; 661 struct xt_match *match;
664 int ret; 662 int ret;
@@ -672,7 +670,7 @@ find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par,
672 } 670 }
673 m->u.kernel.match = match; 671 m->u.kernel.match = match;
674 672
675 ret = check_match(m, par, i); 673 ret = check_match(m, par);
676 if (ret) 674 if (ret)
677 goto err; 675 goto err;
678 676
@@ -709,13 +707,14 @@ static int check_target(struct ip6t_entry *e, struct net *net, const char *name)
709 707
710static int 708static int
711find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, 709find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
712 unsigned int size, unsigned int *i) 710 unsigned int size)
713{ 711{
714 struct ip6t_entry_target *t; 712 struct ip6t_entry_target *t;
715 struct xt_target *target; 713 struct xt_target *target;
716 int ret; 714 int ret;
717 unsigned int j; 715 unsigned int j;
718 struct xt_mtchk_param mtpar; 716 struct xt_mtchk_param mtpar;
717 struct xt_entry_match *ematch;
719 718
720 ret = check_entry(e, name); 719 ret = check_entry(e, name);
721 if (ret) 720 if (ret)
@@ -727,9 +726,12 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
727 mtpar.entryinfo = &e->ipv6; 726 mtpar.entryinfo = &e->ipv6;
728 mtpar.hook_mask = e->comefrom; 727 mtpar.hook_mask = e->comefrom;
729 mtpar.family = NFPROTO_IPV6; 728 mtpar.family = NFPROTO_IPV6;
730 ret = IP6T_MATCH_ITERATE(e, find_check_match, &mtpar, &j); 729 xt_ematch_foreach(ematch, e) {
731 if (ret != 0) 730 ret = find_check_match(ematch, &mtpar);
732 goto cleanup_matches; 731 if (ret != 0)
732 goto cleanup_matches;
733 ++j;
734 }
733 735
734 t = ip6t_get_target(e); 736 t = ip6t_get_target(e);
735 target = try_then_request_module(xt_find_target(AF_INET6, 737 target = try_then_request_module(xt_find_target(AF_INET6,
@@ -746,13 +748,15 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
746 ret = check_target(e, net, name); 748 ret = check_target(e, net, name);
747 if (ret) 749 if (ret)
748 goto err; 750 goto err;
749
750 (*i)++;
751 return 0; 751 return 0;
752 err: 752 err:
753 module_put(t->u.kernel.target->me); 753 module_put(t->u.kernel.target->me);
754 cleanup_matches: 754 cleanup_matches:
755 IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); 755 xt_ematch_foreach(ematch, e) {
756 if (j-- == 0)
757 break;
758 cleanup_match(ematch, net);
759 }
756 return ret; 760 return ret;
757} 761}
758 762
@@ -778,8 +782,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
778 const unsigned char *limit, 782 const unsigned char *limit,
779 const unsigned int *hook_entries, 783 const unsigned int *hook_entries,
780 const unsigned int *underflows, 784 const unsigned int *underflows,
781 unsigned int valid_hooks, 785 unsigned int valid_hooks)
782 unsigned int *i)
783{ 786{
784 unsigned int h; 787 unsigned int h;
785 788
@@ -816,22 +819,18 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
816 /* Clear counters and comefrom */ 819 /* Clear counters and comefrom */
817 e->counters = ((struct xt_counters) { 0, 0 }); 820 e->counters = ((struct xt_counters) { 0, 0 });
818 e->comefrom = 0; 821 e->comefrom = 0;
819
820 (*i)++;
821 return 0; 822 return 0;
822} 823}
823 824
824static int 825static void cleanup_entry(struct ip6t_entry *e, struct net *net)
825cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i)
826{ 826{
827 struct xt_tgdtor_param par; 827 struct xt_tgdtor_param par;
828 struct ip6t_entry_target *t; 828 struct ip6t_entry_target *t;
829 829 struct xt_entry_match *ematch;
830 if (i && (*i)-- == 0)
831 return 1;
832 830
833 /* Cleanup all matches */ 831 /* Cleanup all matches */
834 IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL); 832 xt_ematch_foreach(ematch, e)
833 cleanup_match(ematch, net);
835 t = ip6t_get_target(e); 834 t = ip6t_get_target(e);
836 835
837 par.net = net; 836 par.net = net;
@@ -841,27 +840,20 @@ cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i)
841 if (par.target->destroy != NULL) 840 if (par.target->destroy != NULL)
842 par.target->destroy(&par); 841 par.target->destroy(&par);
843 module_put(par.target->me); 842 module_put(par.target->me);
844 return 0;
845} 843}
846 844
847/* Checks and translates the user-supplied table segment (held in 845/* Checks and translates the user-supplied table segment (held in
848 newinfo) */ 846 newinfo) */
849static int 847static int
850translate_table(struct net *net, 848translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
851 const char *name, 849 const struct ip6t_replace *repl)
852 unsigned int valid_hooks,
853 struct xt_table_info *newinfo,
854 void *entry0,
855 unsigned int size,
856 unsigned int number,
857 const unsigned int *hook_entries,
858 const unsigned int *underflows)
859{ 850{
851 struct ip6t_entry *iter;
860 unsigned int i; 852 unsigned int i;
861 int ret; 853 int ret = 0;
862 854
863 newinfo->size = size; 855 newinfo->size = repl->size;
864 newinfo->number = number; 856 newinfo->number = repl->num_entries;
865 857
866 /* Init all hooks to impossible value. */ 858 /* Init all hooks to impossible value. */
867 for (i = 0; i < NF_INET_NUMHOOKS; i++) { 859 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
@@ -872,49 +864,56 @@ translate_table(struct net *net,
872 duprintf("translate_table: size %u\n", newinfo->size); 864 duprintf("translate_table: size %u\n", newinfo->size);
873 i = 0; 865 i = 0;
874 /* Walk through entries, checking offsets. */ 866 /* Walk through entries, checking offsets. */
875 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 867 xt_entry_foreach(iter, entry0, newinfo->size) {
876 check_entry_size_and_hooks, 868 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
877 newinfo, 869 entry0 + repl->size, repl->hook_entry, repl->underflow,
878 entry0, 870 repl->valid_hooks);
879 entry0 + size, 871 if (ret != 0)
880 hook_entries, underflows, valid_hooks, &i); 872 return ret;
881 if (ret != 0) 873 ++i;
882 return ret; 874 }
883 875
884 if (i != number) { 876 if (i != repl->num_entries) {
885 duprintf("translate_table: %u not %u entries\n", 877 duprintf("translate_table: %u not %u entries\n",
886 i, number); 878 i, repl->num_entries);
887 return -EINVAL; 879 return -EINVAL;
888 } 880 }
889 881
890 /* Check hooks all assigned */ 882 /* Check hooks all assigned */
891 for (i = 0; i < NF_INET_NUMHOOKS; i++) { 883 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
892 /* Only hooks which are valid */ 884 /* Only hooks which are valid */
893 if (!(valid_hooks & (1 << i))) 885 if (!(repl->valid_hooks & (1 << i)))
894 continue; 886 continue;
895 if (newinfo->hook_entry[i] == 0xFFFFFFFF) { 887 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
896 duprintf("Invalid hook entry %u %u\n", 888 duprintf("Invalid hook entry %u %u\n",
897 i, hook_entries[i]); 889 i, repl->hook_entry[i]);
898 return -EINVAL; 890 return -EINVAL;
899 } 891 }
900 if (newinfo->underflow[i] == 0xFFFFFFFF) { 892 if (newinfo->underflow[i] == 0xFFFFFFFF) {
901 duprintf("Invalid underflow %u %u\n", 893 duprintf("Invalid underflow %u %u\n",
902 i, underflows[i]); 894 i, repl->underflow[i]);
903 return -EINVAL; 895 return -EINVAL;
904 } 896 }
905 } 897 }
906 898
907 if (!mark_source_chains(newinfo, valid_hooks, entry0)) 899 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
908 return -ELOOP; 900 return -ELOOP;
909 901
910 /* Finally, each sanity check must pass */ 902 /* Finally, each sanity check must pass */
911 i = 0; 903 i = 0;
912 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 904 xt_entry_foreach(iter, entry0, newinfo->size) {
913 find_check_entry, net, name, size, &i); 905 ret = find_check_entry(iter, net, repl->name, repl->size);
906 if (ret != 0)
907 break;
908 ++i;
909 }
914 910
915 if (ret != 0) { 911 if (ret != 0) {
916 IP6T_ENTRY_ITERATE(entry0, newinfo->size, 912 xt_entry_foreach(iter, entry0, newinfo->size) {
917 cleanup_entry, net, &i); 913 if (i-- == 0)
914 break;
915 cleanup_entry(iter, net);
916 }
918 return ret; 917 return ret;
919 } 918 }
920 919
@@ -927,33 +926,11 @@ translate_table(struct net *net,
927 return ret; 926 return ret;
928} 927}
929 928
930/* Gets counters. */
931static inline int
932add_entry_to_counter(const struct ip6t_entry *e,
933 struct xt_counters total[],
934 unsigned int *i)
935{
936 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
937
938 (*i)++;
939 return 0;
940}
941
942static inline int
943set_entry_to_counter(const struct ip6t_entry *e,
944 struct ip6t_counters total[],
945 unsigned int *i)
946{
947 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
948
949 (*i)++;
950 return 0;
951}
952
953static void 929static void
954get_counters(const struct xt_table_info *t, 930get_counters(const struct xt_table_info *t,
955 struct xt_counters counters[]) 931 struct xt_counters counters[])
956{ 932{
933 struct ip6t_entry *iter;
957 unsigned int cpu; 934 unsigned int cpu;
958 unsigned int i; 935 unsigned int i;
959 unsigned int curcpu; 936 unsigned int curcpu;
@@ -969,22 +946,22 @@ get_counters(const struct xt_table_info *t,
969 curcpu = smp_processor_id(); 946 curcpu = smp_processor_id();
970 947
971 i = 0; 948 i = 0;
972 IP6T_ENTRY_ITERATE(t->entries[curcpu], 949 xt_entry_foreach(iter, t->entries[curcpu], t->size) {
973 t->size, 950 SET_COUNTER(counters[i], iter->counters.bcnt,
974 set_entry_to_counter, 951 iter->counters.pcnt);
975 counters, 952 ++i;
976 &i); 953 }
977 954
978 for_each_possible_cpu(cpu) { 955 for_each_possible_cpu(cpu) {
979 if (cpu == curcpu) 956 if (cpu == curcpu)
980 continue; 957 continue;
981 i = 0; 958 i = 0;
982 xt_info_wrlock(cpu); 959 xt_info_wrlock(cpu);
983 IP6T_ENTRY_ITERATE(t->entries[cpu], 960 xt_entry_foreach(iter, t->entries[cpu], t->size) {
984 t->size, 961 ADD_COUNTER(counters[i], iter->counters.bcnt,
985 add_entry_to_counter, 962 iter->counters.pcnt);
986 counters, 963 ++i;
987 &i); 964 }
988 xt_info_wrunlock(cpu); 965 xt_info_wrunlock(cpu);
989 } 966 }
990 local_bh_enable(); 967 local_bh_enable();
@@ -1103,24 +1080,19 @@ static int compat_standard_to_user(void __user *dst, const void *src)
1103 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; 1080 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1104} 1081}
1105 1082
1106static inline int
1107compat_calc_match(const struct ip6t_entry_match *m, int *size)
1108{
1109 *size += xt_compat_match_offset(m->u.kernel.match);
1110 return 0;
1111}
1112
1113static int compat_calc_entry(const struct ip6t_entry *e, 1083static int compat_calc_entry(const struct ip6t_entry *e,
1114 const struct xt_table_info *info, 1084 const struct xt_table_info *info,
1115 const void *base, struct xt_table_info *newinfo) 1085 const void *base, struct xt_table_info *newinfo)
1116{ 1086{
1087 const struct xt_entry_match *ematch;
1117 const struct ip6t_entry_target *t; 1088 const struct ip6t_entry_target *t;
1118 unsigned int entry_offset; 1089 unsigned int entry_offset;
1119 int off, i, ret; 1090 int off, i, ret;
1120 1091
1121 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1092 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1122 entry_offset = (void *)e - base; 1093 entry_offset = (void *)e - base;
1123 IP6T_MATCH_ITERATE(e, compat_calc_match, &off); 1094 xt_ematch_foreach(ematch, e)
1095 off += xt_compat_match_offset(ematch->u.kernel.match);
1124 t = ip6t_get_target_c(e); 1096 t = ip6t_get_target_c(e);
1125 off += xt_compat_target_offset(t->u.kernel.target); 1097 off += xt_compat_target_offset(t->u.kernel.target);
1126 newinfo->size -= off; 1098 newinfo->size -= off;
@@ -1142,7 +1114,9 @@ static int compat_calc_entry(const struct ip6t_entry *e,
1142static int compat_table_info(const struct xt_table_info *info, 1114static int compat_table_info(const struct xt_table_info *info,
1143 struct xt_table_info *newinfo) 1115 struct xt_table_info *newinfo)
1144{ 1116{
1117 struct ip6t_entry *iter;
1145 void *loc_cpu_entry; 1118 void *loc_cpu_entry;
1119 int ret;
1146 1120
1147 if (!newinfo || !info) 1121 if (!newinfo || !info)
1148 return -EINVAL; 1122 return -EINVAL;
@@ -1151,9 +1125,12 @@ static int compat_table_info(const struct xt_table_info *info,
1151 memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); 1125 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1152 newinfo->initial_entries = 0; 1126 newinfo->initial_entries = 0;
1153 loc_cpu_entry = info->entries[raw_smp_processor_id()]; 1127 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1154 return IP6T_ENTRY_ITERATE(loc_cpu_entry, info->size, 1128 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1155 compat_calc_entry, info, loc_cpu_entry, 1129 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1156 newinfo); 1130 if (ret != 0)
1131 return ret;
1132 }
1133 return 0;
1157} 1134}
1158#endif 1135#endif
1159 1136
@@ -1267,6 +1244,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1267 struct xt_table_info *oldinfo; 1244 struct xt_table_info *oldinfo;
1268 struct xt_counters *counters; 1245 struct xt_counters *counters;
1269 const void *loc_cpu_old_entry; 1246 const void *loc_cpu_old_entry;
1247 struct ip6t_entry *iter;
1270 1248
1271 ret = 0; 1249 ret = 0;
1272 counters = vmalloc_node(num_counters * sizeof(struct xt_counters), 1250 counters = vmalloc_node(num_counters * sizeof(struct xt_counters),
@@ -1310,8 +1288,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1310 1288
1311 /* Decrease module usage counts and free resource */ 1289 /* Decrease module usage counts and free resource */
1312 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1290 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1313 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, 1291 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1314 net, NULL); 1292 cleanup_entry(iter, net);
1293
1315 xt_free_table_info(oldinfo); 1294 xt_free_table_info(oldinfo);
1316 if (copy_to_user(counters_ptr, counters, 1295 if (copy_to_user(counters_ptr, counters,
1317 sizeof(struct xt_counters) * num_counters) != 0) 1296 sizeof(struct xt_counters) * num_counters) != 0)
@@ -1336,6 +1315,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1336 struct ip6t_replace tmp; 1315 struct ip6t_replace tmp;
1337 struct xt_table_info *newinfo; 1316 struct xt_table_info *newinfo;
1338 void *loc_cpu_entry; 1317 void *loc_cpu_entry;
1318 struct ip6t_entry *iter;
1339 1319
1340 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1320 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1341 return -EFAULT; 1321 return -EFAULT;
@@ -1356,9 +1336,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1356 goto free_newinfo; 1336 goto free_newinfo;
1357 } 1337 }
1358 1338
1359 ret = translate_table(net, tmp.name, tmp.valid_hooks, 1339 ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
1360 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1361 tmp.hook_entry, tmp.underflow);
1362 if (ret != 0) 1340 if (ret != 0)
1363 goto free_newinfo; 1341 goto free_newinfo;
1364 1342
@@ -1371,25 +1349,13 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1371 return 0; 1349 return 0;
1372 1350
1373 free_newinfo_untrans: 1351 free_newinfo_untrans:
1374 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); 1352 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1353 cleanup_entry(iter, net);
1375 free_newinfo: 1354 free_newinfo:
1376 xt_free_table_info(newinfo); 1355 xt_free_table_info(newinfo);
1377 return ret; 1356 return ret;
1378} 1357}
1379 1358
1380/* We're lazy, and add to the first CPU; overflow works its fey magic
1381 * and everything is OK. */
1382static int
1383add_counter_to_entry(struct ip6t_entry *e,
1384 const struct xt_counters addme[],
1385 unsigned int *i)
1386{
1387 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1388
1389 (*i)++;
1390 return 0;
1391}
1392
1393static int 1359static int
1394do_add_counters(struct net *net, const void __user *user, unsigned int len, 1360do_add_counters(struct net *net, const void __user *user, unsigned int len,
1395 int compat) 1361 int compat)
@@ -1405,6 +1371,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
1405 const struct xt_table_info *private; 1371 const struct xt_table_info *private;
1406 int ret = 0; 1372 int ret = 0;
1407 const void *loc_cpu_entry; 1373 const void *loc_cpu_entry;
1374 struct ip6t_entry *iter;
1408#ifdef CONFIG_COMPAT 1375#ifdef CONFIG_COMPAT
1409 struct compat_xt_counters_info compat_tmp; 1376 struct compat_xt_counters_info compat_tmp;
1410 1377
@@ -1463,11 +1430,10 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
1463 curcpu = smp_processor_id(); 1430 curcpu = smp_processor_id();
1464 xt_info_wrlock(curcpu); 1431 xt_info_wrlock(curcpu);
1465 loc_cpu_entry = private->entries[curcpu]; 1432 loc_cpu_entry = private->entries[curcpu];
1466 IP6T_ENTRY_ITERATE(loc_cpu_entry, 1433 xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1467 private->size, 1434 ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
1468 add_counter_to_entry, 1435 ++i;
1469 paddc, 1436 }
1470 &i);
1471 xt_info_wrunlock(curcpu); 1437 xt_info_wrunlock(curcpu);
1472 1438
1473 unlock_up_free: 1439 unlock_up_free:
@@ -1496,45 +1462,40 @@ struct compat_ip6t_replace {
1496static int 1462static int
1497compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, 1463compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
1498 unsigned int *size, struct xt_counters *counters, 1464 unsigned int *size, struct xt_counters *counters,
1499 unsigned int *i) 1465 unsigned int i)
1500{ 1466{
1501 struct ip6t_entry_target *t; 1467 struct ip6t_entry_target *t;
1502 struct compat_ip6t_entry __user *ce; 1468 struct compat_ip6t_entry __user *ce;
1503 u_int16_t target_offset, next_offset; 1469 u_int16_t target_offset, next_offset;
1504 compat_uint_t origsize; 1470 compat_uint_t origsize;
1505 int ret; 1471 const struct xt_entry_match *ematch;
1472 int ret = 0;
1506 1473
1507 ret = -EFAULT;
1508 origsize = *size; 1474 origsize = *size;
1509 ce = (struct compat_ip6t_entry __user *)*dstptr; 1475 ce = (struct compat_ip6t_entry __user *)*dstptr;
1510 if (copy_to_user(ce, e, sizeof(struct ip6t_entry))) 1476 if (copy_to_user(ce, e, sizeof(struct ip6t_entry)) != 0 ||
1511 goto out; 1477 copy_to_user(&ce->counters, &counters[i],
1512 1478 sizeof(counters[i])) != 0)
1513 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i]))) 1479 return -EFAULT;
1514 goto out;
1515 1480
1516 *dstptr += sizeof(struct compat_ip6t_entry); 1481 *dstptr += sizeof(struct compat_ip6t_entry);
1517 *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1482 *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1518 1483
1519 ret = IP6T_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); 1484 xt_ematch_foreach(ematch, e) {
1485 ret = xt_compat_match_to_user(ematch, dstptr, size);
1486 if (ret != 0)
1487 return ret;
1488 }
1520 target_offset = e->target_offset - (origsize - *size); 1489 target_offset = e->target_offset - (origsize - *size);
1521 if (ret)
1522 goto out;
1523 t = ip6t_get_target(e); 1490 t = ip6t_get_target(e);
1524 ret = xt_compat_target_to_user(t, dstptr, size); 1491 ret = xt_compat_target_to_user(t, dstptr, size);
1525 if (ret) 1492 if (ret)
1526 goto out; 1493 return ret;
1527 ret = -EFAULT;
1528 next_offset = e->next_offset - (origsize - *size); 1494 next_offset = e->next_offset - (origsize - *size);
1529 if (put_user(target_offset, &ce->target_offset)) 1495 if (put_user(target_offset, &ce->target_offset) != 0 ||
1530 goto out; 1496 put_user(next_offset, &ce->next_offset) != 0)
1531 if (put_user(next_offset, &ce->next_offset)) 1497 return -EFAULT;
1532 goto out;
1533
1534 (*i)++;
1535 return 0; 1498 return 0;
1536out:
1537 return ret;
1538} 1499}
1539 1500
1540static int 1501static int
@@ -1542,7 +1503,7 @@ compat_find_calc_match(struct ip6t_entry_match *m,
1542 const char *name, 1503 const char *name,
1543 const struct ip6t_ip6 *ipv6, 1504 const struct ip6t_ip6 *ipv6,
1544 unsigned int hookmask, 1505 unsigned int hookmask,
1545 int *size, unsigned int *i) 1506 int *size)
1546{ 1507{
1547 struct xt_match *match; 1508 struct xt_match *match;
1548 1509
@@ -1556,34 +1517,19 @@ compat_find_calc_match(struct ip6t_entry_match *m,
1556 } 1517 }
1557 m->u.kernel.match = match; 1518 m->u.kernel.match = match;
1558 *size += xt_compat_match_offset(match); 1519 *size += xt_compat_match_offset(match);
1559
1560 (*i)++;
1561 return 0;
1562}
1563
1564static int
1565compat_release_match(struct ip6t_entry_match *m, unsigned int *i)
1566{
1567 if (i && (*i)-- == 0)
1568 return 1;
1569
1570 module_put(m->u.kernel.match->me);
1571 return 0; 1520 return 0;
1572} 1521}
1573 1522
1574static int 1523static void compat_release_entry(struct compat_ip6t_entry *e)
1575compat_release_entry(struct compat_ip6t_entry *e, unsigned int *i)
1576{ 1524{
1577 struct ip6t_entry_target *t; 1525 struct ip6t_entry_target *t;
1578 1526 struct xt_entry_match *ematch;
1579 if (i && (*i)-- == 0)
1580 return 1;
1581 1527
1582 /* Cleanup all matches */ 1528 /* Cleanup all matches */
1583 COMPAT_IP6T_MATCH_ITERATE(e, compat_release_match, NULL); 1529 xt_ematch_foreach(ematch, e)
1530 module_put(ematch->u.kernel.match->me);
1584 t = compat_ip6t_get_target(e); 1531 t = compat_ip6t_get_target(e);
1585 module_put(t->u.kernel.target->me); 1532 module_put(t->u.kernel.target->me);
1586 return 0;
1587} 1533}
1588 1534
1589static int 1535static int
@@ -1594,9 +1540,9 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1594 const unsigned char *limit, 1540 const unsigned char *limit,
1595 const unsigned int *hook_entries, 1541 const unsigned int *hook_entries,
1596 const unsigned int *underflows, 1542 const unsigned int *underflows,
1597 unsigned int *i,
1598 const char *name) 1543 const char *name)
1599{ 1544{
1545 struct xt_entry_match *ematch;
1600 struct ip6t_entry_target *t; 1546 struct ip6t_entry_target *t;
1601 struct xt_target *target; 1547 struct xt_target *target;
1602 unsigned int entry_offset; 1548 unsigned int entry_offset;
@@ -1625,10 +1571,13 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1625 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1571 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1626 entry_offset = (void *)e - (void *)base; 1572 entry_offset = (void *)e - (void *)base;
1627 j = 0; 1573 j = 0;
1628 ret = COMPAT_IP6T_MATCH_ITERATE(e, compat_find_calc_match, name, 1574 xt_ematch_foreach(ematch, e) {
1629 &e->ipv6, e->comefrom, &off, &j); 1575 ret = compat_find_calc_match(ematch, name,
1630 if (ret != 0) 1576 &e->ipv6, e->comefrom, &off);
1631 goto release_matches; 1577 if (ret != 0)
1578 goto release_matches;
1579 ++j;
1580 }
1632 1581
1633 t = compat_ip6t_get_target(e); 1582 t = compat_ip6t_get_target(e);
1634 target = try_then_request_module(xt_find_target(AF_INET6, 1583 target = try_then_request_module(xt_find_target(AF_INET6,
@@ -1660,14 +1609,16 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1660 /* Clear counters and comefrom */ 1609 /* Clear counters and comefrom */
1661 memset(&e->counters, 0, sizeof(e->counters)); 1610 memset(&e->counters, 0, sizeof(e->counters));
1662 e->comefrom = 0; 1611 e->comefrom = 0;
1663
1664 (*i)++;
1665 return 0; 1612 return 0;
1666 1613
1667out: 1614out:
1668 module_put(t->u.kernel.target->me); 1615 module_put(t->u.kernel.target->me);
1669release_matches: 1616release_matches:
1670 IP6T_MATCH_ITERATE(e, compat_release_match, &j); 1617 xt_ematch_foreach(ematch, e) {
1618 if (j-- == 0)
1619 break;
1620 module_put(ematch->u.kernel.match->me);
1621 }
1671 return ret; 1622 return ret;
1672} 1623}
1673 1624
@@ -1681,6 +1632,7 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
1681 struct ip6t_entry *de; 1632 struct ip6t_entry *de;
1682 unsigned int origsize; 1633 unsigned int origsize;
1683 int ret, h; 1634 int ret, h;
1635 struct xt_entry_match *ematch;
1684 1636
1685 ret = 0; 1637 ret = 0;
1686 origsize = *size; 1638 origsize = *size;
@@ -1691,10 +1643,11 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
1691 *dstptr += sizeof(struct ip6t_entry); 1643 *dstptr += sizeof(struct ip6t_entry);
1692 *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1644 *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1693 1645
1694 ret = COMPAT_IP6T_MATCH_ITERATE(e, xt_compat_match_from_user, 1646 xt_ematch_foreach(ematch, e) {
1695 dstptr, size); 1647 ret = xt_compat_match_from_user(ematch, dstptr, size);
1696 if (ret) 1648 if (ret != 0)
1697 return ret; 1649 return ret;
1650 }
1698 de->target_offset = e->target_offset - (origsize - *size); 1651 de->target_offset = e->target_offset - (origsize - *size);
1699 t = compat_ip6t_get_target(e); 1652 t = compat_ip6t_get_target(e);
1700 target = t->u.kernel.target; 1653 target = t->u.kernel.target;
@@ -1711,11 +1664,12 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
1711} 1664}
1712 1665
1713static int compat_check_entry(struct ip6t_entry *e, struct net *net, 1666static int compat_check_entry(struct ip6t_entry *e, struct net *net,
1714 const char *name, unsigned int *i) 1667 const char *name)
1715{ 1668{
1716 unsigned int j; 1669 unsigned int j;
1717 int ret; 1670 int ret = 0;
1718 struct xt_mtchk_param mtpar; 1671 struct xt_mtchk_param mtpar;
1672 struct xt_entry_match *ematch;
1719 1673
1720 j = 0; 1674 j = 0;
1721 mtpar.net = net; 1675 mtpar.net = net;
@@ -1723,19 +1677,24 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net,
1723 mtpar.entryinfo = &e->ipv6; 1677 mtpar.entryinfo = &e->ipv6;
1724 mtpar.hook_mask = e->comefrom; 1678 mtpar.hook_mask = e->comefrom;
1725 mtpar.family = NFPROTO_IPV6; 1679 mtpar.family = NFPROTO_IPV6;
1726 ret = IP6T_MATCH_ITERATE(e, check_match, &mtpar, &j); 1680 xt_ematch_foreach(ematch, e) {
1727 if (ret) 1681 ret = check_match(ematch, &mtpar);
1728 goto cleanup_matches; 1682 if (ret != 0)
1683 goto cleanup_matches;
1684 ++j;
1685 }
1729 1686
1730 ret = check_target(e, net, name); 1687 ret = check_target(e, net, name);
1731 if (ret) 1688 if (ret)
1732 goto cleanup_matches; 1689 goto cleanup_matches;
1733
1734 (*i)++;
1735 return 0; 1690 return 0;
1736 1691
1737 cleanup_matches: 1692 cleanup_matches:
1738 IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); 1693 xt_ematch_foreach(ematch, e) {
1694 if (j-- == 0)
1695 break;
1696 cleanup_match(ematch, net);
1697 }
1739 return ret; 1698 return ret;
1740} 1699}
1741 1700
@@ -1753,8 +1712,10 @@ translate_compat_table(struct net *net,
1753 unsigned int i, j; 1712 unsigned int i, j;
1754 struct xt_table_info *newinfo, *info; 1713 struct xt_table_info *newinfo, *info;
1755 void *pos, *entry0, *entry1; 1714 void *pos, *entry0, *entry1;
1715 struct compat_ip6t_entry *iter0;
1716 struct ip6t_entry *iter1;
1756 unsigned int size; 1717 unsigned int size;
1757 int ret; 1718 int ret = 0;
1758 1719
1759 info = *pinfo; 1720 info = *pinfo;
1760 entry0 = *pentry0; 1721 entry0 = *pentry0;
@@ -1771,13 +1732,14 @@ translate_compat_table(struct net *net,
1771 j = 0; 1732 j = 0;
1772 xt_compat_lock(AF_INET6); 1733 xt_compat_lock(AF_INET6);
1773 /* Walk through entries, checking offsets. */ 1734 /* Walk through entries, checking offsets. */
1774 ret = COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, 1735 xt_entry_foreach(iter0, entry0, total_size) {
1775 check_compat_entry_size_and_hooks, 1736 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1776 info, &size, entry0, 1737 entry0, entry0 + total_size, hook_entries, underflows,
1777 entry0 + total_size, 1738 name);
1778 hook_entries, underflows, &j, name); 1739 if (ret != 0)
1779 if (ret != 0) 1740 goto out_unlock;
1780 goto out_unlock; 1741 ++j;
1742 }
1781 1743
1782 ret = -EINVAL; 1744 ret = -EINVAL;
1783 if (j != number) { 1745 if (j != number) {
@@ -1816,9 +1778,12 @@ translate_compat_table(struct net *net,
1816 entry1 = newinfo->entries[raw_smp_processor_id()]; 1778 entry1 = newinfo->entries[raw_smp_processor_id()];
1817 pos = entry1; 1779 pos = entry1;
1818 size = total_size; 1780 size = total_size;
1819 ret = COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, 1781 xt_entry_foreach(iter0, entry0, total_size) {
1820 compat_copy_entry_from_user, 1782 ret = compat_copy_entry_from_user(iter0, &pos,
1821 &pos, &size, name, newinfo, entry1); 1783 &size, name, newinfo, entry1);
1784 if (ret != 0)
1785 break;
1786 }
1822 xt_compat_flush_offsets(AF_INET6); 1787 xt_compat_flush_offsets(AF_INET6);
1823 xt_compat_unlock(AF_INET6); 1788 xt_compat_unlock(AF_INET6);
1824 if (ret) 1789 if (ret)
@@ -1829,13 +1794,32 @@ translate_compat_table(struct net *net,
1829 goto free_newinfo; 1794 goto free_newinfo;
1830 1795
1831 i = 0; 1796 i = 0;
1832 ret = IP6T_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, 1797 xt_entry_foreach(iter1, entry1, newinfo->size) {
1833 net, name, &i); 1798 ret = compat_check_entry(iter1, net, name);
1799 if (ret != 0)
1800 break;
1801 ++i;
1802 }
1834 if (ret) { 1803 if (ret) {
1804 /*
1805 * The first i matches need cleanup_entry (calls ->destroy)
1806 * because they had called ->check already. The other j-i
1807 * entries need only release.
1808 */
1809 int skip = i;
1835 j -= i; 1810 j -= i;
1836 COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, 1811 xt_entry_foreach(iter0, entry0, newinfo->size) {
1837 compat_release_entry, &j); 1812 if (skip-- > 0)
1838 IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i); 1813 continue;
1814 if (j-- == 0)
1815 break;
1816 compat_release_entry(iter0);
1817 }
1818 xt_entry_foreach(iter1, entry1, newinfo->size) {
1819 if (i-- == 0)
1820 break;
1821 cleanup_entry(iter1, net);
1822 }
1839 xt_free_table_info(newinfo); 1823 xt_free_table_info(newinfo);
1840 return ret; 1824 return ret;
1841 } 1825 }
@@ -1853,7 +1837,11 @@ translate_compat_table(struct net *net,
1853free_newinfo: 1837free_newinfo:
1854 xt_free_table_info(newinfo); 1838 xt_free_table_info(newinfo);
1855out: 1839out:
1856 COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); 1840 xt_entry_foreach(iter0, entry0, total_size) {
1841 if (j-- == 0)
1842 break;
1843 compat_release_entry(iter0);
1844 }
1857 return ret; 1845 return ret;
1858out_unlock: 1846out_unlock:
1859 xt_compat_flush_offsets(AF_INET6); 1847 xt_compat_flush_offsets(AF_INET6);
@@ -1868,6 +1856,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1868 struct compat_ip6t_replace tmp; 1856 struct compat_ip6t_replace tmp;
1869 struct xt_table_info *newinfo; 1857 struct xt_table_info *newinfo;
1870 void *loc_cpu_entry; 1858 void *loc_cpu_entry;
1859 struct ip6t_entry *iter;
1871 1860
1872 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1861 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1873 return -EFAULT; 1862 return -EFAULT;
@@ -1906,7 +1895,8 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1906 return 0; 1895 return 0;
1907 1896
1908 free_newinfo_untrans: 1897 free_newinfo_untrans:
1909 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); 1898 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1899 cleanup_entry(iter, net);
1910 free_newinfo: 1900 free_newinfo:
1911 xt_free_table_info(newinfo); 1901 xt_free_table_info(newinfo);
1912 return ret; 1902 return ret;
@@ -1955,6 +1945,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1955 int ret = 0; 1945 int ret = 0;
1956 const void *loc_cpu_entry; 1946 const void *loc_cpu_entry;
1957 unsigned int i = 0; 1947 unsigned int i = 0;
1948 struct ip6t_entry *iter;
1958 1949
1959 counters = alloc_counters(table); 1950 counters = alloc_counters(table);
1960 if (IS_ERR(counters)) 1951 if (IS_ERR(counters))
@@ -1967,9 +1958,12 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1967 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 1958 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1968 pos = userptr; 1959 pos = userptr;
1969 size = total_size; 1960 size = total_size;
1970 ret = IP6T_ENTRY_ITERATE(loc_cpu_entry, total_size, 1961 xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1971 compat_copy_entry_to_user, 1962 ret = compat_copy_entry_to_user(iter, &pos,
1972 &pos, &size, counters, &i); 1963 &size, counters, i++);
1964 if (ret != 0)
1965 break;
1966 }
1973 1967
1974 vfree(counters); 1968 vfree(counters);
1975 return ret; 1969 return ret;
@@ -2143,11 +2137,7 @@ struct xt_table *ip6t_register_table(struct net *net,
2143 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; 2137 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2144 memcpy(loc_cpu_entry, repl->entries, repl->size); 2138 memcpy(loc_cpu_entry, repl->entries, repl->size);
2145 2139
2146 ret = translate_table(net, table->name, table->valid_hooks, 2140 ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2147 newinfo, loc_cpu_entry, repl->size,
2148 repl->num_entries,
2149 repl->hook_entry,
2150 repl->underflow);
2151 if (ret != 0) 2141 if (ret != 0)
2152 goto out_free; 2142 goto out_free;
2153 2143
@@ -2169,12 +2159,14 @@ void ip6t_unregister_table(struct net *net, struct xt_table *table)
2169 struct xt_table_info *private; 2159 struct xt_table_info *private;
2170 void *loc_cpu_entry; 2160 void *loc_cpu_entry;
2171 struct module *table_owner = table->me; 2161 struct module *table_owner = table->me;
2162 struct ip6t_entry *iter;
2172 2163
2173 private = xt_unregister_table(table); 2164 private = xt_unregister_table(table);
2174 2165
2175 /* Decrease module usage counts and free resources */ 2166 /* Decrease module usage counts and free resources */
2176 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 2167 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2177 IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL); 2168 xt_entry_foreach(iter, loc_cpu_entry, private->size)
2169 cleanup_entry(iter, net);
2178 if (private->number > private->initial_entries) 2170 if (private->number > private->initial_entries)
2179 module_put(table_owner); 2171 module_put(table_owner);
2180 xt_free_table_info(private); 2172 xt_free_table_info(private);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index ad1fcda6898b..f1171b744650 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -469,7 +469,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
469 469
470 /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ 470 /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */
471 fp = skb_shinfo(head)->frag_list; 471 fp = skb_shinfo(head)->frag_list;
472 if (NFCT_FRAG6_CB(fp)->orig == NULL) 472 if (fp && NFCT_FRAG6_CB(fp)->orig == NULL)
473 /* at above code, head skb is divided into two skbs. */ 473 /* at above code, head skb is divided into two skbs. */
474 fp = fp->next; 474 fp = fp->next;
475 475
@@ -595,12 +595,6 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
595 hdr = ipv6_hdr(clone); 595 hdr = ipv6_hdr(clone);
596 fhdr = (struct frag_hdr *)skb_transport_header(clone); 596 fhdr = (struct frag_hdr *)skb_transport_header(clone);
597 597
598 if (!(fhdr->frag_off & htons(0xFFF9))) {
599 pr_debug("Invalid fragment offset\n");
600 /* It is not a fragmented frame */
601 goto ret_orig;
602 }
603
604 if (atomic_read(&nf_init_frags.mem) > nf_init_frags.high_thresh) 598 if (atomic_read(&nf_init_frags.mem) > nf_init_frags.high_thresh)
605 nf_ct_frag6_evictor(); 599 nf_ct_frag6_evictor();
606 600
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 6f21b4377dbb..0e357ac9a2a8 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -239,6 +239,7 @@ static bool tcpmss_tg4_check(const struct xt_tgchk_param *par)
239{ 239{
240 const struct xt_tcpmss_info *info = par->targinfo; 240 const struct xt_tcpmss_info *info = par->targinfo;
241 const struct ipt_entry *e = par->entryinfo; 241 const struct ipt_entry *e = par->entryinfo;
242 const struct xt_entry_match *ematch;
242 243
243 if (info->mss == XT_TCPMSS_CLAMP_PMTU && 244 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
244 (par->hook_mask & ~((1 << NF_INET_FORWARD) | 245 (par->hook_mask & ~((1 << NF_INET_FORWARD) |
@@ -248,8 +249,9 @@ static bool tcpmss_tg4_check(const struct xt_tgchk_param *par)
248 "FORWARD, OUTPUT and POSTROUTING hooks\n"); 249 "FORWARD, OUTPUT and POSTROUTING hooks\n");
249 return false; 250 return false;
250 } 251 }
251 if (IPT_MATCH_ITERATE(e, find_syn_match)) 252 xt_ematch_foreach(ematch, e)
252 return true; 253 if (find_syn_match(ematch))
254 return true;
253 printk("xt_TCPMSS: Only works on TCP SYN packets\n"); 255 printk("xt_TCPMSS: Only works on TCP SYN packets\n");
254 return false; 256 return false;
255} 257}
@@ -259,6 +261,7 @@ static bool tcpmss_tg6_check(const struct xt_tgchk_param *par)
259{ 261{
260 const struct xt_tcpmss_info *info = par->targinfo; 262 const struct xt_tcpmss_info *info = par->targinfo;
261 const struct ip6t_entry *e = par->entryinfo; 263 const struct ip6t_entry *e = par->entryinfo;
264 const struct xt_entry_match *ematch;
262 265
263 if (info->mss == XT_TCPMSS_CLAMP_PMTU && 266 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
264 (par->hook_mask & ~((1 << NF_INET_FORWARD) | 267 (par->hook_mask & ~((1 << NF_INET_FORWARD) |
@@ -268,8 +271,9 @@ static bool tcpmss_tg6_check(const struct xt_tgchk_param *par)
268 "FORWARD, OUTPUT and POSTROUTING hooks\n"); 271 "FORWARD, OUTPUT and POSTROUTING hooks\n");
269 return false; 272 return false;
270 } 273 }
271 if (IP6T_MATCH_ITERATE(e, find_syn_match)) 274 xt_ematch_foreach(ematch, e)
272 return true; 275 if (find_syn_match(ematch))
276 return true;
273 printk("xt_TCPMSS: Only works on TCP SYN packets\n"); 277 printk("xt_TCPMSS: Only works on TCP SYN packets\n");
274 return false; 278 return false;
275} 279}
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index 132cfaa84cdc..7073dbb8100c 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -177,10 +177,10 @@ recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr,
177 177
178static void recent_entry_update(struct recent_table *t, struct recent_entry *e) 178static void recent_entry_update(struct recent_table *t, struct recent_entry *e)
179{ 179{
180 e->index %= ip_pkt_list_tot;
180 e->stamps[e->index++] = jiffies; 181 e->stamps[e->index++] = jiffies;
181 if (e->index > e->nstamps) 182 if (e->index > e->nstamps)
182 e->nstamps = e->index; 183 e->nstamps = e->index;
183 e->index %= ip_pkt_list_tot;
184 list_move_tail(&e->lru_list, &t->lru_list); 184 list_move_tail(&e->lru_list, &t->lru_list);
185} 185}
186 186
@@ -267,7 +267,7 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par)
267 for (i = 0; i < e->nstamps; i++) { 267 for (i = 0; i < e->nstamps; i++) {
268 if (info->seconds && time_after(time, e->stamps[i])) 268 if (info->seconds && time_after(time, e->stamps[i]))
269 continue; 269 continue;
270 if (++hits >= info->hit_count) { 270 if (info->hit_count && ++hits >= info->hit_count) {
271 ret = !ret; 271 ret = !ret;
272 break; 272 break;
273 } 273 }