aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
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/ipv6
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/ipv6')
-rw-r--r--net/ipv6/netfilter/ip6_tables.c436
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c8
2 files changed, 215 insertions, 229 deletions
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