diff options
author | David S. Miller <davem@davemloft.net> | 2010-02-16 14:15:13 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-16 14:15:13 -0500 |
commit | 749f621e20ab0db35a15ff730088922603c809ba (patch) | |
tree | 2684d12199b58f2b9e0c5b7e6cc0ea3f002e611a /net/ipv6 | |
parent | 339c6e99853d2ef1f02ad8a313e079050a300427 (diff) | |
parent | 3e5e524ffb5fcf2447eb5dd9f8e54ad22dd9baa7 (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.c | 158 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_filter.c | 113 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_mangle.c | 141 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_raw.c | 86 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_security.c | 109 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 14 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 11 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 7 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 4 |
9 files changed, 208 insertions, 435 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 8a7e0f52e177..4185099c2943 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/netfilter_ipv6/ip6_tables.h> | 29 | #include <linux/netfilter_ipv6/ip6_tables.h> |
30 | #include <linux/netfilter/x_tables.h> | 30 | #include <linux/netfilter/x_tables.h> |
31 | #include <net/netfilter/nf_log.h> | 31 | #include <net/netfilter/nf_log.h> |
32 | #include "../../netfilter/xt_repldata.h" | ||
32 | 33 | ||
33 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
34 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 35 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
@@ -67,6 +68,12 @@ do { \ | |||
67 | #define inline | 68 | #define inline |
68 | #endif | 69 | #endif |
69 | 70 | ||
71 | void *ip6t_alloc_initial_table(const struct xt_table *info) | ||
72 | { | ||
73 | return xt_alloc_initial_table(ip6t, IP6T); | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table); | ||
76 | |||
70 | /* | 77 | /* |
71 | We keep a set of rules for each CPU, so we can avoid write-locking | 78 | We keep a set of rules for each CPU, so we can avoid write-locking |
72 | them in the softirq when updating the counters and therefore | 79 | them in the softirq when updating the counters and therefore |
@@ -201,7 +208,7 @@ ip6t_error(struct sk_buff *skb, const struct xt_target_param *par) | |||
201 | 208 | ||
202 | /* Performance critical - called for every packet */ | 209 | /* Performance critical - called for every packet */ |
203 | static inline bool | 210 | static inline bool |
204 | do_match(struct ip6t_entry_match *m, const struct sk_buff *skb, | 211 | do_match(const struct ip6t_entry_match *m, const struct sk_buff *skb, |
205 | struct xt_match_param *par) | 212 | struct xt_match_param *par) |
206 | { | 213 | { |
207 | par->match = m->u.kernel.match; | 214 | par->match = m->u.kernel.match; |
@@ -215,7 +222,7 @@ do_match(struct ip6t_entry_match *m, const struct sk_buff *skb, | |||
215 | } | 222 | } |
216 | 223 | ||
217 | static inline struct ip6t_entry * | 224 | static inline struct ip6t_entry * |
218 | get_entry(void *base, unsigned int offset) | 225 | get_entry(const void *base, unsigned int offset) |
219 | { | 226 | { |
220 | return (struct ip6t_entry *)(base + offset); | 227 | return (struct ip6t_entry *)(base + offset); |
221 | } | 228 | } |
@@ -229,6 +236,12 @@ static inline bool unconditional(const struct ip6t_ip6 *ipv6) | |||
229 | return memcmp(ipv6, &uncond, sizeof(uncond)) == 0; | 236 | return memcmp(ipv6, &uncond, sizeof(uncond)) == 0; |
230 | } | 237 | } |
231 | 238 | ||
239 | static inline const struct ip6t_entry_target * | ||
240 | ip6t_get_target_c(const struct ip6t_entry *e) | ||
241 | { | ||
242 | return ip6t_get_target((struct ip6t_entry *)e); | ||
243 | } | ||
244 | |||
232 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | 245 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ |
233 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | 246 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) |
234 | /* This cries for unification! */ | 247 | /* This cries for unification! */ |
@@ -264,11 +277,11 @@ static struct nf_loginfo trace_loginfo = { | |||
264 | 277 | ||
265 | /* Mildly perf critical (only if packet tracing is on) */ | 278 | /* Mildly perf critical (only if packet tracing is on) */ |
266 | static inline int | 279 | static inline int |
267 | get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, | 280 | get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e, |
268 | const char *hookname, const char **chainname, | 281 | const char *hookname, const char **chainname, |
269 | const char **comment, unsigned int *rulenum) | 282 | const char **comment, unsigned int *rulenum) |
270 | { | 283 | { |
271 | struct ip6t_standard_target *t = (void *)ip6t_get_target(s); | 284 | const struct ip6t_standard_target *t = (void *)ip6t_get_target_c(s); |
272 | 285 | ||
273 | if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) { | 286 | if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) { |
274 | /* Head of user chain: ERROR target with chainname */ | 287 | /* Head of user chain: ERROR target with chainname */ |
@@ -294,15 +307,15 @@ get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, | |||
294 | return 0; | 307 | return 0; |
295 | } | 308 | } |
296 | 309 | ||
297 | static void trace_packet(struct sk_buff *skb, | 310 | static void trace_packet(const struct sk_buff *skb, |
298 | unsigned int hook, | 311 | unsigned int hook, |
299 | const struct net_device *in, | 312 | const struct net_device *in, |
300 | const struct net_device *out, | 313 | const struct net_device *out, |
301 | const char *tablename, | 314 | const char *tablename, |
302 | struct xt_table_info *private, | 315 | const struct xt_table_info *private, |
303 | struct ip6t_entry *e) | 316 | const struct ip6t_entry *e) |
304 | { | 317 | { |
305 | void *table_base; | 318 | const void *table_base; |
306 | const struct ip6t_entry *root; | 319 | const struct ip6t_entry *root; |
307 | const char *hookname, *chainname, *comment; | 320 | const char *hookname, *chainname, *comment; |
308 | unsigned int rulenum = 0; | 321 | unsigned int rulenum = 0; |
@@ -345,9 +358,9 @@ ip6t_do_table(struct sk_buff *skb, | |||
345 | /* Initializing verdict to NF_DROP keeps gcc happy. */ | 358 | /* Initializing verdict to NF_DROP keeps gcc happy. */ |
346 | unsigned int verdict = NF_DROP; | 359 | unsigned int verdict = NF_DROP; |
347 | const char *indev, *outdev; | 360 | const char *indev, *outdev; |
348 | void *table_base; | 361 | const void *table_base; |
349 | struct ip6t_entry *e, *back; | 362 | struct ip6t_entry *e, *back; |
350 | struct xt_table_info *private; | 363 | const struct xt_table_info *private; |
351 | struct xt_match_param mtpar; | 364 | struct xt_match_param mtpar; |
352 | struct xt_target_param tgpar; | 365 | struct xt_target_param tgpar; |
353 | 366 | ||
@@ -378,7 +391,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
378 | back = get_entry(table_base, private->underflow[hook]); | 391 | back = get_entry(table_base, private->underflow[hook]); |
379 | 392 | ||
380 | do { | 393 | do { |
381 | struct ip6t_entry_target *t; | 394 | const struct ip6t_entry_target *t; |
382 | 395 | ||
383 | IP_NF_ASSERT(e); | 396 | IP_NF_ASSERT(e); |
384 | IP_NF_ASSERT(back); | 397 | IP_NF_ASSERT(back); |
@@ -393,7 +406,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
393 | ntohs(ipv6_hdr(skb)->payload_len) + | 406 | ntohs(ipv6_hdr(skb)->payload_len) + |
394 | sizeof(struct ipv6hdr), 1); | 407 | sizeof(struct ipv6hdr), 1); |
395 | 408 | ||
396 | t = ip6t_get_target(e); | 409 | t = ip6t_get_target_c(e); |
397 | IP_NF_ASSERT(t->u.kernel.target); | 410 | IP_NF_ASSERT(t->u.kernel.target); |
398 | 411 | ||
399 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | 412 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ |
@@ -475,7 +488,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
475 | /* Figures out from what hook each rule can be called: returns 0 if | 488 | /* Figures out from what hook each rule can be called: returns 0 if |
476 | there are loops. Puts hook bitmask in comefrom. */ | 489 | there are loops. Puts hook bitmask in comefrom. */ |
477 | static int | 490 | static int |
478 | mark_source_chains(struct xt_table_info *newinfo, | 491 | mark_source_chains(const struct xt_table_info *newinfo, |
479 | unsigned int valid_hooks, void *entry0) | 492 | unsigned int valid_hooks, void *entry0) |
480 | { | 493 | { |
481 | unsigned int hook; | 494 | unsigned int hook; |
@@ -493,8 +506,8 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
493 | e->counters.pcnt = pos; | 506 | e->counters.pcnt = pos; |
494 | 507 | ||
495 | for (;;) { | 508 | for (;;) { |
496 | struct ip6t_standard_target *t | 509 | const struct ip6t_standard_target *t |
497 | = (void *)ip6t_get_target(e); | 510 | = (void *)ip6t_get_target_c(e); |
498 | int visited = e->comefrom & (1 << hook); | 511 | int visited = e->comefrom & (1 << hook); |
499 | 512 | ||
500 | if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { | 513 | if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { |
@@ -585,13 +598,14 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
585 | } | 598 | } |
586 | 599 | ||
587 | static int | 600 | static int |
588 | cleanup_match(struct ip6t_entry_match *m, unsigned int *i) | 601 | cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i) |
589 | { | 602 | { |
590 | struct xt_mtdtor_param par; | 603 | struct xt_mtdtor_param par; |
591 | 604 | ||
592 | if (i && (*i)-- == 0) | 605 | if (i && (*i)-- == 0) |
593 | return 1; | 606 | return 1; |
594 | 607 | ||
608 | par.net = net; | ||
595 | par.match = m->u.kernel.match; | 609 | par.match = m->u.kernel.match; |
596 | par.matchinfo = m->data; | 610 | par.matchinfo = m->data; |
597 | par.family = NFPROTO_IPV6; | 611 | par.family = NFPROTO_IPV6; |
@@ -602,9 +616,9 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i) | |||
602 | } | 616 | } |
603 | 617 | ||
604 | static int | 618 | static int |
605 | check_entry(struct ip6t_entry *e, const char *name) | 619 | check_entry(const struct ip6t_entry *e, const char *name) |
606 | { | 620 | { |
607 | struct ip6t_entry_target *t; | 621 | const struct ip6t_entry_target *t; |
608 | 622 | ||
609 | if (!ip6_checkentry(&e->ipv6)) { | 623 | if (!ip6_checkentry(&e->ipv6)) { |
610 | duprintf("ip_tables: ip check failed %p %s.\n", e, name); | 624 | duprintf("ip_tables: ip check failed %p %s.\n", e, name); |
@@ -615,7 +629,7 @@ check_entry(struct ip6t_entry *e, const char *name) | |||
615 | e->next_offset) | 629 | e->next_offset) |
616 | return -EINVAL; | 630 | return -EINVAL; |
617 | 631 | ||
618 | t = ip6t_get_target(e); | 632 | t = ip6t_get_target_c(e); |
619 | if (e->target_offset + t->u.target_size > e->next_offset) | 633 | if (e->target_offset + t->u.target_size > e->next_offset) |
620 | return -EINVAL; | 634 | return -EINVAL; |
621 | 635 | ||
@@ -668,10 +682,11 @@ err: | |||
668 | return ret; | 682 | return ret; |
669 | } | 683 | } |
670 | 684 | ||
671 | static int check_target(struct ip6t_entry *e, const char *name) | 685 | static int check_target(struct ip6t_entry *e, struct net *net, const char *name) |
672 | { | 686 | { |
673 | struct ip6t_entry_target *t = ip6t_get_target(e); | 687 | struct ip6t_entry_target *t = ip6t_get_target(e); |
674 | struct xt_tgchk_param par = { | 688 | struct xt_tgchk_param par = { |
689 | .net = net, | ||
675 | .table = name, | 690 | .table = name, |
676 | .entryinfo = e, | 691 | .entryinfo = e, |
677 | .target = t->u.kernel.target, | 692 | .target = t->u.kernel.target, |
@@ -693,8 +708,8 @@ static int check_target(struct ip6t_entry *e, const char *name) | |||
693 | } | 708 | } |
694 | 709 | ||
695 | static int | 710 | static int |
696 | find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | 711 | find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, |
697 | unsigned int *i) | 712 | unsigned int size, unsigned int *i) |
698 | { | 713 | { |
699 | struct ip6t_entry_target *t; | 714 | struct ip6t_entry_target *t; |
700 | struct xt_target *target; | 715 | struct xt_target *target; |
@@ -707,6 +722,7 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
707 | return ret; | 722 | return ret; |
708 | 723 | ||
709 | j = 0; | 724 | j = 0; |
725 | mtpar.net = net; | ||
710 | mtpar.table = name; | 726 | mtpar.table = name; |
711 | mtpar.entryinfo = &e->ipv6; | 727 | mtpar.entryinfo = &e->ipv6; |
712 | mtpar.hook_mask = e->comefrom; | 728 | mtpar.hook_mask = e->comefrom; |
@@ -727,7 +743,7 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
727 | } | 743 | } |
728 | t->u.kernel.target = target; | 744 | t->u.kernel.target = target; |
729 | 745 | ||
730 | ret = check_target(e, name); | 746 | ret = check_target(e, net, name); |
731 | if (ret) | 747 | if (ret) |
732 | goto err; | 748 | goto err; |
733 | 749 | ||
@@ -736,18 +752,18 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
736 | err: | 752 | err: |
737 | module_put(t->u.kernel.target->me); | 753 | module_put(t->u.kernel.target->me); |
738 | cleanup_matches: | 754 | cleanup_matches: |
739 | IP6T_MATCH_ITERATE(e, cleanup_match, &j); | 755 | IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); |
740 | return ret; | 756 | return ret; |
741 | } | 757 | } |
742 | 758 | ||
743 | static bool check_underflow(struct ip6t_entry *e) | 759 | static bool check_underflow(const struct ip6t_entry *e) |
744 | { | 760 | { |
745 | const struct ip6t_entry_target *t; | 761 | const struct ip6t_entry_target *t; |
746 | unsigned int verdict; | 762 | unsigned int verdict; |
747 | 763 | ||
748 | if (!unconditional(&e->ipv6)) | 764 | if (!unconditional(&e->ipv6)) |
749 | return false; | 765 | return false; |
750 | t = ip6t_get_target(e); | 766 | t = ip6t_get_target_c(e); |
751 | if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) | 767 | if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) |
752 | return false; | 768 | return false; |
753 | verdict = ((struct ip6t_standard_target *)t)->verdict; | 769 | verdict = ((struct ip6t_standard_target *)t)->verdict; |
@@ -758,8 +774,8 @@ static bool check_underflow(struct ip6t_entry *e) | |||
758 | static int | 774 | static int |
759 | check_entry_size_and_hooks(struct ip6t_entry *e, | 775 | check_entry_size_and_hooks(struct ip6t_entry *e, |
760 | struct xt_table_info *newinfo, | 776 | struct xt_table_info *newinfo, |
761 | unsigned char *base, | 777 | const unsigned char *base, |
762 | unsigned char *limit, | 778 | const unsigned char *limit, |
763 | const unsigned int *hook_entries, | 779 | const unsigned int *hook_entries, |
764 | const unsigned int *underflows, | 780 | const unsigned int *underflows, |
765 | unsigned int valid_hooks, | 781 | unsigned int valid_hooks, |
@@ -806,7 +822,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, | |||
806 | } | 822 | } |
807 | 823 | ||
808 | static int | 824 | static int |
809 | cleanup_entry(struct ip6t_entry *e, unsigned int *i) | 825 | cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i) |
810 | { | 826 | { |
811 | struct xt_tgdtor_param par; | 827 | struct xt_tgdtor_param par; |
812 | struct ip6t_entry_target *t; | 828 | struct ip6t_entry_target *t; |
@@ -815,9 +831,10 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) | |||
815 | return 1; | 831 | return 1; |
816 | 832 | ||
817 | /* Cleanup all matches */ | 833 | /* Cleanup all matches */ |
818 | IP6T_MATCH_ITERATE(e, cleanup_match, NULL); | 834 | IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL); |
819 | t = ip6t_get_target(e); | 835 | t = ip6t_get_target(e); |
820 | 836 | ||
837 | par.net = net; | ||
821 | par.target = t->u.kernel.target; | 838 | par.target = t->u.kernel.target; |
822 | par.targinfo = t->data; | 839 | par.targinfo = t->data; |
823 | par.family = NFPROTO_IPV6; | 840 | par.family = NFPROTO_IPV6; |
@@ -830,7 +847,8 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) | |||
830 | /* Checks and translates the user-supplied table segment (held in | 847 | /* Checks and translates the user-supplied table segment (held in |
831 | newinfo) */ | 848 | newinfo) */ |
832 | static int | 849 | static int |
833 | translate_table(const char *name, | 850 | translate_table(struct net *net, |
851 | const char *name, | ||
834 | unsigned int valid_hooks, | 852 | unsigned int valid_hooks, |
835 | struct xt_table_info *newinfo, | 853 | struct xt_table_info *newinfo, |
836 | void *entry0, | 854 | void *entry0, |
@@ -892,11 +910,11 @@ translate_table(const char *name, | |||
892 | /* Finally, each sanity check must pass */ | 910 | /* Finally, each sanity check must pass */ |
893 | i = 0; | 911 | i = 0; |
894 | ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, | 912 | ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, |
895 | find_check_entry, name, size, &i); | 913 | find_check_entry, net, name, size, &i); |
896 | 914 | ||
897 | if (ret != 0) { | 915 | if (ret != 0) { |
898 | IP6T_ENTRY_ITERATE(entry0, newinfo->size, | 916 | IP6T_ENTRY_ITERATE(entry0, newinfo->size, |
899 | cleanup_entry, &i); | 917 | cleanup_entry, net, &i); |
900 | return ret; | 918 | return ret; |
901 | } | 919 | } |
902 | 920 | ||
@@ -972,11 +990,11 @@ get_counters(const struct xt_table_info *t, | |||
972 | local_bh_enable(); | 990 | local_bh_enable(); |
973 | } | 991 | } |
974 | 992 | ||
975 | static struct xt_counters *alloc_counters(struct xt_table *table) | 993 | static struct xt_counters *alloc_counters(const struct xt_table *table) |
976 | { | 994 | { |
977 | unsigned int countersize; | 995 | unsigned int countersize; |
978 | struct xt_counters *counters; | 996 | struct xt_counters *counters; |
979 | struct xt_table_info *private = table->private; | 997 | const struct xt_table_info *private = table->private; |
980 | 998 | ||
981 | /* We need atomic snapshot of counters: rest doesn't change | 999 | /* We need atomic snapshot of counters: rest doesn't change |
982 | (other than comefrom, which userspace doesn't care | 1000 | (other than comefrom, which userspace doesn't care |
@@ -994,11 +1012,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table) | |||
994 | 1012 | ||
995 | static int | 1013 | static int |
996 | copy_entries_to_user(unsigned int total_size, | 1014 | copy_entries_to_user(unsigned int total_size, |
997 | struct xt_table *table, | 1015 | const struct xt_table *table, |
998 | void __user *userptr) | 1016 | void __user *userptr) |
999 | { | 1017 | { |
1000 | unsigned int off, num; | 1018 | unsigned int off, num; |
1001 | struct ip6t_entry *e; | 1019 | const struct ip6t_entry *e; |
1002 | struct xt_counters *counters; | 1020 | struct xt_counters *counters; |
1003 | const struct xt_table_info *private = table->private; | 1021 | const struct xt_table_info *private = table->private; |
1004 | int ret = 0; | 1022 | int ret = 0; |
@@ -1050,7 +1068,7 @@ copy_entries_to_user(unsigned int total_size, | |||
1050 | } | 1068 | } |
1051 | } | 1069 | } |
1052 | 1070 | ||
1053 | t = ip6t_get_target(e); | 1071 | t = ip6t_get_target_c(e); |
1054 | if (copy_to_user(userptr + off + e->target_offset | 1072 | if (copy_to_user(userptr + off + e->target_offset |
1055 | + offsetof(struct ip6t_entry_target, | 1073 | + offsetof(struct ip6t_entry_target, |
1056 | u.user.name), | 1074 | u.user.name), |
@@ -1067,7 +1085,7 @@ copy_entries_to_user(unsigned int total_size, | |||
1067 | } | 1085 | } |
1068 | 1086 | ||
1069 | #ifdef CONFIG_COMPAT | 1087 | #ifdef CONFIG_COMPAT |
1070 | static void compat_standard_from_user(void *dst, void *src) | 1088 | static void compat_standard_from_user(void *dst, const void *src) |
1071 | { | 1089 | { |
1072 | int v = *(compat_int_t *)src; | 1090 | int v = *(compat_int_t *)src; |
1073 | 1091 | ||
@@ -1076,7 +1094,7 @@ static void compat_standard_from_user(void *dst, void *src) | |||
1076 | memcpy(dst, &v, sizeof(v)); | 1094 | memcpy(dst, &v, sizeof(v)); |
1077 | } | 1095 | } |
1078 | 1096 | ||
1079 | static int compat_standard_to_user(void __user *dst, void *src) | 1097 | static int compat_standard_to_user(void __user *dst, const void *src) |
1080 | { | 1098 | { |
1081 | compat_int_t cv = *(int *)src; | 1099 | compat_int_t cv = *(int *)src; |
1082 | 1100 | ||
@@ -1086,24 +1104,24 @@ static int compat_standard_to_user(void __user *dst, void *src) | |||
1086 | } | 1104 | } |
1087 | 1105 | ||
1088 | static inline int | 1106 | static inline int |
1089 | compat_calc_match(struct ip6t_entry_match *m, int *size) | 1107 | compat_calc_match(const struct ip6t_entry_match *m, int *size) |
1090 | { | 1108 | { |
1091 | *size += xt_compat_match_offset(m->u.kernel.match); | 1109 | *size += xt_compat_match_offset(m->u.kernel.match); |
1092 | return 0; | 1110 | return 0; |
1093 | } | 1111 | } |
1094 | 1112 | ||
1095 | static int compat_calc_entry(struct ip6t_entry *e, | 1113 | static int compat_calc_entry(const struct ip6t_entry *e, |
1096 | const struct xt_table_info *info, | 1114 | const struct xt_table_info *info, |
1097 | void *base, struct xt_table_info *newinfo) | 1115 | const void *base, struct xt_table_info *newinfo) |
1098 | { | 1116 | { |
1099 | struct ip6t_entry_target *t; | 1117 | const struct ip6t_entry_target *t; |
1100 | unsigned int entry_offset; | 1118 | unsigned int entry_offset; |
1101 | int off, i, ret; | 1119 | int off, i, ret; |
1102 | 1120 | ||
1103 | off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); | 1121 | off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); |
1104 | entry_offset = (void *)e - base; | 1122 | entry_offset = (void *)e - base; |
1105 | IP6T_MATCH_ITERATE(e, compat_calc_match, &off); | 1123 | IP6T_MATCH_ITERATE(e, compat_calc_match, &off); |
1106 | t = ip6t_get_target(e); | 1124 | t = ip6t_get_target_c(e); |
1107 | off += xt_compat_target_offset(t->u.kernel.target); | 1125 | off += xt_compat_target_offset(t->u.kernel.target); |
1108 | newinfo->size -= off; | 1126 | newinfo->size -= off; |
1109 | ret = xt_compat_add_offset(AF_INET6, entry_offset, off); | 1127 | ret = xt_compat_add_offset(AF_INET6, entry_offset, off); |
@@ -1139,7 +1157,8 @@ static int compat_table_info(const struct xt_table_info *info, | |||
1139 | } | 1157 | } |
1140 | #endif | 1158 | #endif |
1141 | 1159 | ||
1142 | static int get_info(struct net *net, void __user *user, int *len, int compat) | 1160 | static int get_info(struct net *net, void __user *user, |
1161 | const int *len, int compat) | ||
1143 | { | 1162 | { |
1144 | char name[IP6T_TABLE_MAXNAMELEN]; | 1163 | char name[IP6T_TABLE_MAXNAMELEN]; |
1145 | struct xt_table *t; | 1164 | struct xt_table *t; |
@@ -1199,7 +1218,8 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) | |||
1199 | } | 1218 | } |
1200 | 1219 | ||
1201 | static int | 1220 | static int |
1202 | get_entries(struct net *net, struct ip6t_get_entries __user *uptr, int *len) | 1221 | get_entries(struct net *net, struct ip6t_get_entries __user *uptr, |
1222 | const int *len) | ||
1203 | { | 1223 | { |
1204 | int ret; | 1224 | int ret; |
1205 | struct ip6t_get_entries get; | 1225 | struct ip6t_get_entries get; |
@@ -1291,7 +1311,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | |||
1291 | /* Decrease module usage counts and free resource */ | 1311 | /* Decrease module usage counts and free resource */ |
1292 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 1312 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1293 | IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, | 1313 | IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, |
1294 | NULL); | 1314 | net, NULL); |
1295 | xt_free_table_info(oldinfo); | 1315 | xt_free_table_info(oldinfo); |
1296 | if (copy_to_user(counters_ptr, counters, | 1316 | if (copy_to_user(counters_ptr, counters, |
1297 | sizeof(struct xt_counters) * num_counters) != 0) | 1317 | sizeof(struct xt_counters) * num_counters) != 0) |
@@ -1310,7 +1330,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | |||
1310 | } | 1330 | } |
1311 | 1331 | ||
1312 | static int | 1332 | static int |
1313 | do_replace(struct net *net, void __user *user, unsigned int len) | 1333 | do_replace(struct net *net, const void __user *user, unsigned int len) |
1314 | { | 1334 | { |
1315 | int ret; | 1335 | int ret; |
1316 | struct ip6t_replace tmp; | 1336 | struct ip6t_replace tmp; |
@@ -1336,7 +1356,7 @@ do_replace(struct net *net, void __user *user, unsigned int len) | |||
1336 | goto free_newinfo; | 1356 | goto free_newinfo; |
1337 | } | 1357 | } |
1338 | 1358 | ||
1339 | ret = translate_table(tmp.name, tmp.valid_hooks, | 1359 | ret = translate_table(net, tmp.name, tmp.valid_hooks, |
1340 | newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, | 1360 | newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, |
1341 | tmp.hook_entry, tmp.underflow); | 1361 | tmp.hook_entry, tmp.underflow); |
1342 | if (ret != 0) | 1362 | if (ret != 0) |
@@ -1351,7 +1371,7 @@ do_replace(struct net *net, void __user *user, unsigned int len) | |||
1351 | return 0; | 1371 | return 0; |
1352 | 1372 | ||
1353 | free_newinfo_untrans: | 1373 | free_newinfo_untrans: |
1354 | IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); | 1374 | IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); |
1355 | free_newinfo: | 1375 | free_newinfo: |
1356 | xt_free_table_info(newinfo); | 1376 | xt_free_table_info(newinfo); |
1357 | return ret; | 1377 | return ret; |
@@ -1371,7 +1391,7 @@ add_counter_to_entry(struct ip6t_entry *e, | |||
1371 | } | 1391 | } |
1372 | 1392 | ||
1373 | static int | 1393 | static int |
1374 | do_add_counters(struct net *net, void __user *user, unsigned int len, | 1394 | do_add_counters(struct net *net, const void __user *user, unsigned int len, |
1375 | int compat) | 1395 | int compat) |
1376 | { | 1396 | { |
1377 | unsigned int i, curcpu; | 1397 | unsigned int i, curcpu; |
@@ -1570,10 +1590,10 @@ static int | |||
1570 | check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | 1590 | check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, |
1571 | struct xt_table_info *newinfo, | 1591 | struct xt_table_info *newinfo, |
1572 | unsigned int *size, | 1592 | unsigned int *size, |
1573 | unsigned char *base, | 1593 | const unsigned char *base, |
1574 | unsigned char *limit, | 1594 | const unsigned char *limit, |
1575 | unsigned int *hook_entries, | 1595 | const unsigned int *hook_entries, |
1576 | unsigned int *underflows, | 1596 | const unsigned int *underflows, |
1577 | unsigned int *i, | 1597 | unsigned int *i, |
1578 | const char *name) | 1598 | const char *name) |
1579 | { | 1599 | { |
@@ -1690,14 +1710,15 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, | |||
1690 | return ret; | 1710 | return ret; |
1691 | } | 1711 | } |
1692 | 1712 | ||
1693 | static int compat_check_entry(struct ip6t_entry *e, const char *name, | 1713 | static int compat_check_entry(struct ip6t_entry *e, struct net *net, |
1694 | unsigned int *i) | 1714 | const char *name, unsigned int *i) |
1695 | { | 1715 | { |
1696 | unsigned int j; | 1716 | unsigned int j; |
1697 | int ret; | 1717 | int ret; |
1698 | struct xt_mtchk_param mtpar; | 1718 | struct xt_mtchk_param mtpar; |
1699 | 1719 | ||
1700 | j = 0; | 1720 | j = 0; |
1721 | mtpar.net = net; | ||
1701 | mtpar.table = name; | 1722 | mtpar.table = name; |
1702 | mtpar.entryinfo = &e->ipv6; | 1723 | mtpar.entryinfo = &e->ipv6; |
1703 | mtpar.hook_mask = e->comefrom; | 1724 | mtpar.hook_mask = e->comefrom; |
@@ -1706,7 +1727,7 @@ static int compat_check_entry(struct ip6t_entry *e, const char *name, | |||
1706 | if (ret) | 1727 | if (ret) |
1707 | goto cleanup_matches; | 1728 | goto cleanup_matches; |
1708 | 1729 | ||
1709 | ret = check_target(e, name); | 1730 | ret = check_target(e, net, name); |
1710 | if (ret) | 1731 | if (ret) |
1711 | goto cleanup_matches; | 1732 | goto cleanup_matches; |
1712 | 1733 | ||
@@ -1714,12 +1735,13 @@ static int compat_check_entry(struct ip6t_entry *e, const char *name, | |||
1714 | return 0; | 1735 | return 0; |
1715 | 1736 | ||
1716 | cleanup_matches: | 1737 | cleanup_matches: |
1717 | IP6T_MATCH_ITERATE(e, cleanup_match, &j); | 1738 | IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); |
1718 | return ret; | 1739 | return ret; |
1719 | } | 1740 | } |
1720 | 1741 | ||
1721 | static int | 1742 | static int |
1722 | translate_compat_table(const char *name, | 1743 | translate_compat_table(struct net *net, |
1744 | const char *name, | ||
1723 | unsigned int valid_hooks, | 1745 | unsigned int valid_hooks, |
1724 | struct xt_table_info **pinfo, | 1746 | struct xt_table_info **pinfo, |
1725 | void **pentry0, | 1747 | void **pentry0, |
@@ -1808,12 +1830,12 @@ translate_compat_table(const char *name, | |||
1808 | 1830 | ||
1809 | i = 0; | 1831 | i = 0; |
1810 | ret = IP6T_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, | 1832 | ret = IP6T_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, |
1811 | name, &i); | 1833 | net, name, &i); |
1812 | if (ret) { | 1834 | if (ret) { |
1813 | j -= i; | 1835 | j -= i; |
1814 | COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, | 1836 | COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, |
1815 | compat_release_entry, &j); | 1837 | compat_release_entry, &j); |
1816 | IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); | 1838 | IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i); |
1817 | xt_free_table_info(newinfo); | 1839 | xt_free_table_info(newinfo); |
1818 | return ret; | 1840 | return ret; |
1819 | } | 1841 | } |
@@ -1868,7 +1890,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) | |||
1868 | goto free_newinfo; | 1890 | goto free_newinfo; |
1869 | } | 1891 | } |
1870 | 1892 | ||
1871 | ret = translate_compat_table(tmp.name, tmp.valid_hooks, | 1893 | ret = translate_compat_table(net, tmp.name, tmp.valid_hooks, |
1872 | &newinfo, &loc_cpu_entry, tmp.size, | 1894 | &newinfo, &loc_cpu_entry, tmp.size, |
1873 | tmp.num_entries, tmp.hook_entry, | 1895 | tmp.num_entries, tmp.hook_entry, |
1874 | tmp.underflow); | 1896 | tmp.underflow); |
@@ -1884,7 +1906,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) | |||
1884 | return 0; | 1906 | return 0; |
1885 | 1907 | ||
1886 | free_newinfo_untrans: | 1908 | free_newinfo_untrans: |
1887 | IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); | 1909 | IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); |
1888 | free_newinfo: | 1910 | free_newinfo: |
1889 | xt_free_table_info(newinfo); | 1911 | xt_free_table_info(newinfo); |
1890 | return ret; | 1912 | return ret; |
@@ -2121,7 +2143,7 @@ struct xt_table *ip6t_register_table(struct net *net, | |||
2121 | loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; | 2143 | loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; |
2122 | memcpy(loc_cpu_entry, repl->entries, repl->size); | 2144 | memcpy(loc_cpu_entry, repl->entries, repl->size); |
2123 | 2145 | ||
2124 | ret = translate_table(table->name, table->valid_hooks, | 2146 | ret = translate_table(net, table->name, table->valid_hooks, |
2125 | newinfo, loc_cpu_entry, repl->size, | 2147 | newinfo, loc_cpu_entry, repl->size, |
2126 | repl->num_entries, | 2148 | repl->num_entries, |
2127 | repl->hook_entry, | 2149 | repl->hook_entry, |
@@ -2142,7 +2164,7 @@ out: | |||
2142 | return ERR_PTR(ret); | 2164 | return ERR_PTR(ret); |
2143 | } | 2165 | } |
2144 | 2166 | ||
2145 | void ip6t_unregister_table(struct xt_table *table) | 2167 | void ip6t_unregister_table(struct net *net, struct xt_table *table) |
2146 | { | 2168 | { |
2147 | struct xt_table_info *private; | 2169 | struct xt_table_info *private; |
2148 | void *loc_cpu_entry; | 2170 | void *loc_cpu_entry; |
@@ -2152,7 +2174,7 @@ void ip6t_unregister_table(struct xt_table *table) | |||
2152 | 2174 | ||
2153 | /* Decrease module usage counts and free resources */ | 2175 | /* Decrease module usage counts and free resources */ |
2154 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; | 2176 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
2155 | IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); | 2177 | IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL); |
2156 | if (private->number > private->initial_entries) | 2178 | if (private->number > private->initial_entries) |
2157 | module_put(table_owner); | 2179 | module_put(table_owner); |
2158 | xt_free_table_info(private); | 2180 | xt_free_table_info(private); |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index ad378efd0eb8..36b72cafc227 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -21,99 +21,26 @@ MODULE_DESCRIPTION("ip6tables filter table"); | |||
21 | (1 << NF_INET_FORWARD) | \ | 21 | (1 << NF_INET_FORWARD) | \ |
22 | (1 << NF_INET_LOCAL_OUT)) | 22 | (1 << NF_INET_LOCAL_OUT)) |
23 | 23 | ||
24 | static struct | ||
25 | { | ||
26 | struct ip6t_replace repl; | ||
27 | struct ip6t_standard entries[3]; | ||
28 | struct ip6t_error term; | ||
29 | } initial_table __net_initdata = { | ||
30 | .repl = { | ||
31 | .name = "filter", | ||
32 | .valid_hooks = FILTER_VALID_HOOKS, | ||
33 | .num_entries = 4, | ||
34 | .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), | ||
35 | .hook_entry = { | ||
36 | [NF_INET_LOCAL_IN] = 0, | ||
37 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard), | ||
38 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 | ||
39 | }, | ||
40 | .underflow = { | ||
41 | [NF_INET_LOCAL_IN] = 0, | ||
42 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard), | ||
43 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 | ||
44 | }, | ||
45 | }, | ||
46 | .entries = { | ||
47 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ | ||
48 | IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ | ||
49 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ | ||
50 | }, | ||
51 | .term = IP6T_ERROR_INIT, /* ERROR */ | ||
52 | }; | ||
53 | |||
54 | static const struct xt_table packet_filter = { | 24 | static const struct xt_table packet_filter = { |
55 | .name = "filter", | 25 | .name = "filter", |
56 | .valid_hooks = FILTER_VALID_HOOKS, | 26 | .valid_hooks = FILTER_VALID_HOOKS, |
57 | .me = THIS_MODULE, | 27 | .me = THIS_MODULE, |
58 | .af = NFPROTO_IPV6, | 28 | .af = NFPROTO_IPV6, |
29 | .priority = NF_IP6_PRI_FILTER, | ||
59 | }; | 30 | }; |
60 | 31 | ||
61 | /* The work comes in here from netfilter.c. */ | 32 | /* The work comes in here from netfilter.c. */ |
62 | static unsigned int | 33 | static unsigned int |
63 | ip6t_in_hook(unsigned int hook, | 34 | ip6table_filter_hook(unsigned int hook, struct sk_buff *skb, |
64 | struct sk_buff *skb, | 35 | const struct net_device *in, const struct net_device *out, |
65 | const struct net_device *in, | 36 | int (*okfn)(struct sk_buff *)) |
66 | const struct net_device *out, | ||
67 | int (*okfn)(struct sk_buff *)) | ||
68 | { | ||
69 | return ip6t_do_table(skb, hook, in, out, | ||
70 | dev_net(in)->ipv6.ip6table_filter); | ||
71 | } | ||
72 | |||
73 | static unsigned int | ||
74 | ip6t_local_out_hook(unsigned int hook, | ||
75 | struct sk_buff *skb, | ||
76 | const struct net_device *in, | ||
77 | const struct net_device *out, | ||
78 | int (*okfn)(struct sk_buff *)) | ||
79 | { | 37 | { |
80 | #if 0 | 38 | const struct net *net = dev_net((in != NULL) ? in : out); |
81 | /* root is playing with raw sockets. */ | ||
82 | if (skb->len < sizeof(struct iphdr) || | ||
83 | ip_hdrlen(skb) < sizeof(struct iphdr)) { | ||
84 | if (net_ratelimit()) | ||
85 | printk("ip6t_hook: happy cracking.\n"); | ||
86 | return NF_ACCEPT; | ||
87 | } | ||
88 | #endif | ||
89 | 39 | ||
90 | return ip6t_do_table(skb, hook, in, out, | 40 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter); |
91 | dev_net(out)->ipv6.ip6table_filter); | ||
92 | } | 41 | } |
93 | 42 | ||
94 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 43 | static struct nf_hook_ops *filter_ops __read_mostly; |
95 | { | ||
96 | .hook = ip6t_in_hook, | ||
97 | .owner = THIS_MODULE, | ||
98 | .pf = NFPROTO_IPV6, | ||
99 | .hooknum = NF_INET_LOCAL_IN, | ||
100 | .priority = NF_IP6_PRI_FILTER, | ||
101 | }, | ||
102 | { | ||
103 | .hook = ip6t_in_hook, | ||
104 | .owner = THIS_MODULE, | ||
105 | .pf = NFPROTO_IPV6, | ||
106 | .hooknum = NF_INET_FORWARD, | ||
107 | .priority = NF_IP6_PRI_FILTER, | ||
108 | }, | ||
109 | { | ||
110 | .hook = ip6t_local_out_hook, | ||
111 | .owner = THIS_MODULE, | ||
112 | .pf = NFPROTO_IPV6, | ||
113 | .hooknum = NF_INET_LOCAL_OUT, | ||
114 | .priority = NF_IP6_PRI_FILTER, | ||
115 | }, | ||
116 | }; | ||
117 | 44 | ||
118 | /* Default to forward because I got too much mail already. */ | 45 | /* Default to forward because I got too much mail already. */ |
119 | static int forward = NF_ACCEPT; | 46 | static int forward = NF_ACCEPT; |
@@ -121,9 +48,18 @@ module_param(forward, bool, 0000); | |||
121 | 48 | ||
122 | static int __net_init ip6table_filter_net_init(struct net *net) | 49 | static int __net_init ip6table_filter_net_init(struct net *net) |
123 | { | 50 | { |
124 | /* Register table */ | 51 | struct ip6t_replace *repl; |
52 | |||
53 | repl = ip6t_alloc_initial_table(&packet_filter); | ||
54 | if (repl == NULL) | ||
55 | return -ENOMEM; | ||
56 | /* Entry 1 is the FORWARD hook */ | ||
57 | ((struct ip6t_standard *)repl->entries)[1].target.verdict = | ||
58 | -forward - 1; | ||
59 | |||
125 | net->ipv6.ip6table_filter = | 60 | net->ipv6.ip6table_filter = |
126 | ip6t_register_table(net, &packet_filter, &initial_table.repl); | 61 | ip6t_register_table(net, &packet_filter, repl); |
62 | kfree(repl); | ||
127 | if (IS_ERR(net->ipv6.ip6table_filter)) | 63 | if (IS_ERR(net->ipv6.ip6table_filter)) |
128 | return PTR_ERR(net->ipv6.ip6table_filter); | 64 | return PTR_ERR(net->ipv6.ip6table_filter); |
129 | return 0; | 65 | return 0; |
@@ -131,7 +67,7 @@ static int __net_init ip6table_filter_net_init(struct net *net) | |||
131 | 67 | ||
132 | static void __net_exit ip6table_filter_net_exit(struct net *net) | 68 | static void __net_exit ip6table_filter_net_exit(struct net *net) |
133 | { | 69 | { |
134 | ip6t_unregister_table(net->ipv6.ip6table_filter); | 70 | ip6t_unregister_table(net, net->ipv6.ip6table_filter); |
135 | } | 71 | } |
136 | 72 | ||
137 | static struct pernet_operations ip6table_filter_net_ops = { | 73 | static struct pernet_operations ip6table_filter_net_ops = { |
@@ -148,17 +84,16 @@ static int __init ip6table_filter_init(void) | |||
148 | return -EINVAL; | 84 | return -EINVAL; |
149 | } | 85 | } |
150 | 86 | ||
151 | /* Entry 1 is the FORWARD hook */ | ||
152 | initial_table.entries[1].target.verdict = -forward - 1; | ||
153 | |||
154 | ret = register_pernet_subsys(&ip6table_filter_net_ops); | 87 | ret = register_pernet_subsys(&ip6table_filter_net_ops); |
155 | if (ret < 0) | 88 | if (ret < 0) |
156 | return ret; | 89 | return ret; |
157 | 90 | ||
158 | /* Register hooks */ | 91 | /* Register hooks */ |
159 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 92 | filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook); |
160 | if (ret < 0) | 93 | if (IS_ERR(filter_ops)) { |
94 | ret = PTR_ERR(filter_ops); | ||
161 | goto cleanup_table; | 95 | goto cleanup_table; |
96 | } | ||
162 | 97 | ||
163 | return ret; | 98 | return ret; |
164 | 99 | ||
@@ -169,7 +104,7 @@ static int __init ip6table_filter_init(void) | |||
169 | 104 | ||
170 | static void __exit ip6table_filter_fini(void) | 105 | static void __exit ip6table_filter_fini(void) |
171 | { | 106 | { |
172 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 107 | xt_hook_unlink(&packet_filter, filter_ops); |
173 | unregister_pernet_subsys(&ip6table_filter_net_ops); | 108 | unregister_pernet_subsys(&ip6table_filter_net_ops); |
174 | } | 109 | } |
175 | 110 | ||
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index a929c19d30e3..7844e557c0ec 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -21,80 +21,17 @@ MODULE_DESCRIPTION("ip6tables mangle table"); | |||
21 | (1 << NF_INET_LOCAL_OUT) | \ | 21 | (1 << NF_INET_LOCAL_OUT) | \ |
22 | (1 << NF_INET_POST_ROUTING)) | 22 | (1 << NF_INET_POST_ROUTING)) |
23 | 23 | ||
24 | static const struct | ||
25 | { | ||
26 | struct ip6t_replace repl; | ||
27 | struct ip6t_standard entries[5]; | ||
28 | struct ip6t_error term; | ||
29 | } initial_table __net_initdata = { | ||
30 | .repl = { | ||
31 | .name = "mangle", | ||
32 | .valid_hooks = MANGLE_VALID_HOOKS, | ||
33 | .num_entries = 6, | ||
34 | .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error), | ||
35 | .hook_entry = { | ||
36 | [NF_INET_PRE_ROUTING] = 0, | ||
37 | [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard), | ||
38 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2, | ||
39 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, | ||
40 | [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, | ||
41 | }, | ||
42 | .underflow = { | ||
43 | [NF_INET_PRE_ROUTING] = 0, | ||
44 | [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard), | ||
45 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2, | ||
46 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, | ||
47 | [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, | ||
48 | }, | ||
49 | }, | ||
50 | .entries = { | ||
51 | IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ | ||
52 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ | ||
53 | IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ | ||
54 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ | ||
55 | IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */ | ||
56 | }, | ||
57 | .term = IP6T_ERROR_INIT, /* ERROR */ | ||
58 | }; | ||
59 | |||
60 | static const struct xt_table packet_mangler = { | 24 | static const struct xt_table packet_mangler = { |
61 | .name = "mangle", | 25 | .name = "mangle", |
62 | .valid_hooks = MANGLE_VALID_HOOKS, | 26 | .valid_hooks = MANGLE_VALID_HOOKS, |
63 | .me = THIS_MODULE, | 27 | .me = THIS_MODULE, |
64 | .af = NFPROTO_IPV6, | 28 | .af = NFPROTO_IPV6, |
29 | .priority = NF_IP6_PRI_MANGLE, | ||
65 | }; | 30 | }; |
66 | 31 | ||
67 | /* The work comes in here from netfilter.c. */ | ||
68 | static unsigned int | ||
69 | ip6t_in_hook(unsigned int hook, | ||
70 | struct sk_buff *skb, | ||
71 | const struct net_device *in, | ||
72 | const struct net_device *out, | ||
73 | int (*okfn)(struct sk_buff *)) | ||
74 | { | ||
75 | return ip6t_do_table(skb, hook, in, out, | ||
76 | dev_net(in)->ipv6.ip6table_mangle); | ||
77 | } | ||
78 | |||
79 | static unsigned int | ||
80 | ip6t_post_routing_hook(unsigned int hook, | ||
81 | struct sk_buff *skb, | ||
82 | const struct net_device *in, | ||
83 | const struct net_device *out, | ||
84 | int (*okfn)(struct sk_buff *)) | ||
85 | { | ||
86 | return ip6t_do_table(skb, hook, in, out, | ||
87 | dev_net(out)->ipv6.ip6table_mangle); | ||
88 | } | ||
89 | |||
90 | static unsigned int | 32 | static unsigned int |
91 | ip6t_local_out_hook(unsigned int hook, | 33 | ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out) |
92 | struct sk_buff *skb, | ||
93 | const struct net_device *in, | ||
94 | const struct net_device *out, | ||
95 | int (*okfn)(struct sk_buff *)) | ||
96 | { | 34 | { |
97 | |||
98 | unsigned int ret; | 35 | unsigned int ret; |
99 | struct in6_addr saddr, daddr; | 36 | struct in6_addr saddr, daddr; |
100 | u_int8_t hop_limit; | 37 | u_int8_t hop_limit; |
@@ -119,7 +56,7 @@ ip6t_local_out_hook(unsigned int hook, | |||
119 | /* flowlabel and prio (includes version, which shouldn't change either */ | 56 | /* flowlabel and prio (includes version, which shouldn't change either */ |
120 | flowlabel = *((u_int32_t *)ipv6_hdr(skb)); | 57 | flowlabel = *((u_int32_t *)ipv6_hdr(skb)); |
121 | 58 | ||
122 | ret = ip6t_do_table(skb, hook, in, out, | 59 | ret = ip6t_do_table(skb, NF_INET_LOCAL_OUT, NULL, out, |
123 | dev_net(out)->ipv6.ip6table_mangle); | 60 | dev_net(out)->ipv6.ip6table_mangle); |
124 | 61 | ||
125 | if (ret != NF_DROP && ret != NF_STOLEN && | 62 | if (ret != NF_DROP && ret != NF_STOLEN && |
@@ -132,49 +69,33 @@ ip6t_local_out_hook(unsigned int hook, | |||
132 | return ret; | 69 | return ret; |
133 | } | 70 | } |
134 | 71 | ||
135 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 72 | /* The work comes in here from netfilter.c. */ |
136 | { | 73 | static unsigned int |
137 | .hook = ip6t_in_hook, | 74 | ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb, |
138 | .owner = THIS_MODULE, | 75 | const struct net_device *in, const struct net_device *out, |
139 | .pf = NFPROTO_IPV6, | 76 | int (*okfn)(struct sk_buff *)) |
140 | .hooknum = NF_INET_PRE_ROUTING, | 77 | { |
141 | .priority = NF_IP6_PRI_MANGLE, | 78 | if (hook == NF_INET_LOCAL_OUT) |
142 | }, | 79 | return ip6t_mangle_out(skb, out); |
143 | { | 80 | if (hook == NF_INET_POST_ROUTING) |
144 | .hook = ip6t_in_hook, | 81 | return ip6t_do_table(skb, hook, in, out, |
145 | .owner = THIS_MODULE, | 82 | dev_net(out)->ipv6.ip6table_mangle); |
146 | .pf = NFPROTO_IPV6, | 83 | /* INPUT/FORWARD */ |
147 | .hooknum = NF_INET_LOCAL_IN, | 84 | return ip6t_do_table(skb, hook, in, out, |
148 | .priority = NF_IP6_PRI_MANGLE, | 85 | dev_net(in)->ipv6.ip6table_mangle); |
149 | }, | 86 | } |
150 | { | ||
151 | .hook = ip6t_in_hook, | ||
152 | .owner = THIS_MODULE, | ||
153 | .pf = NFPROTO_IPV6, | ||
154 | .hooknum = NF_INET_FORWARD, | ||
155 | .priority = NF_IP6_PRI_MANGLE, | ||
156 | }, | ||
157 | { | ||
158 | .hook = ip6t_local_out_hook, | ||
159 | .owner = THIS_MODULE, | ||
160 | .pf = NFPROTO_IPV6, | ||
161 | .hooknum = NF_INET_LOCAL_OUT, | ||
162 | .priority = NF_IP6_PRI_MANGLE, | ||
163 | }, | ||
164 | { | ||
165 | .hook = ip6t_post_routing_hook, | ||
166 | .owner = THIS_MODULE, | ||
167 | .pf = NFPROTO_IPV6, | ||
168 | .hooknum = NF_INET_POST_ROUTING, | ||
169 | .priority = NF_IP6_PRI_MANGLE, | ||
170 | }, | ||
171 | }; | ||
172 | 87 | ||
88 | static struct nf_hook_ops *mangle_ops __read_mostly; | ||
173 | static int __net_init ip6table_mangle_net_init(struct net *net) | 89 | static int __net_init ip6table_mangle_net_init(struct net *net) |
174 | { | 90 | { |
175 | /* Register table */ | 91 | struct ip6t_replace *repl; |
92 | |||
93 | repl = ip6t_alloc_initial_table(&packet_mangler); | ||
94 | if (repl == NULL) | ||
95 | return -ENOMEM; | ||
176 | net->ipv6.ip6table_mangle = | 96 | net->ipv6.ip6table_mangle = |
177 | ip6t_register_table(net, &packet_mangler, &initial_table.repl); | 97 | ip6t_register_table(net, &packet_mangler, repl); |
98 | kfree(repl); | ||
178 | if (IS_ERR(net->ipv6.ip6table_mangle)) | 99 | if (IS_ERR(net->ipv6.ip6table_mangle)) |
179 | return PTR_ERR(net->ipv6.ip6table_mangle); | 100 | return PTR_ERR(net->ipv6.ip6table_mangle); |
180 | return 0; | 101 | return 0; |
@@ -182,7 +103,7 @@ static int __net_init ip6table_mangle_net_init(struct net *net) | |||
182 | 103 | ||
183 | static void __net_exit ip6table_mangle_net_exit(struct net *net) | 104 | static void __net_exit ip6table_mangle_net_exit(struct net *net) |
184 | { | 105 | { |
185 | ip6t_unregister_table(net->ipv6.ip6table_mangle); | 106 | ip6t_unregister_table(net, net->ipv6.ip6table_mangle); |
186 | } | 107 | } |
187 | 108 | ||
188 | static struct pernet_operations ip6table_mangle_net_ops = { | 109 | static struct pernet_operations ip6table_mangle_net_ops = { |
@@ -199,9 +120,11 @@ static int __init ip6table_mangle_init(void) | |||
199 | return ret; | 120 | return ret; |
200 | 121 | ||
201 | /* Register hooks */ | 122 | /* Register hooks */ |
202 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 123 | mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook); |
203 | if (ret < 0) | 124 | if (IS_ERR(mangle_ops)) { |
125 | ret = PTR_ERR(mangle_ops); | ||
204 | goto cleanup_table; | 126 | goto cleanup_table; |
127 | } | ||
205 | 128 | ||
206 | return ret; | 129 | return ret; |
207 | 130 | ||
@@ -212,7 +135,7 @@ static int __init ip6table_mangle_init(void) | |||
212 | 135 | ||
213 | static void __exit ip6table_mangle_fini(void) | 136 | static void __exit ip6table_mangle_fini(void) |
214 | { | 137 | { |
215 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 138 | xt_hook_unlink(&packet_mangler, mangle_ops); |
216 | unregister_pernet_subsys(&ip6table_mangle_net_ops); | 139 | unregister_pernet_subsys(&ip6table_mangle_net_ops); |
217 | } | 140 | } |
218 | 141 | ||
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index ed1a1180f3b3..aef31a29de9e 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -8,85 +8,37 @@ | |||
8 | 8 | ||
9 | #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) | 9 | #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) |
10 | 10 | ||
11 | static const struct | ||
12 | { | ||
13 | struct ip6t_replace repl; | ||
14 | struct ip6t_standard entries[2]; | ||
15 | struct ip6t_error term; | ||
16 | } initial_table __net_initdata = { | ||
17 | .repl = { | ||
18 | .name = "raw", | ||
19 | .valid_hooks = RAW_VALID_HOOKS, | ||
20 | .num_entries = 3, | ||
21 | .size = sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error), | ||
22 | .hook_entry = { | ||
23 | [NF_INET_PRE_ROUTING] = 0, | ||
24 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) | ||
25 | }, | ||
26 | .underflow = { | ||
27 | [NF_INET_PRE_ROUTING] = 0, | ||
28 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) | ||
29 | }, | ||
30 | }, | ||
31 | .entries = { | ||
32 | IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ | ||
33 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ | ||
34 | }, | ||
35 | .term = IP6T_ERROR_INIT, /* ERROR */ | ||
36 | }; | ||
37 | |||
38 | static const struct xt_table packet_raw = { | 11 | static const struct xt_table packet_raw = { |
39 | .name = "raw", | 12 | .name = "raw", |
40 | .valid_hooks = RAW_VALID_HOOKS, | 13 | .valid_hooks = RAW_VALID_HOOKS, |
41 | .me = THIS_MODULE, | 14 | .me = THIS_MODULE, |
42 | .af = NFPROTO_IPV6, | 15 | .af = NFPROTO_IPV6, |
16 | .priority = NF_IP6_PRI_FIRST, | ||
43 | }; | 17 | }; |
44 | 18 | ||
45 | /* The work comes in here from netfilter.c. */ | 19 | /* The work comes in here from netfilter.c. */ |
46 | static unsigned int | 20 | static unsigned int |
47 | ip6t_pre_routing_hook(unsigned int hook, | 21 | ip6table_raw_hook(unsigned int hook, struct sk_buff *skb, |
48 | struct sk_buff *skb, | 22 | const struct net_device *in, const struct net_device *out, |
49 | const struct net_device *in, | 23 | int (*okfn)(struct sk_buff *)) |
50 | const struct net_device *out, | ||
51 | int (*okfn)(struct sk_buff *)) | ||
52 | { | 24 | { |
53 | return ip6t_do_table(skb, hook, in, out, | 25 | const struct net *net = dev_net((in != NULL) ? in : out); |
54 | dev_net(in)->ipv6.ip6table_raw); | ||
55 | } | ||
56 | 26 | ||
57 | static unsigned int | 27 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw); |
58 | ip6t_local_out_hook(unsigned int hook, | ||
59 | struct sk_buff *skb, | ||
60 | const struct net_device *in, | ||
61 | const struct net_device *out, | ||
62 | int (*okfn)(struct sk_buff *)) | ||
63 | { | ||
64 | return ip6t_do_table(skb, hook, in, out, | ||
65 | dev_net(out)->ipv6.ip6table_raw); | ||
66 | } | 28 | } |
67 | 29 | ||
68 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 30 | static struct nf_hook_ops *rawtable_ops __read_mostly; |
69 | { | ||
70 | .hook = ip6t_pre_routing_hook, | ||
71 | .pf = NFPROTO_IPV6, | ||
72 | .hooknum = NF_INET_PRE_ROUTING, | ||
73 | .priority = NF_IP6_PRI_FIRST, | ||
74 | .owner = THIS_MODULE, | ||
75 | }, | ||
76 | { | ||
77 | .hook = ip6t_local_out_hook, | ||
78 | .pf = NFPROTO_IPV6, | ||
79 | .hooknum = NF_INET_LOCAL_OUT, | ||
80 | .priority = NF_IP6_PRI_FIRST, | ||
81 | .owner = THIS_MODULE, | ||
82 | }, | ||
83 | }; | ||
84 | 31 | ||
85 | static int __net_init ip6table_raw_net_init(struct net *net) | 32 | static int __net_init ip6table_raw_net_init(struct net *net) |
86 | { | 33 | { |
87 | /* Register table */ | 34 | struct ip6t_replace *repl; |
35 | |||
36 | repl = ip6t_alloc_initial_table(&packet_raw); | ||
37 | if (repl == NULL) | ||
38 | return -ENOMEM; | ||
88 | net->ipv6.ip6table_raw = | 39 | net->ipv6.ip6table_raw = |
89 | ip6t_register_table(net, &packet_raw, &initial_table.repl); | 40 | ip6t_register_table(net, &packet_raw, repl); |
41 | kfree(repl); | ||
90 | if (IS_ERR(net->ipv6.ip6table_raw)) | 42 | if (IS_ERR(net->ipv6.ip6table_raw)) |
91 | return PTR_ERR(net->ipv6.ip6table_raw); | 43 | return PTR_ERR(net->ipv6.ip6table_raw); |
92 | return 0; | 44 | return 0; |
@@ -94,7 +46,7 @@ static int __net_init ip6table_raw_net_init(struct net *net) | |||
94 | 46 | ||
95 | static void __net_exit ip6table_raw_net_exit(struct net *net) | 47 | static void __net_exit ip6table_raw_net_exit(struct net *net) |
96 | { | 48 | { |
97 | ip6t_unregister_table(net->ipv6.ip6table_raw); | 49 | ip6t_unregister_table(net, net->ipv6.ip6table_raw); |
98 | } | 50 | } |
99 | 51 | ||
100 | static struct pernet_operations ip6table_raw_net_ops = { | 52 | static struct pernet_operations ip6table_raw_net_ops = { |
@@ -111,9 +63,11 @@ static int __init ip6table_raw_init(void) | |||
111 | return ret; | 63 | return ret; |
112 | 64 | ||
113 | /* Register hooks */ | 65 | /* Register hooks */ |
114 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 66 | rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook); |
115 | if (ret < 0) | 67 | if (IS_ERR(rawtable_ops)) { |
68 | ret = PTR_ERR(rawtable_ops); | ||
116 | goto cleanup_table; | 69 | goto cleanup_table; |
70 | } | ||
117 | 71 | ||
118 | return ret; | 72 | return ret; |
119 | 73 | ||
@@ -124,7 +78,7 @@ static int __init ip6table_raw_init(void) | |||
124 | 78 | ||
125 | static void __exit ip6table_raw_fini(void) | 79 | static void __exit ip6table_raw_fini(void) |
126 | { | 80 | { |
127 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 81 | xt_hook_unlink(&packet_raw, rawtable_ops); |
128 | unregister_pernet_subsys(&ip6table_raw_net_ops); | 82 | unregister_pernet_subsys(&ip6table_raw_net_ops); |
129 | } | 83 | } |
130 | 84 | ||
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 41b444c60934..0824d865aa9b 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c | |||
@@ -26,106 +26,37 @@ MODULE_DESCRIPTION("ip6tables security table, for MAC rules"); | |||
26 | (1 << NF_INET_FORWARD) | \ | 26 | (1 << NF_INET_FORWARD) | \ |
27 | (1 << NF_INET_LOCAL_OUT) | 27 | (1 << NF_INET_LOCAL_OUT) |
28 | 28 | ||
29 | static const struct | ||
30 | { | ||
31 | struct ip6t_replace repl; | ||
32 | struct ip6t_standard entries[3]; | ||
33 | struct ip6t_error term; | ||
34 | } initial_table __net_initdata = { | ||
35 | .repl = { | ||
36 | .name = "security", | ||
37 | .valid_hooks = SECURITY_VALID_HOOKS, | ||
38 | .num_entries = 4, | ||
39 | .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), | ||
40 | .hook_entry = { | ||
41 | [NF_INET_LOCAL_IN] = 0, | ||
42 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard), | ||
43 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2, | ||
44 | }, | ||
45 | .underflow = { | ||
46 | [NF_INET_LOCAL_IN] = 0, | ||
47 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard), | ||
48 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2, | ||
49 | }, | ||
50 | }, | ||
51 | .entries = { | ||
52 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ | ||
53 | IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ | ||
54 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ | ||
55 | }, | ||
56 | .term = IP6T_ERROR_INIT, /* ERROR */ | ||
57 | }; | ||
58 | |||
59 | static const struct xt_table security_table = { | 29 | static const struct xt_table security_table = { |
60 | .name = "security", | 30 | .name = "security", |
61 | .valid_hooks = SECURITY_VALID_HOOKS, | 31 | .valid_hooks = SECURITY_VALID_HOOKS, |
62 | .me = THIS_MODULE, | 32 | .me = THIS_MODULE, |
63 | .af = NFPROTO_IPV6, | 33 | .af = NFPROTO_IPV6, |
34 | .priority = NF_IP6_PRI_SECURITY, | ||
64 | }; | 35 | }; |
65 | 36 | ||
66 | static unsigned int | 37 | static unsigned int |
67 | ip6t_local_in_hook(unsigned int hook, | 38 | ip6table_security_hook(unsigned int hook, struct sk_buff *skb, |
68 | struct sk_buff *skb, | 39 | const struct net_device *in, |
69 | const struct net_device *in, | 40 | const struct net_device *out, |
70 | const struct net_device *out, | 41 | int (*okfn)(struct sk_buff *)) |
71 | int (*okfn)(struct sk_buff *)) | ||
72 | { | ||
73 | return ip6t_do_table(skb, hook, in, out, | ||
74 | dev_net(in)->ipv6.ip6table_security); | ||
75 | } | ||
76 | |||
77 | static unsigned int | ||
78 | ip6t_forward_hook(unsigned int hook, | ||
79 | struct sk_buff *skb, | ||
80 | const struct net_device *in, | ||
81 | const struct net_device *out, | ||
82 | int (*okfn)(struct sk_buff *)) | ||
83 | { | 42 | { |
84 | return ip6t_do_table(skb, hook, in, out, | 43 | const struct net *net = dev_net((in != NULL) ? in : out); |
85 | dev_net(in)->ipv6.ip6table_security); | ||
86 | } | ||
87 | 44 | ||
88 | static unsigned int | 45 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security); |
89 | ip6t_local_out_hook(unsigned int hook, | ||
90 | struct sk_buff *skb, | ||
91 | const struct net_device *in, | ||
92 | const struct net_device *out, | ||
93 | int (*okfn)(struct sk_buff *)) | ||
94 | { | ||
95 | /* TBD: handle short packets via raw socket */ | ||
96 | return ip6t_do_table(skb, hook, in, out, | ||
97 | dev_net(out)->ipv6.ip6table_security); | ||
98 | } | 46 | } |
99 | 47 | ||
100 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 48 | static struct nf_hook_ops *sectbl_ops __read_mostly; |
101 | { | ||
102 | .hook = ip6t_local_in_hook, | ||
103 | .owner = THIS_MODULE, | ||
104 | .pf = NFPROTO_IPV6, | ||
105 | .hooknum = NF_INET_LOCAL_IN, | ||
106 | .priority = NF_IP6_PRI_SECURITY, | ||
107 | }, | ||
108 | { | ||
109 | .hook = ip6t_forward_hook, | ||
110 | .owner = THIS_MODULE, | ||
111 | .pf = NFPROTO_IPV6, | ||
112 | .hooknum = NF_INET_FORWARD, | ||
113 | .priority = NF_IP6_PRI_SECURITY, | ||
114 | }, | ||
115 | { | ||
116 | .hook = ip6t_local_out_hook, | ||
117 | .owner = THIS_MODULE, | ||
118 | .pf = NFPROTO_IPV6, | ||
119 | .hooknum = NF_INET_LOCAL_OUT, | ||
120 | .priority = NF_IP6_PRI_SECURITY, | ||
121 | }, | ||
122 | }; | ||
123 | 49 | ||
124 | static int __net_init ip6table_security_net_init(struct net *net) | 50 | static int __net_init ip6table_security_net_init(struct net *net) |
125 | { | 51 | { |
126 | net->ipv6.ip6table_security = | 52 | struct ip6t_replace *repl; |
127 | ip6t_register_table(net, &security_table, &initial_table.repl); | ||
128 | 53 | ||
54 | repl = ip6t_alloc_initial_table(&security_table); | ||
55 | if (repl == NULL) | ||
56 | return -ENOMEM; | ||
57 | net->ipv6.ip6table_security = | ||
58 | ip6t_register_table(net, &security_table, repl); | ||
59 | kfree(repl); | ||
129 | if (IS_ERR(net->ipv6.ip6table_security)) | 60 | if (IS_ERR(net->ipv6.ip6table_security)) |
130 | return PTR_ERR(net->ipv6.ip6table_security); | 61 | return PTR_ERR(net->ipv6.ip6table_security); |
131 | 62 | ||
@@ -134,7 +65,7 @@ static int __net_init ip6table_security_net_init(struct net *net) | |||
134 | 65 | ||
135 | static void __net_exit ip6table_security_net_exit(struct net *net) | 66 | static void __net_exit ip6table_security_net_exit(struct net *net) |
136 | { | 67 | { |
137 | ip6t_unregister_table(net->ipv6.ip6table_security); | 68 | ip6t_unregister_table(net, net->ipv6.ip6table_security); |
138 | } | 69 | } |
139 | 70 | ||
140 | static struct pernet_operations ip6table_security_net_ops = { | 71 | static struct pernet_operations ip6table_security_net_ops = { |
@@ -150,9 +81,11 @@ static int __init ip6table_security_init(void) | |||
150 | if (ret < 0) | 81 | if (ret < 0) |
151 | return ret; | 82 | return ret; |
152 | 83 | ||
153 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 84 | sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook); |
154 | if (ret < 0) | 85 | if (IS_ERR(sectbl_ops)) { |
86 | ret = PTR_ERR(sectbl_ops); | ||
155 | goto cleanup_table; | 87 | goto cleanup_table; |
88 | } | ||
156 | 89 | ||
157 | return ret; | 90 | return ret; |
158 | 91 | ||
@@ -163,7 +96,7 @@ cleanup_table: | |||
163 | 96 | ||
164 | static void __exit ip6table_security_fini(void) | 97 | static void __exit ip6table_security_fini(void) |
165 | { | 98 | { |
166 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 99 | xt_hook_unlink(&security_table, sectbl_ops); |
167 | unregister_pernet_subsys(&ip6table_security_net_ops); | 100 | unregister_pernet_subsys(&ip6table_security_net_ops); |
168 | } | 101 | } |
169 | 102 | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 0956ebabbff2..996c3f41fecd 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <net/netfilter/nf_conntrack_l4proto.h> | 27 | #include <net/netfilter/nf_conntrack_l4proto.h> |
28 | #include <net/netfilter/nf_conntrack_l3proto.h> | 28 | #include <net/netfilter/nf_conntrack_l3proto.h> |
29 | #include <net/netfilter/nf_conntrack_core.h> | 29 | #include <net/netfilter/nf_conntrack_core.h> |
30 | #include <net/netfilter/nf_conntrack_zones.h> | ||
30 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | 31 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
31 | #include <net/netfilter/nf_log.h> | 32 | #include <net/netfilter/nf_log.h> |
32 | 33 | ||
@@ -191,15 +192,20 @@ out: | |||
191 | static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, | 192 | static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, |
192 | struct sk_buff *skb) | 193 | struct sk_buff *skb) |
193 | { | 194 | { |
195 | u16 zone = NF_CT_DEFAULT_ZONE; | ||
196 | |||
197 | if (skb->nfct) | ||
198 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); | ||
199 | |||
194 | #ifdef CONFIG_BRIDGE_NETFILTER | 200 | #ifdef CONFIG_BRIDGE_NETFILTER |
195 | if (skb->nf_bridge && | 201 | if (skb->nf_bridge && |
196 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) | 202 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) |
197 | return IP6_DEFRAG_CONNTRACK_BRIDGE_IN; | 203 | return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone; |
198 | #endif | 204 | #endif |
199 | if (hooknum == NF_INET_PRE_ROUTING) | 205 | if (hooknum == NF_INET_PRE_ROUTING) |
200 | return IP6_DEFRAG_CONNTRACK_IN; | 206 | return IP6_DEFRAG_CONNTRACK_IN + zone; |
201 | else | 207 | else |
202 | return IP6_DEFRAG_CONNTRACK_OUT; | 208 | return IP6_DEFRAG_CONNTRACK_OUT + zone; |
203 | 209 | ||
204 | } | 210 | } |
205 | 211 | ||
@@ -212,7 +218,7 @@ static unsigned int ipv6_defrag(unsigned int hooknum, | |||
212 | struct sk_buff *reasm; | 218 | struct sk_buff *reasm; |
213 | 219 | ||
214 | /* Previously seen (loopback)? */ | 220 | /* Previously seen (loopback)? */ |
215 | if (skb->nfct) | 221 | if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) |
216 | return NF_ACCEPT; | 222 | return NF_ACCEPT; |
217 | 223 | ||
218 | reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); | 224 | reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index c7b8bd1d7984..9be81776415e 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <net/netfilter/nf_conntrack_tuple.h> | 23 | #include <net/netfilter/nf_conntrack_tuple.h> |
24 | #include <net/netfilter/nf_conntrack_l4proto.h> | 24 | #include <net/netfilter/nf_conntrack_l4proto.h> |
25 | #include <net/netfilter/nf_conntrack_core.h> | 25 | #include <net/netfilter/nf_conntrack_core.h> |
26 | #include <net/netfilter/nf_conntrack_zones.h> | ||
26 | #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> | 27 | #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> |
27 | #include <net/netfilter/nf_log.h> | 28 | #include <net/netfilter/nf_log.h> |
28 | 29 | ||
@@ -128,7 +129,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
128 | } | 129 | } |
129 | 130 | ||
130 | static int | 131 | static int |
131 | icmpv6_error_message(struct net *net, | 132 | icmpv6_error_message(struct net *net, struct nf_conn *tmpl, |
132 | struct sk_buff *skb, | 133 | struct sk_buff *skb, |
133 | unsigned int icmp6off, | 134 | unsigned int icmp6off, |
134 | enum ip_conntrack_info *ctinfo, | 135 | enum ip_conntrack_info *ctinfo, |
@@ -137,6 +138,7 @@ icmpv6_error_message(struct net *net, | |||
137 | struct nf_conntrack_tuple intuple, origtuple; | 138 | struct nf_conntrack_tuple intuple, origtuple; |
138 | const struct nf_conntrack_tuple_hash *h; | 139 | const struct nf_conntrack_tuple_hash *h; |
139 | const struct nf_conntrack_l4proto *inproto; | 140 | const struct nf_conntrack_l4proto *inproto; |
141 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; | ||
140 | 142 | ||
141 | NF_CT_ASSERT(skb->nfct == NULL); | 143 | NF_CT_ASSERT(skb->nfct == NULL); |
142 | 144 | ||
@@ -163,7 +165,7 @@ icmpv6_error_message(struct net *net, | |||
163 | 165 | ||
164 | *ctinfo = IP_CT_RELATED; | 166 | *ctinfo = IP_CT_RELATED; |
165 | 167 | ||
166 | h = nf_conntrack_find_get(net, &intuple); | 168 | h = nf_conntrack_find_get(net, zone, &intuple); |
167 | if (!h) { | 169 | if (!h) { |
168 | pr_debug("icmpv6_error: no match\n"); | 170 | pr_debug("icmpv6_error: no match\n"); |
169 | return -NF_ACCEPT; | 171 | return -NF_ACCEPT; |
@@ -179,7 +181,8 @@ icmpv6_error_message(struct net *net, | |||
179 | } | 181 | } |
180 | 182 | ||
181 | static int | 183 | static int |
182 | icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, | 184 | icmpv6_error(struct net *net, struct nf_conn *tmpl, |
185 | struct sk_buff *skb, unsigned int dataoff, | ||
183 | enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum) | 186 | enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum) |
184 | { | 187 | { |
185 | const struct icmp6hdr *icmp6h; | 188 | const struct icmp6hdr *icmp6h; |
@@ -215,7 +218,7 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, | |||
215 | if (icmp6h->icmp6_type >= 128) | 218 | if (icmp6h->icmp6_type >= 128) |
216 | return NF_ACCEPT; | 219 | return NF_ACCEPT; |
217 | 220 | ||
218 | return icmpv6_error_message(net, skb, dataoff, ctinfo, hooknum); | 221 | return icmpv6_error_message(net, tmpl, skb, dataoff, ctinfo, hooknum); |
219 | } | 222 | } |
220 | 223 | ||
221 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 224 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 624a54832a7c..ad1fcda6898b 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -45,9 +45,6 @@ | |||
45 | #include <linux/kernel.h> | 45 | #include <linux/kernel.h> |
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | 47 | ||
48 | #define NF_CT_FRAG6_HIGH_THRESH 262144 /* == 256*1024 */ | ||
49 | #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ | ||
50 | #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT | ||
51 | 48 | ||
52 | struct nf_ct_frag6_skb_cb | 49 | struct nf_ct_frag6_skb_cb |
53 | { | 50 | { |
@@ -670,8 +667,8 @@ int nf_ct_frag6_init(void) | |||
670 | nf_frags.frag_expire = nf_ct_frag6_expire; | 667 | nf_frags.frag_expire = nf_ct_frag6_expire; |
671 | nf_frags.secret_interval = 10 * 60 * HZ; | 668 | nf_frags.secret_interval = 10 * 60 * HZ; |
672 | nf_init_frags.timeout = IPV6_FRAG_TIMEOUT; | 669 | nf_init_frags.timeout = IPV6_FRAG_TIMEOUT; |
673 | nf_init_frags.high_thresh = 256 * 1024; | 670 | nf_init_frags.high_thresh = IPV6_FRAG_HIGH_THRESH; |
674 | nf_init_frags.low_thresh = 192 * 1024; | 671 | nf_init_frags.low_thresh = IPV6_FRAG_LOW_THRESH; |
675 | inet_frags_init_net(&nf_init_frags); | 672 | inet_frags_init_net(&nf_init_frags); |
676 | inet_frags_init(&nf_frags); | 673 | inet_frags_init(&nf_frags); |
677 | 674 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index fe27eb4264d6..b2847ed6a7d9 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -742,8 +742,8 @@ static inline void ip6_frags_sysctl_unregister(void) | |||
742 | 742 | ||
743 | static int __net_init ipv6_frags_init_net(struct net *net) | 743 | static int __net_init ipv6_frags_init_net(struct net *net) |
744 | { | 744 | { |
745 | net->ipv6.frags.high_thresh = 256 * 1024; | 745 | net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; |
746 | net->ipv6.frags.low_thresh = 192 * 1024; | 746 | net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH; |
747 | net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT; | 747 | net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT; |
748 | 748 | ||
749 | inet_frags_init_net(&net->ipv6.frags); | 749 | inet_frags_init_net(&net->ipv6.frags); |