summaryrefslogtreecommitdiffstats
path: root/net/netfilter/nf_tables_api.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso2018-03-27 11:53:08 +0200
committerPablo Neira Ayuso2018-03-30 11:29:19 +0200
commit43a605f2f722b6e08addedae8545b490fca252c4 (patch)
treeec3310d2587f35c25d59d79ad4d1460ecc710d75 /net/netfilter/nf_tables_api.c
parentnetfilter: nf_tables: build-in filter chain type (diff)
downloadkernel-qcow2-linux-43a605f2f722b6e08addedae8545b490fca252c4.tar.gz
kernel-qcow2-linux-43a605f2f722b6e08addedae8545b490fca252c4.tar.xz
kernel-qcow2-linux-43a605f2f722b6e08addedae8545b490fca252c4.zip
netfilter: nf_tables: enable conntrack if NAT chain is registered
Register conntrack hooks if the user adds NAT chains. Users get confused with the existing behaviour since they will see no packets hitting this chain until they add the first rule that refers to conntrack. This patch adds new ->init() and ->free() indirections to chain types that can be used by NAT chains to invoke the conntrack dependency. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nf_tables_api.c')
-rw-r--r--net/netfilter/nf_tables_api.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 97ec1c388bfe..af8b6a7488bd 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1211,13 +1211,17 @@ static void nft_chain_stats_replace(struct nft_base_chain *chain,
rcu_assign_pointer(chain->stats, newstats);
}
-static void nf_tables_chain_destroy(struct nft_chain *chain)
+static void nf_tables_chain_destroy(struct nft_ctx *ctx)
{
+ struct nft_chain *chain = ctx->chain;
+
BUG_ON(chain->use > 0);
if (nft_is_base_chain(chain)) {
struct nft_base_chain *basechain = nft_base_chain(chain);
+ if (basechain->type->free)
+ basechain->type->free(ctx);
module_put(basechain->type->owner);
free_percpu(basechain->stats);
if (basechain->stats)
@@ -1354,6 +1358,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
}
basechain->type = hook.type;
+ if (basechain->type->init)
+ basechain->type->init(ctx);
+
chain = &basechain->chain;
ops = &basechain->ops;
@@ -1374,6 +1381,8 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
if (chain == NULL)
return -ENOMEM;
}
+ ctx->chain = chain;
+
INIT_LIST_HEAD(&chain->rules);
chain->handle = nf_tables_alloc_handle(table);
chain->table = table;
@@ -1387,7 +1396,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
if (err < 0)
goto err1;
- ctx->chain = chain;
err = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
if (err < 0)
goto err2;
@@ -1399,7 +1407,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
err2:
nf_tables_unregister_hook(net, table, chain);
err1:
- nf_tables_chain_destroy(chain);
+ nf_tables_chain_destroy(ctx);
return err;
}
@@ -5678,7 +5686,7 @@ static void nf_tables_commit_release(struct nft_trans *trans)
nf_tables_table_destroy(&trans->ctx);
break;
case NFT_MSG_DELCHAIN:
- nf_tables_chain_destroy(trans->ctx.chain);
+ nf_tables_chain_destroy(&trans->ctx);
break;
case NFT_MSG_DELRULE:
nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
@@ -5849,7 +5857,7 @@ static void nf_tables_abort_release(struct nft_trans *trans)
nf_tables_table_destroy(&trans->ctx);
break;
case NFT_MSG_NEWCHAIN:
- nf_tables_chain_destroy(trans->ctx.chain);
+ nf_tables_chain_destroy(&trans->ctx);
break;
case NFT_MSG_NEWRULE:
nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
@@ -6499,7 +6507,7 @@ int __nft_release_basechain(struct nft_ctx *ctx)
}
list_del(&ctx->chain->list);
ctx->table->use--;
- nf_tables_chain_destroy(ctx->chain);
+ nf_tables_chain_destroy(ctx);
return 0;
}
@@ -6515,6 +6523,7 @@ static void __nft_release_tables(struct net *net)
struct nft_set *set, *ns;
struct nft_ctx ctx = {
.net = net,
+ .family = NFPROTO_NETDEV,
};
list_for_each_entry_safe(table, nt, &net->nft.tables, list) {
@@ -6551,9 +6560,10 @@ static void __nft_release_tables(struct net *net)
nft_obj_destroy(obj);
}
list_for_each_entry_safe(chain, nc, &table->chains, list) {
+ ctx.chain = chain;
list_del(&chain->list);
table->use--;
- nf_tables_chain_destroy(chain);
+ nf_tables_chain_destroy(&ctx);
}
list_del(&table->list);
nf_tables_table_destroy(&ctx);