diff options
-rw-r--r-- | include/linux/netfilter/x_tables.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/arptable_filter.c | 33 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_filter.c | 33 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_mangle.c | 47 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_raw.c | 27 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_security.c | 33 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_filter.c | 33 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_mangle.c | 48 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_raw.c | 26 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_security.c | 33 | ||||
-rw-r--r-- | net/netfilter/x_tables.c | 54 |
11 files changed, 121 insertions, 250 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 365fabe1b16e..fdd3342c1235 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h | |||
@@ -361,6 +361,7 @@ struct xt_table { | |||
361 | struct module *me; | 361 | struct module *me; |
362 | 362 | ||
363 | u_int8_t af; /* address/protocol family */ | 363 | u_int8_t af; /* address/protocol family */ |
364 | int priority; /* hook order */ | ||
364 | 365 | ||
365 | /* A unique name... */ | 366 | /* A unique name... */ |
366 | const char name[XT_TABLE_MAXNAMELEN]; | 367 | const char name[XT_TABLE_MAXNAMELEN]; |
@@ -522,6 +523,9 @@ static inline unsigned long ifname_compare_aligned(const char *_a, | |||
522 | return ret; | 523 | return ret; |
523 | } | 524 | } |
524 | 525 | ||
526 | extern struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *); | ||
527 | extern void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *); | ||
528 | |||
525 | #ifdef CONFIG_COMPAT | 529 | #ifdef CONFIG_COMPAT |
526 | #include <net/compat.h> | 530 | #include <net/compat.h> |
527 | 531 | ||
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index deeda9b2cf05..b361de0dac4c 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c | |||
@@ -50,6 +50,7 @@ static const struct xt_table packet_filter = { | |||
50 | .valid_hooks = FILTER_VALID_HOOKS, | 50 | .valid_hooks = FILTER_VALID_HOOKS, |
51 | .me = THIS_MODULE, | 51 | .me = THIS_MODULE, |
52 | .af = NFPROTO_ARP, | 52 | .af = NFPROTO_ARP, |
53 | .priority = NF_IP_PRI_FILTER, | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | /* The work comes in here from netfilter.c */ | 56 | /* The work comes in here from netfilter.c */ |
@@ -63,29 +64,7 @@ arptable_filter_hook(unsigned int hook, struct sk_buff *skb, | |||
63 | return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter); | 64 | return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter); |
64 | } | 65 | } |
65 | 66 | ||
66 | static struct nf_hook_ops arpt_ops[] __read_mostly = { | 67 | static struct nf_hook_ops *arpfilter_ops __read_mostly; |
67 | { | ||
68 | .hook = arptable_filter_hook, | ||
69 | .owner = THIS_MODULE, | ||
70 | .pf = NFPROTO_ARP, | ||
71 | .hooknum = NF_ARP_IN, | ||
72 | .priority = NF_IP_PRI_FILTER, | ||
73 | }, | ||
74 | { | ||
75 | .hook = arptable_filter_hook, | ||
76 | .owner = THIS_MODULE, | ||
77 | .pf = NFPROTO_ARP, | ||
78 | .hooknum = NF_ARP_OUT, | ||
79 | .priority = NF_IP_PRI_FILTER, | ||
80 | }, | ||
81 | { | ||
82 | .hook = arptable_filter_hook, | ||
83 | .owner = THIS_MODULE, | ||
84 | .pf = NFPROTO_ARP, | ||
85 | .hooknum = NF_ARP_FORWARD, | ||
86 | .priority = NF_IP_PRI_FILTER, | ||
87 | }, | ||
88 | }; | ||
89 | 68 | ||
90 | static int __net_init arptable_filter_net_init(struct net *net) | 69 | static int __net_init arptable_filter_net_init(struct net *net) |
91 | { | 70 | { |
@@ -115,9 +94,11 @@ static int __init arptable_filter_init(void) | |||
115 | if (ret < 0) | 94 | if (ret < 0) |
116 | return ret; | 95 | return ret; |
117 | 96 | ||
118 | ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); | 97 | arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook); |
119 | if (ret < 0) | 98 | if (IS_ERR(arpfilter_ops)) { |
99 | ret = PTR_ERR(arpfilter_ops); | ||
120 | goto cleanup_table; | 100 | goto cleanup_table; |
101 | } | ||
121 | return ret; | 102 | return ret; |
122 | 103 | ||
123 | cleanup_table: | 104 | cleanup_table: |
@@ -127,7 +108,7 @@ cleanup_table: | |||
127 | 108 | ||
128 | static void __exit arptable_filter_fini(void) | 109 | static void __exit arptable_filter_fini(void) |
129 | { | 110 | { |
130 | nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); | 111 | xt_hook_unlink(&packet_filter, arpfilter_ops); |
131 | unregister_pernet_subsys(&arptable_filter_net_ops); | 112 | unregister_pernet_subsys(&arptable_filter_net_ops); |
132 | } | 113 | } |
133 | 114 | ||
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 1bfeaae6f624..c14bb85db1d9 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -58,6 +58,7 @@ static const struct xt_table packet_filter = { | |||
58 | .valid_hooks = FILTER_VALID_HOOKS, | 58 | .valid_hooks = FILTER_VALID_HOOKS, |
59 | .me = THIS_MODULE, | 59 | .me = THIS_MODULE, |
60 | .af = NFPROTO_IPV4, | 60 | .af = NFPROTO_IPV4, |
61 | .priority = NF_IP_PRI_FILTER, | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | static unsigned int | 64 | static unsigned int |
@@ -77,29 +78,7 @@ iptable_filter_hook(unsigned int hook, struct sk_buff *skb, | |||
77 | return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter); | 78 | return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter); |
78 | } | 79 | } |
79 | 80 | ||
80 | static struct nf_hook_ops ipt_ops[] __read_mostly = { | 81 | static struct nf_hook_ops *filter_ops __read_mostly; |
81 | { | ||
82 | .hook = iptable_filter_hook, | ||
83 | .owner = THIS_MODULE, | ||
84 | .pf = NFPROTO_IPV4, | ||
85 | .hooknum = NF_INET_LOCAL_IN, | ||
86 | .priority = NF_IP_PRI_FILTER, | ||
87 | }, | ||
88 | { | ||
89 | .hook = iptable_filter_hook, | ||
90 | .owner = THIS_MODULE, | ||
91 | .pf = NFPROTO_IPV4, | ||
92 | .hooknum = NF_INET_FORWARD, | ||
93 | .priority = NF_IP_PRI_FILTER, | ||
94 | }, | ||
95 | { | ||
96 | .hook = iptable_filter_hook, | ||
97 | .owner = THIS_MODULE, | ||
98 | .pf = NFPROTO_IPV4, | ||
99 | .hooknum = NF_INET_LOCAL_OUT, | ||
100 | .priority = NF_IP_PRI_FILTER, | ||
101 | }, | ||
102 | }; | ||
103 | 82 | ||
104 | /* Default to forward because I got too much mail already. */ | 83 | /* Default to forward because I got too much mail already. */ |
105 | static int forward = NF_ACCEPT; | 84 | static int forward = NF_ACCEPT; |
@@ -142,9 +121,11 @@ static int __init iptable_filter_init(void) | |||
142 | return ret; | 121 | return ret; |
143 | 122 | ||
144 | /* Register hooks */ | 123 | /* Register hooks */ |
145 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 124 | filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook); |
146 | if (ret < 0) | 125 | if (IS_ERR(filter_ops)) { |
126 | ret = PTR_ERR(filter_ops); | ||
147 | goto cleanup_table; | 127 | goto cleanup_table; |
128 | } | ||
148 | 129 | ||
149 | return ret; | 130 | return ret; |
150 | 131 | ||
@@ -155,7 +136,7 @@ static int __init iptable_filter_init(void) | |||
155 | 136 | ||
156 | static void __exit iptable_filter_fini(void) | 137 | static void __exit iptable_filter_fini(void) |
157 | { | 138 | { |
158 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 139 | xt_hook_unlink(&packet_filter, filter_ops); |
159 | unregister_pernet_subsys(&iptable_filter_net_ops); | 140 | unregister_pernet_subsys(&iptable_filter_net_ops); |
160 | } | 141 | } |
161 | 142 | ||
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 4e699cd275c6..2355a229f8ee 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -69,6 +69,7 @@ static const struct xt_table packet_mangler = { | |||
69 | .valid_hooks = MANGLE_VALID_HOOKS, | 69 | .valid_hooks = MANGLE_VALID_HOOKS, |
70 | .me = THIS_MODULE, | 70 | .me = THIS_MODULE, |
71 | .af = NFPROTO_IPV4, | 71 | .af = NFPROTO_IPV4, |
72 | .priority = NF_IP_PRI_MANGLE, | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | static unsigned int | 75 | static unsigned int |
@@ -129,43 +130,7 @@ iptable_mangle_hook(unsigned int hook, | |||
129 | dev_net(in)->ipv4.iptable_mangle); | 130 | dev_net(in)->ipv4.iptable_mangle); |
130 | } | 131 | } |
131 | 132 | ||
132 | static struct nf_hook_ops ipt_ops[] __read_mostly = { | 133 | static struct nf_hook_ops *mangle_ops __read_mostly; |
133 | { | ||
134 | .hook = iptable_mangle_hook, | ||
135 | .owner = THIS_MODULE, | ||
136 | .pf = NFPROTO_IPV4, | ||
137 | .hooknum = NF_INET_PRE_ROUTING, | ||
138 | .priority = NF_IP_PRI_MANGLE, | ||
139 | }, | ||
140 | { | ||
141 | .hook = iptable_mangle_hook, | ||
142 | .owner = THIS_MODULE, | ||
143 | .pf = NFPROTO_IPV4, | ||
144 | .hooknum = NF_INET_LOCAL_IN, | ||
145 | .priority = NF_IP_PRI_MANGLE, | ||
146 | }, | ||
147 | { | ||
148 | .hook = iptable_mangle_hook, | ||
149 | .owner = THIS_MODULE, | ||
150 | .pf = NFPROTO_IPV4, | ||
151 | .hooknum = NF_INET_FORWARD, | ||
152 | .priority = NF_IP_PRI_MANGLE, | ||
153 | }, | ||
154 | { | ||
155 | .hook = iptable_mangle_hook, | ||
156 | .owner = THIS_MODULE, | ||
157 | .pf = NFPROTO_IPV4, | ||
158 | .hooknum = NF_INET_LOCAL_OUT, | ||
159 | .priority = NF_IP_PRI_MANGLE, | ||
160 | }, | ||
161 | { | ||
162 | .hook = iptable_mangle_hook, | ||
163 | .owner = THIS_MODULE, | ||
164 | .pf = NFPROTO_IPV4, | ||
165 | .hooknum = NF_INET_POST_ROUTING, | ||
166 | .priority = NF_IP_PRI_MANGLE, | ||
167 | }, | ||
168 | }; | ||
169 | 134 | ||
170 | static int __net_init iptable_mangle_net_init(struct net *net) | 135 | static int __net_init iptable_mangle_net_init(struct net *net) |
171 | { | 136 | { |
@@ -196,9 +161,11 @@ static int __init iptable_mangle_init(void) | |||
196 | return ret; | 161 | return ret; |
197 | 162 | ||
198 | /* Register hooks */ | 163 | /* Register hooks */ |
199 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 164 | mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook); |
200 | if (ret < 0) | 165 | if (IS_ERR(mangle_ops)) { |
166 | ret = PTR_ERR(mangle_ops); | ||
201 | goto cleanup_table; | 167 | goto cleanup_table; |
168 | } | ||
202 | 169 | ||
203 | return ret; | 170 | return ret; |
204 | 171 | ||
@@ -209,7 +176,7 @@ static int __init iptable_mangle_init(void) | |||
209 | 176 | ||
210 | static void __exit iptable_mangle_fini(void) | 177 | static void __exit iptable_mangle_fini(void) |
211 | { | 178 | { |
212 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 179 | xt_hook_unlink(&packet_mangler, mangle_ops); |
213 | unregister_pernet_subsys(&iptable_mangle_net_ops); | 180 | unregister_pernet_subsys(&iptable_mangle_net_ops); |
214 | } | 181 | } |
215 | 182 | ||
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index d16e43777c31..62a99154f14c 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
@@ -41,6 +41,7 @@ static const struct xt_table packet_raw = { | |||
41 | .valid_hooks = RAW_VALID_HOOKS, | 41 | .valid_hooks = RAW_VALID_HOOKS, |
42 | .me = THIS_MODULE, | 42 | .me = THIS_MODULE, |
43 | .af = NFPROTO_IPV4, | 43 | .af = NFPROTO_IPV4, |
44 | .priority = NF_IP_PRI_RAW, | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | /* The work comes in here from netfilter.c. */ | 47 | /* The work comes in here from netfilter.c. */ |
@@ -61,23 +62,7 @@ iptable_raw_hook(unsigned int hook, struct sk_buff *skb, | |||
61 | return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw); | 62 | return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw); |
62 | } | 63 | } |
63 | 64 | ||
64 | /* 'raw' is the very first table. */ | 65 | static struct nf_hook_ops *rawtable_ops __read_mostly; |
65 | static struct nf_hook_ops ipt_ops[] __read_mostly = { | ||
66 | { | ||
67 | .hook = iptable_raw_hook, | ||
68 | .pf = NFPROTO_IPV4, | ||
69 | .hooknum = NF_INET_PRE_ROUTING, | ||
70 | .priority = NF_IP_PRI_RAW, | ||
71 | .owner = THIS_MODULE, | ||
72 | }, | ||
73 | { | ||
74 | .hook = iptable_raw_hook, | ||
75 | .pf = NFPROTO_IPV4, | ||
76 | .hooknum = NF_INET_LOCAL_OUT, | ||
77 | .priority = NF_IP_PRI_RAW, | ||
78 | .owner = THIS_MODULE, | ||
79 | }, | ||
80 | }; | ||
81 | 66 | ||
82 | static int __net_init iptable_raw_net_init(struct net *net) | 67 | static int __net_init iptable_raw_net_init(struct net *net) |
83 | { | 68 | { |
@@ -108,9 +93,11 @@ static int __init iptable_raw_init(void) | |||
108 | return ret; | 93 | return ret; |
109 | 94 | ||
110 | /* Register hooks */ | 95 | /* Register hooks */ |
111 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 96 | rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook); |
112 | if (ret < 0) | 97 | if (IS_ERR(rawtable_ops)) { |
98 | ret = PTR_ERR(rawtable_ops); | ||
113 | goto cleanup_table; | 99 | goto cleanup_table; |
100 | } | ||
114 | 101 | ||
115 | return ret; | 102 | return ret; |
116 | 103 | ||
@@ -121,7 +108,7 @@ static int __init iptable_raw_init(void) | |||
121 | 108 | ||
122 | static void __exit iptable_raw_fini(void) | 109 | static void __exit iptable_raw_fini(void) |
123 | { | 110 | { |
124 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 111 | xt_hook_unlink(&packet_raw, rawtable_ops); |
125 | unregister_pernet_subsys(&iptable_raw_net_ops); | 112 | unregister_pernet_subsys(&iptable_raw_net_ops); |
126 | } | 113 | } |
127 | 114 | ||
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index 324505aaaa73..b1bf3ca2c6c7 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c | |||
@@ -62,6 +62,7 @@ static const struct xt_table security_table = { | |||
62 | .valid_hooks = SECURITY_VALID_HOOKS, | 62 | .valid_hooks = SECURITY_VALID_HOOKS, |
63 | .me = THIS_MODULE, | 63 | .me = THIS_MODULE, |
64 | .af = NFPROTO_IPV4, | 64 | .af = NFPROTO_IPV4, |
65 | .priority = NF_IP_PRI_SECURITY, | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | static unsigned int | 68 | static unsigned int |
@@ -82,29 +83,7 @@ iptable_security_hook(unsigned int hook, struct sk_buff *skb, | |||
82 | return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security); | 83 | return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security); |
83 | } | 84 | } |
84 | 85 | ||
85 | static struct nf_hook_ops ipt_ops[] __read_mostly = { | 86 | static struct nf_hook_ops *sectbl_ops __read_mostly; |
86 | { | ||
87 | .hook = iptable_security_hook, | ||
88 | .owner = THIS_MODULE, | ||
89 | .pf = NFPROTO_IPV4, | ||
90 | .hooknum = NF_INET_LOCAL_IN, | ||
91 | .priority = NF_IP_PRI_SECURITY, | ||
92 | }, | ||
93 | { | ||
94 | .hook = iptable_security_hook, | ||
95 | .owner = THIS_MODULE, | ||
96 | .pf = NFPROTO_IPV4, | ||
97 | .hooknum = NF_INET_FORWARD, | ||
98 | .priority = NF_IP_PRI_SECURITY, | ||
99 | }, | ||
100 | { | ||
101 | .hook = iptable_security_hook, | ||
102 | .owner = THIS_MODULE, | ||
103 | .pf = NFPROTO_IPV4, | ||
104 | .hooknum = NF_INET_LOCAL_OUT, | ||
105 | .priority = NF_IP_PRI_SECURITY, | ||
106 | }, | ||
107 | }; | ||
108 | 87 | ||
109 | static int __net_init iptable_security_net_init(struct net *net) | 88 | static int __net_init iptable_security_net_init(struct net *net) |
110 | { | 89 | { |
@@ -135,9 +114,11 @@ static int __init iptable_security_init(void) | |||
135 | if (ret < 0) | 114 | if (ret < 0) |
136 | return ret; | 115 | return ret; |
137 | 116 | ||
138 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 117 | sectbl_ops = xt_hook_link(&security_table, iptable_security_hook); |
139 | if (ret < 0) | 118 | if (IS_ERR(sectbl_ops)) { |
119 | ret = PTR_ERR(sectbl_ops); | ||
140 | goto cleanup_table; | 120 | goto cleanup_table; |
121 | } | ||
141 | 122 | ||
142 | return ret; | 123 | return ret; |
143 | 124 | ||
@@ -148,7 +129,7 @@ cleanup_table: | |||
148 | 129 | ||
149 | static void __exit iptable_security_fini(void) | 130 | static void __exit iptable_security_fini(void) |
150 | { | 131 | { |
151 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 132 | xt_hook_unlink(&security_table, sectbl_ops); |
152 | unregister_pernet_subsys(&iptable_security_net_ops); | 133 | unregister_pernet_subsys(&iptable_security_net_ops); |
153 | } | 134 | } |
154 | 135 | ||
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 866f34ae236b..6e95d0614ca9 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -56,6 +56,7 @@ static const struct xt_table packet_filter = { | |||
56 | .valid_hooks = FILTER_VALID_HOOKS, | 56 | .valid_hooks = FILTER_VALID_HOOKS, |
57 | .me = THIS_MODULE, | 57 | .me = THIS_MODULE, |
58 | .af = NFPROTO_IPV6, | 58 | .af = NFPROTO_IPV6, |
59 | .priority = NF_IP6_PRI_FILTER, | ||
59 | }; | 60 | }; |
60 | 61 | ||
61 | /* The work comes in here from netfilter.c. */ | 62 | /* The work comes in here from netfilter.c. */ |
@@ -69,29 +70,7 @@ ip6table_filter_hook(unsigned int hook, struct sk_buff *skb, | |||
69 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter); | 70 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter); |
70 | } | 71 | } |
71 | 72 | ||
72 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 73 | static struct nf_hook_ops *filter_ops __read_mostly; |
73 | { | ||
74 | .hook = ip6table_filter_hook, | ||
75 | .owner = THIS_MODULE, | ||
76 | .pf = NFPROTO_IPV6, | ||
77 | .hooknum = NF_INET_LOCAL_IN, | ||
78 | .priority = NF_IP6_PRI_FILTER, | ||
79 | }, | ||
80 | { | ||
81 | .hook = ip6table_filter_hook, | ||
82 | .owner = THIS_MODULE, | ||
83 | .pf = NFPROTO_IPV6, | ||
84 | .hooknum = NF_INET_FORWARD, | ||
85 | .priority = NF_IP6_PRI_FILTER, | ||
86 | }, | ||
87 | { | ||
88 | .hook = ip6table_filter_hook, | ||
89 | .owner = THIS_MODULE, | ||
90 | .pf = NFPROTO_IPV6, | ||
91 | .hooknum = NF_INET_LOCAL_OUT, | ||
92 | .priority = NF_IP6_PRI_FILTER, | ||
93 | }, | ||
94 | }; | ||
95 | 74 | ||
96 | /* Default to forward because I got too much mail already. */ | 75 | /* Default to forward because I got too much mail already. */ |
97 | static int forward = NF_ACCEPT; | 76 | static int forward = NF_ACCEPT; |
@@ -134,9 +113,11 @@ static int __init ip6table_filter_init(void) | |||
134 | return ret; | 113 | return ret; |
135 | 114 | ||
136 | /* Register hooks */ | 115 | /* Register hooks */ |
137 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 116 | filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook); |
138 | if (ret < 0) | 117 | if (IS_ERR(filter_ops)) { |
118 | ret = PTR_ERR(filter_ops); | ||
139 | goto cleanup_table; | 119 | goto cleanup_table; |
120 | } | ||
140 | 121 | ||
141 | return ret; | 122 | return ret; |
142 | 123 | ||
@@ -147,7 +128,7 @@ static int __init ip6table_filter_init(void) | |||
147 | 128 | ||
148 | static void __exit ip6table_filter_fini(void) | 129 | static void __exit ip6table_filter_fini(void) |
149 | { | 130 | { |
150 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 131 | xt_hook_unlink(&packet_filter, filter_ops); |
151 | unregister_pernet_subsys(&ip6table_filter_net_ops); | 132 | unregister_pernet_subsys(&ip6table_filter_net_ops); |
152 | } | 133 | } |
153 | 134 | ||
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 405ac1f76390..5023ac52ffec 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -62,6 +62,7 @@ static const struct xt_table packet_mangler = { | |||
62 | .valid_hooks = MANGLE_VALID_HOOKS, | 62 | .valid_hooks = MANGLE_VALID_HOOKS, |
63 | .me = THIS_MODULE, | 63 | .me = THIS_MODULE, |
64 | .af = NFPROTO_IPV6, | 64 | .af = NFPROTO_IPV6, |
65 | .priority = NF_IP6_PRI_MANGLE, | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | static unsigned int | 68 | static unsigned int |
@@ -122,44 +123,7 @@ ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb, | |||
122 | dev_net(in)->ipv6.ip6table_mangle); | 123 | dev_net(in)->ipv6.ip6table_mangle); |
123 | } | 124 | } |
124 | 125 | ||
125 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 126 | static struct nf_hook_ops *mangle_ops __read_mostly; |
126 | { | ||
127 | .hook = ip6table_mangle_hook, | ||
128 | .owner = THIS_MODULE, | ||
129 | .pf = NFPROTO_IPV6, | ||
130 | .hooknum = NF_INET_PRE_ROUTING, | ||
131 | .priority = NF_IP6_PRI_MANGLE, | ||
132 | }, | ||
133 | { | ||
134 | .hook = ip6table_mangle_hook, | ||
135 | .owner = THIS_MODULE, | ||
136 | .pf = NFPROTO_IPV6, | ||
137 | .hooknum = NF_INET_LOCAL_IN, | ||
138 | .priority = NF_IP6_PRI_MANGLE, | ||
139 | }, | ||
140 | { | ||
141 | .hook = ip6table_mangle_hook, | ||
142 | .owner = THIS_MODULE, | ||
143 | .pf = NFPROTO_IPV6, | ||
144 | .hooknum = NF_INET_FORWARD, | ||
145 | .priority = NF_IP6_PRI_MANGLE, | ||
146 | }, | ||
147 | { | ||
148 | .hook = ip6table_mangle_hook, | ||
149 | .owner = THIS_MODULE, | ||
150 | .pf = NFPROTO_IPV6, | ||
151 | .hooknum = NF_INET_LOCAL_OUT, | ||
152 | .priority = NF_IP6_PRI_MANGLE, | ||
153 | }, | ||
154 | { | ||
155 | .hook = ip6table_mangle_hook, | ||
156 | .owner = THIS_MODULE, | ||
157 | .pf = NFPROTO_IPV6, | ||
158 | .hooknum = NF_INET_POST_ROUTING, | ||
159 | .priority = NF_IP6_PRI_MANGLE, | ||
160 | }, | ||
161 | }; | ||
162 | |||
163 | static int __net_init ip6table_mangle_net_init(struct net *net) | 127 | static int __net_init ip6table_mangle_net_init(struct net *net) |
164 | { | 128 | { |
165 | /* Register table */ | 129 | /* Register table */ |
@@ -189,9 +153,11 @@ static int __init ip6table_mangle_init(void) | |||
189 | return ret; | 153 | return ret; |
190 | 154 | ||
191 | /* Register hooks */ | 155 | /* Register hooks */ |
192 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 156 | mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook); |
193 | if (ret < 0) | 157 | if (IS_ERR(mangle_ops)) { |
158 | ret = PTR_ERR(mangle_ops); | ||
194 | goto cleanup_table; | 159 | goto cleanup_table; |
160 | } | ||
195 | 161 | ||
196 | return ret; | 162 | return ret; |
197 | 163 | ||
@@ -202,7 +168,7 @@ static int __init ip6table_mangle_init(void) | |||
202 | 168 | ||
203 | static void __exit ip6table_mangle_fini(void) | 169 | static void __exit ip6table_mangle_fini(void) |
204 | { | 170 | { |
205 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 171 | xt_hook_unlink(&packet_mangler, mangle_ops); |
206 | unregister_pernet_subsys(&ip6table_mangle_net_ops); | 172 | unregister_pernet_subsys(&ip6table_mangle_net_ops); |
207 | } | 173 | } |
208 | 174 | ||
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 5451a36fbc21..3bfa69511641 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -40,6 +40,7 @@ static const struct xt_table packet_raw = { | |||
40 | .valid_hooks = RAW_VALID_HOOKS, | 40 | .valid_hooks = RAW_VALID_HOOKS, |
41 | .me = THIS_MODULE, | 41 | .me = THIS_MODULE, |
42 | .af = NFPROTO_IPV6, | 42 | .af = NFPROTO_IPV6, |
43 | .priority = NF_IP6_PRI_FIRST, | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | /* The work comes in here from netfilter.c. */ | 46 | /* The work comes in here from netfilter.c. */ |
@@ -53,22 +54,7 @@ ip6table_raw_hook(unsigned int hook, struct sk_buff *skb, | |||
53 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw); | 54 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw); |
54 | } | 55 | } |
55 | 56 | ||
56 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 57 | static struct nf_hook_ops *rawtable_ops __read_mostly; |
57 | { | ||
58 | .hook = ip6table_raw_hook, | ||
59 | .pf = NFPROTO_IPV6, | ||
60 | .hooknum = NF_INET_PRE_ROUTING, | ||
61 | .priority = NF_IP6_PRI_FIRST, | ||
62 | .owner = THIS_MODULE, | ||
63 | }, | ||
64 | { | ||
65 | .hook = ip6table_raw_hook, | ||
66 | .pf = NFPROTO_IPV6, | ||
67 | .hooknum = NF_INET_LOCAL_OUT, | ||
68 | .priority = NF_IP6_PRI_FIRST, | ||
69 | .owner = THIS_MODULE, | ||
70 | }, | ||
71 | }; | ||
72 | 58 | ||
73 | static int __net_init ip6table_raw_net_init(struct net *net) | 59 | static int __net_init ip6table_raw_net_init(struct net *net) |
74 | { | 60 | { |
@@ -99,9 +85,11 @@ static int __init ip6table_raw_init(void) | |||
99 | return ret; | 85 | return ret; |
100 | 86 | ||
101 | /* Register hooks */ | 87 | /* Register hooks */ |
102 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 88 | rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook); |
103 | if (ret < 0) | 89 | if (IS_ERR(rawtable_ops)) { |
90 | ret = PTR_ERR(rawtable_ops); | ||
104 | goto cleanup_table; | 91 | goto cleanup_table; |
92 | } | ||
105 | 93 | ||
106 | return ret; | 94 | return ret; |
107 | 95 | ||
@@ -112,7 +100,7 @@ static int __init ip6table_raw_init(void) | |||
112 | 100 | ||
113 | static void __exit ip6table_raw_fini(void) | 101 | static void __exit ip6table_raw_fini(void) |
114 | { | 102 | { |
115 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 103 | xt_hook_unlink(&packet_raw, rawtable_ops); |
116 | unregister_pernet_subsys(&ip6table_raw_net_ops); | 104 | unregister_pernet_subsys(&ip6table_raw_net_ops); |
117 | } | 105 | } |
118 | 106 | ||
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 841ea77f5218..dd2200f17a6c 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c | |||
@@ -61,6 +61,7 @@ static const struct xt_table security_table = { | |||
61 | .valid_hooks = SECURITY_VALID_HOOKS, | 61 | .valid_hooks = SECURITY_VALID_HOOKS, |
62 | .me = THIS_MODULE, | 62 | .me = THIS_MODULE, |
63 | .af = NFPROTO_IPV6, | 63 | .af = NFPROTO_IPV6, |
64 | .priority = NF_IP6_PRI_SECURITY, | ||
64 | }; | 65 | }; |
65 | 66 | ||
66 | static unsigned int | 67 | static unsigned int |
@@ -74,29 +75,7 @@ ip6table_security_hook(unsigned int hook, struct sk_buff *skb, | |||
74 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security); | 75 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security); |
75 | } | 76 | } |
76 | 77 | ||
77 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 78 | static struct nf_hook_ops *sectbl_ops __read_mostly; |
78 | { | ||
79 | .hook = ip6table_security_hook, | ||
80 | .owner = THIS_MODULE, | ||
81 | .pf = NFPROTO_IPV6, | ||
82 | .hooknum = NF_INET_LOCAL_IN, | ||
83 | .priority = NF_IP6_PRI_SECURITY, | ||
84 | }, | ||
85 | { | ||
86 | .hook = ip6table_security_hook, | ||
87 | .owner = THIS_MODULE, | ||
88 | .pf = NFPROTO_IPV6, | ||
89 | .hooknum = NF_INET_FORWARD, | ||
90 | .priority = NF_IP6_PRI_SECURITY, | ||
91 | }, | ||
92 | { | ||
93 | .hook = ip6table_security_hook, | ||
94 | .owner = THIS_MODULE, | ||
95 | .pf = NFPROTO_IPV6, | ||
96 | .hooknum = NF_INET_LOCAL_OUT, | ||
97 | .priority = NF_IP6_PRI_SECURITY, | ||
98 | }, | ||
99 | }; | ||
100 | 79 | ||
101 | static int __net_init ip6table_security_net_init(struct net *net) | 80 | static int __net_init ip6table_security_net_init(struct net *net) |
102 | { | 81 | { |
@@ -127,9 +106,11 @@ static int __init ip6table_security_init(void) | |||
127 | if (ret < 0) | 106 | if (ret < 0) |
128 | return ret; | 107 | return ret; |
129 | 108 | ||
130 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 109 | sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook); |
131 | if (ret < 0) | 110 | if (IS_ERR(sectbl_ops)) { |
111 | ret = PTR_ERR(sectbl_ops); | ||
132 | goto cleanup_table; | 112 | goto cleanup_table; |
113 | } | ||
133 | 114 | ||
134 | return ret; | 115 | return ret; |
135 | 116 | ||
@@ -140,7 +121,7 @@ cleanup_table: | |||
140 | 121 | ||
141 | static void __exit ip6table_security_fini(void) | 122 | static void __exit ip6table_security_fini(void) |
142 | { | 123 | { |
143 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 124 | xt_hook_unlink(&security_table, sectbl_ops); |
144 | unregister_pernet_subsys(&ip6table_security_net_ops); | 125 | unregister_pernet_subsys(&ip6table_security_net_ops); |
145 | } | 126 | } |
146 | 127 | ||
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index f01955cce314..b51cb0d7234a 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -1091,6 +1091,60 @@ static const struct file_operations xt_target_ops = { | |||
1091 | 1091 | ||
1092 | #endif /* CONFIG_PROC_FS */ | 1092 | #endif /* CONFIG_PROC_FS */ |
1093 | 1093 | ||
1094 | /** | ||
1095 | * xt_hook_link - set up hooks for a new table | ||
1096 | * @table: table with metadata needed to set up hooks | ||
1097 | * @fn: Hook function | ||
1098 | * | ||
1099 | * This function will take care of creating and registering the necessary | ||
1100 | * Netfilter hooks for XT tables. | ||
1101 | */ | ||
1102 | struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn) | ||
1103 | { | ||
1104 | unsigned int hook_mask = table->valid_hooks; | ||
1105 | uint8_t i, num_hooks = hweight32(hook_mask); | ||
1106 | uint8_t hooknum; | ||
1107 | struct nf_hook_ops *ops; | ||
1108 | int ret; | ||
1109 | |||
1110 | ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL); | ||
1111 | if (ops == NULL) | ||
1112 | return ERR_PTR(-ENOMEM); | ||
1113 | |||
1114 | for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0; | ||
1115 | hook_mask >>= 1, ++hooknum) { | ||
1116 | if (!(hook_mask & 1)) | ||
1117 | continue; | ||
1118 | ops[i].hook = fn; | ||
1119 | ops[i].owner = table->me; | ||
1120 | ops[i].pf = table->af; | ||
1121 | ops[i].hooknum = hooknum; | ||
1122 | ops[i].priority = table->priority; | ||
1123 | ++i; | ||
1124 | } | ||
1125 | |||
1126 | ret = nf_register_hooks(ops, num_hooks); | ||
1127 | if (ret < 0) { | ||
1128 | kfree(ops); | ||
1129 | return ERR_PTR(ret); | ||
1130 | } | ||
1131 | |||
1132 | return ops; | ||
1133 | } | ||
1134 | EXPORT_SYMBOL_GPL(xt_hook_link); | ||
1135 | |||
1136 | /** | ||
1137 | * xt_hook_unlink - remove hooks for a table | ||
1138 | * @ops: nf_hook_ops array as returned by nf_hook_link | ||
1139 | * @hook_mask: the very same mask that was passed to nf_hook_link | ||
1140 | */ | ||
1141 | void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops) | ||
1142 | { | ||
1143 | nf_unregister_hooks(ops, hweight32(table->valid_hooks)); | ||
1144 | kfree(ops); | ||
1145 | } | ||
1146 | EXPORT_SYMBOL_GPL(xt_hook_unlink); | ||
1147 | |||
1094 | int xt_proto_init(struct net *net, u_int8_t af) | 1148 | int xt_proto_init(struct net *net, u_int8_t af) |
1095 | { | 1149 | { |
1096 | #ifdef CONFIG_PROC_FS | 1150 | #ifdef CONFIG_PROC_FS |