81f140441f3d56b93dfaa4359dfc142e31775b8f
[openwrt/staging/linusw.git] /
1 From: Pablo Neira Ayuso <pablo@netfilter.org>
2 Date: Sat, 9 Dec 2017 15:40:25 +0100
3 Subject: [PATCH] netfilter: nf_tables: remove multihook chains and families
4
5 Since NFPROTO_INET is handled from the core, we don't need to maintain
6 extra infrastructure in nf_tables to handle the double hook
7 registration, one for IPv4 and another for IPv6.
8
9 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 ---
11
12 --- a/include/net/netfilter/nf_tables.h
13 +++ b/include/net/netfilter/nf_tables.h
14 @@ -892,8 +892,6 @@ struct nft_stats {
15 struct u64_stats_sync syncp;
16 };
17
18 -#define NFT_HOOK_OPS_MAX 2
19 -
20 /**
21 * struct nft_base_chain - nf_tables base chain
22 *
23 @@ -905,7 +903,7 @@ struct nft_stats {
24 * @dev_name: device name that this base chain is attached to (if any)
25 */
26 struct nft_base_chain {
27 - struct nf_hook_ops ops[NFT_HOOK_OPS_MAX];
28 + struct nf_hook_ops ops;
29 const struct nf_chain_type *type;
30 u8 policy;
31 u8 flags;
32 @@ -966,8 +964,6 @@ enum nft_af_flags {
33 * @owner: module owner
34 * @tables: used internally
35 * @flags: family flags
36 - * @nops: number of hook ops in this family
37 - * @hook_ops_init: initialization function for chain hook ops
38 * @hooks: hookfn overrides for packet validation
39 */
40 struct nft_af_info {
41 @@ -977,9 +973,6 @@ struct nft_af_info {
42 struct module *owner;
43 struct list_head tables;
44 u32 flags;
45 - unsigned int nops;
46 - void (*hook_ops_init)(struct nf_hook_ops *,
47 - unsigned int);
48 nf_hookfn *hooks[NF_MAX_HOOKS];
49 };
50
51 --- a/net/bridge/netfilter/nf_tables_bridge.c
52 +++ b/net/bridge/netfilter/nf_tables_bridge.c
53 @@ -46,7 +46,6 @@ static struct nft_af_info nft_af_bridge
54 .family = NFPROTO_BRIDGE,
55 .nhooks = NF_BR_NUMHOOKS,
56 .owner = THIS_MODULE,
57 - .nops = 1,
58 .hooks = {
59 [NF_BR_PRE_ROUTING] = nft_do_chain_bridge,
60 [NF_BR_LOCAL_IN] = nft_do_chain_bridge,
61 --- a/net/ipv4/netfilter/nf_tables_arp.c
62 +++ b/net/ipv4/netfilter/nf_tables_arp.c
63 @@ -31,7 +31,6 @@ static struct nft_af_info nft_af_arp __r
64 .family = NFPROTO_ARP,
65 .nhooks = NF_ARP_NUMHOOKS,
66 .owner = THIS_MODULE,
67 - .nops = 1,
68 .hooks = {
69 [NF_ARP_IN] = nft_do_chain_arp,
70 [NF_ARP_OUT] = nft_do_chain_arp,
71 --- a/net/ipv4/netfilter/nf_tables_ipv4.c
72 +++ b/net/ipv4/netfilter/nf_tables_ipv4.c
73 @@ -49,7 +49,6 @@ static struct nft_af_info nft_af_ipv4 __
74 .family = NFPROTO_IPV4,
75 .nhooks = NF_INET_NUMHOOKS,
76 .owner = THIS_MODULE,
77 - .nops = 1,
78 .hooks = {
79 [NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
80 [NF_INET_LOCAL_OUT] = nft_ipv4_output,
81 --- a/net/ipv6/netfilter/nf_tables_ipv6.c
82 +++ b/net/ipv6/netfilter/nf_tables_ipv6.c
83 @@ -46,7 +46,6 @@ static struct nft_af_info nft_af_ipv6 __
84 .family = NFPROTO_IPV6,
85 .nhooks = NF_INET_NUMHOOKS,
86 .owner = THIS_MODULE,
87 - .nops = 1,
88 .hooks = {
89 [NF_INET_LOCAL_IN] = nft_do_chain_ipv6,
90 [NF_INET_LOCAL_OUT] = nft_ipv6_output,
91 --- a/net/netfilter/nf_tables_api.c
92 +++ b/net/netfilter/nf_tables_api.c
93 @@ -139,29 +139,26 @@ static void nft_trans_destroy(struct nft
94 kfree(trans);
95 }
96
97 -static int nf_tables_register_hooks(struct net *net,
98 - const struct nft_table *table,
99 - struct nft_chain *chain,
100 - unsigned int hook_nops)
101 +static int nf_tables_register_hook(struct net *net,
102 + const struct nft_table *table,
103 + struct nft_chain *chain)
104 {
105 if (table->flags & NFT_TABLE_F_DORMANT ||
106 !nft_is_base_chain(chain))
107 return 0;
108
109 - return nf_register_net_hooks(net, nft_base_chain(chain)->ops,
110 - hook_nops);
111 + return nf_register_net_hook(net, &nft_base_chain(chain)->ops);
112 }
113
114 -static void nf_tables_unregister_hooks(struct net *net,
115 - const struct nft_table *table,
116 - struct nft_chain *chain,
117 - unsigned int hook_nops)
118 +static void nf_tables_unregister_hook(struct net *net,
119 + const struct nft_table *table,
120 + struct nft_chain *chain)
121 {
122 if (table->flags & NFT_TABLE_F_DORMANT ||
123 !nft_is_base_chain(chain))
124 return;
125
126 - nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, hook_nops);
127 + nf_unregister_net_hook(net, &nft_base_chain(chain)->ops);
128 }
129
130 static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
131 @@ -595,8 +592,7 @@ static void _nf_tables_table_disable(str
132 if (cnt && i++ == cnt)
133 break;
134
135 - nf_unregister_net_hooks(net, nft_base_chain(chain)->ops,
136 - afi->nops);
137 + nf_unregister_net_hook(net, &nft_base_chain(chain)->ops);
138 }
139 }
140
141 @@ -613,8 +609,7 @@ static int nf_tables_table_enable(struct
142 if (!nft_is_base_chain(chain))
143 continue;
144
145 - err = nf_register_net_hooks(net, nft_base_chain(chain)->ops,
146 - afi->nops);
147 + err = nf_register_net_hook(net, &nft_base_chain(chain)->ops);
148 if (err < 0)
149 goto err;
150
151 @@ -1026,7 +1021,7 @@ static int nf_tables_fill_chain_info(str
152
153 if (nft_is_base_chain(chain)) {
154 const struct nft_base_chain *basechain = nft_base_chain(chain);
155 - const struct nf_hook_ops *ops = &basechain->ops[0];
156 + const struct nf_hook_ops *ops = &basechain->ops;
157 struct nlattr *nest;
158
159 nest = nla_nest_start(skb, NFTA_CHAIN_HOOK);
160 @@ -1252,8 +1247,8 @@ static void nf_tables_chain_destroy(stru
161 free_percpu(basechain->stats);
162 if (basechain->stats)
163 static_branch_dec(&nft_counters_enabled);
164 - if (basechain->ops[0].dev != NULL)
165 - dev_put(basechain->ops[0].dev);
166 + if (basechain->ops.dev != NULL)
167 + dev_put(basechain->ops.dev);
168 kfree(chain->name);
169 kfree(basechain);
170 } else {
171 @@ -1349,7 +1344,6 @@ static int nf_tables_addchain(struct nft
172 struct nft_stats __percpu *stats;
173 struct net *net = ctx->net;
174 struct nft_chain *chain;
175 - unsigned int i;
176 int err;
177
178 if (table->use == UINT_MAX)
179 @@ -1388,21 +1382,18 @@ static int nf_tables_addchain(struct nft
180 basechain->type = hook.type;
181 chain = &basechain->chain;
182
183 - for (i = 0; i < afi->nops; i++) {
184 - ops = &basechain->ops[i];
185 - ops->pf = family;
186 - ops->hooknum = hook.num;
187 - ops->priority = hook.priority;
188 - ops->priv = chain;
189 - ops->hook = afi->hooks[ops->hooknum];
190 - ops->dev = hook.dev;
191 - if (hookfn)
192 - ops->hook = hookfn;
193 - if (afi->hook_ops_init)
194 - afi->hook_ops_init(ops, i);
195 - if (basechain->type->type == NFT_CHAIN_T_NAT)
196 - ops->nat_hook = true;
197 - }
198 + ops = &basechain->ops;
199 + ops->pf = family;
200 + ops->hooknum = hook.num;
201 + ops->priority = hook.priority;
202 + ops->priv = chain;
203 + ops->hook = afi->hooks[ops->hooknum];
204 + ops->dev = hook.dev;
205 + if (hookfn)
206 + ops->hook = hookfn;
207 +
208 + if (basechain->type->type == NFT_CHAIN_T_NAT)
209 + ops->nat_hook = true;
210
211 chain->flags |= NFT_BASE_CHAIN;
212 basechain->policy = policy;
213 @@ -1420,7 +1411,7 @@ static int nf_tables_addchain(struct nft
214 goto err1;
215 }
216
217 - err = nf_tables_register_hooks(net, table, chain, afi->nops);
218 + err = nf_tables_register_hook(net, table, chain);
219 if (err < 0)
220 goto err1;
221
222 @@ -1434,7 +1425,7 @@ static int nf_tables_addchain(struct nft
223
224 return 0;
225 err2:
226 - nf_tables_unregister_hooks(net, table, chain, afi->nops);
227 + nf_tables_unregister_hook(net, table, chain);
228 err1:
229 nf_tables_chain_destroy(chain);
230
231 @@ -1447,14 +1438,13 @@ static int nf_tables_updchain(struct nft
232 const struct nlattr * const *nla = ctx->nla;
233 struct nft_table *table = ctx->table;
234 struct nft_chain *chain = ctx->chain;
235 - struct nft_af_info *afi = ctx->afi;
236 struct nft_base_chain *basechain;
237 struct nft_stats *stats = NULL;
238 struct nft_chain_hook hook;
239 const struct nlattr *name;
240 struct nf_hook_ops *ops;
241 struct nft_trans *trans;
242 - int err, i;
243 + int err;
244
245 if (nla[NFTA_CHAIN_HOOK]) {
246 if (!nft_is_base_chain(chain))
247 @@ -1471,14 +1461,12 @@ static int nf_tables_updchain(struct nft
248 return -EBUSY;
249 }
250
251 - for (i = 0; i < afi->nops; i++) {
252 - ops = &basechain->ops[i];
253 - if (ops->hooknum != hook.num ||
254 - ops->priority != hook.priority ||
255 - ops->dev != hook.dev) {
256 - nft_chain_release_hook(&hook);
257 - return -EBUSY;
258 - }
259 + ops = &basechain->ops;
260 + if (ops->hooknum != hook.num ||
261 + ops->priority != hook.priority ||
262 + ops->dev != hook.dev) {
263 + nft_chain_release_hook(&hook);
264 + return -EBUSY;
265 }
266 nft_chain_release_hook(&hook);
267 }
268 @@ -5069,10 +5057,9 @@ static int nf_tables_commit(struct net *
269 case NFT_MSG_DELCHAIN:
270 list_del_rcu(&trans->ctx.chain->list);
271 nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
272 - nf_tables_unregister_hooks(trans->ctx.net,
273 - trans->ctx.table,
274 - trans->ctx.chain,
275 - trans->ctx.afi->nops);
276 + nf_tables_unregister_hook(trans->ctx.net,
277 + trans->ctx.table,
278 + trans->ctx.chain);
279 break;
280 case NFT_MSG_NEWRULE:
281 nft_clear(trans->ctx.net, nft_trans_rule(trans));
282 @@ -5209,10 +5196,9 @@ static int nf_tables_abort(struct net *n
283 } else {
284 trans->ctx.table->use--;
285 list_del_rcu(&trans->ctx.chain->list);
286 - nf_tables_unregister_hooks(trans->ctx.net,
287 - trans->ctx.table,
288 - trans->ctx.chain,
289 - trans->ctx.afi->nops);
290 + nf_tables_unregister_hook(trans->ctx.net,
291 + trans->ctx.table,
292 + trans->ctx.chain);
293 }
294 break;
295 case NFT_MSG_DELCHAIN:
296 @@ -5313,7 +5299,7 @@ int nft_chain_validate_hooks(const struc
297 if (nft_is_base_chain(chain)) {
298 basechain = nft_base_chain(chain);
299
300 - if ((1 << basechain->ops[0].hooknum) & hook_flags)
301 + if ((1 << basechain->ops.hooknum) & hook_flags)
302 return 0;
303
304 return -EOPNOTSUPP;
305 @@ -5795,8 +5781,7 @@ int __nft_release_basechain(struct nft_c
306
307 BUG_ON(!nft_is_base_chain(ctx->chain));
308
309 - nf_tables_unregister_hooks(ctx->net, ctx->chain->table, ctx->chain,
310 - ctx->afi->nops);
311 + nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain);
312 list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
313 list_del(&rule->list);
314 ctx->chain->use--;
315 @@ -5825,8 +5810,7 @@ static void __nft_release_afinfo(struct
316
317 list_for_each_entry_safe(table, nt, &afi->tables, list) {
318 list_for_each_entry(chain, &table->chains, list)
319 - nf_tables_unregister_hooks(net, table, chain,
320 - afi->nops);
321 + nf_tables_unregister_hook(net, table, chain);
322 /* No packets are walking on these chains anymore. */
323 ctx.table = table;
324 list_for_each_entry(chain, &table->chains, list) {
325 --- a/net/netfilter/nf_tables_inet.c
326 +++ b/net/netfilter/nf_tables_inet.c
327 @@ -74,7 +74,6 @@ static struct nft_af_info nft_af_inet __
328 .family = NFPROTO_INET,
329 .nhooks = NF_INET_NUMHOOKS,
330 .owner = THIS_MODULE,
331 - .nops = 1,
332 .hooks = {
333 [NF_INET_LOCAL_IN] = nft_do_chain_inet,
334 [NF_INET_LOCAL_OUT] = nft_inet_output,
335 --- a/net/netfilter/nf_tables_netdev.c
336 +++ b/net/netfilter/nf_tables_netdev.c
337 @@ -43,7 +43,6 @@ static struct nft_af_info nft_af_netdev
338 .nhooks = NF_NETDEV_NUMHOOKS,
339 .owner = THIS_MODULE,
340 .flags = NFT_AF_NEEDS_DEV,
341 - .nops = 1,
342 .hooks = {
343 [NF_NETDEV_INGRESS] = nft_do_chain_netdev,
344 },
345 @@ -98,7 +97,7 @@ static void nft_netdev_event(unsigned lo
346 __nft_release_basechain(ctx);
347 break;
348 case NETDEV_CHANGENAME:
349 - if (dev->ifindex != basechain->ops[0].dev->ifindex)
350 + if (dev->ifindex != basechain->ops.dev->ifindex)
351 return;
352
353 strncpy(basechain->dev_name, dev->name, IFNAMSIZ);
354 --- a/net/netfilter/nft_compat.c
355 +++ b/net/netfilter/nft_compat.c
356 @@ -169,7 +169,7 @@ nft_target_set_tgchk_param(struct xt_tgc
357 if (nft_is_base_chain(ctx->chain)) {
358 const struct nft_base_chain *basechain =
359 nft_base_chain(ctx->chain);
360 - const struct nf_hook_ops *ops = &basechain->ops[0];
361 + const struct nf_hook_ops *ops = &basechain->ops;
362
363 par->hook_mask = 1 << ops->hooknum;
364 } else {
365 @@ -302,7 +302,7 @@ static int nft_target_validate(const str
366 if (nft_is_base_chain(ctx->chain)) {
367 const struct nft_base_chain *basechain =
368 nft_base_chain(ctx->chain);
369 - const struct nf_hook_ops *ops = &basechain->ops[0];
370 + const struct nf_hook_ops *ops = &basechain->ops;
371
372 hook_mask = 1 << ops->hooknum;
373 if (target->hooks && !(hook_mask & target->hooks))
374 @@ -383,7 +383,7 @@ nft_match_set_mtchk_param(struct xt_mtch
375 if (nft_is_base_chain(ctx->chain)) {
376 const struct nft_base_chain *basechain =
377 nft_base_chain(ctx->chain);
378 - const struct nf_hook_ops *ops = &basechain->ops[0];
379 + const struct nf_hook_ops *ops = &basechain->ops;
380
381 par->hook_mask = 1 << ops->hooknum;
382 } else {
383 @@ -481,7 +481,7 @@ static int nft_match_validate(const stru
384 if (nft_is_base_chain(ctx->chain)) {
385 const struct nft_base_chain *basechain =
386 nft_base_chain(ctx->chain);
387 - const struct nf_hook_ops *ops = &basechain->ops[0];
388 + const struct nf_hook_ops *ops = &basechain->ops;
389
390 hook_mask = 1 << ops->hooknum;
391 if (match->hooks && !(hook_mask & match->hooks))