aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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 /net/ipv4
parentfb977e2ca607a7e74946a1de798f474d1b80b9d6 (diff)
parent0f234214d15fa914436d304ecf5c3e43449e79f9 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/arp_tables.c301
-rw-r--r--net/ipv4/netfilter/ip_tables.c436
2 files changed, 349 insertions, 388 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 4db5c1ece0f..57098dcda29 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 e94c18bdfc6..c92f4e541cf 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);