aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter/nft_immediate.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2020-06-30 19:21:36 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2020-07-04 01:22:14 +0200
commitd0e2c7de92c7f2b3d355ad76b0bb9fc43d1beb87 (patch)
treeaeb58859a40e1b8478a275c2fd534b5bf56cad10 /net/netfilter/nft_immediate.c
parentnetfilter: nf_tables: add nft_chain_add() (diff)
downloadlinux-dev-d0e2c7de92c7f2b3d355ad76b0bb9fc43d1beb87.tar.xz
linux-dev-d0e2c7de92c7f2b3d355ad76b0bb9fc43d1beb87.zip
netfilter: nf_tables: add NFT_CHAIN_BINDING
This new chain flag specifies that: * the kernel dynamically allocates the chain name, if no chain name is specified. * If the immediate expression that refers to this chain is removed, then this bound chain (and its content) is destroyed. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nft_immediate.c')
-rw-r--r--net/netfilter/nft_immediate.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
index c7f0ef73d939..9e556638bb32 100644
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -54,6 +54,23 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
if (err < 0)
goto err1;
+ if (priv->dreg == NFT_REG_VERDICT) {
+ struct nft_chain *chain = priv->data.verdict.chain;
+
+ switch (priv->data.verdict.code) {
+ case NFT_JUMP:
+ case NFT_GOTO:
+ if (nft_chain_is_bound(chain)) {
+ err = -EBUSY;
+ goto err1;
+ }
+ chain->bound = true;
+ break;
+ default:
+ break;
+ }
+ }
+
return 0;
err1:
@@ -81,6 +98,39 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));
}
+static void nft_immediate_destroy(const struct nft_ctx *ctx,
+ const struct nft_expr *expr)
+{
+ const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+ const struct nft_data *data = &priv->data;
+ struct nft_ctx chain_ctx;
+ struct nft_chain *chain;
+ struct nft_rule *rule;
+
+ if (priv->dreg != NFT_REG_VERDICT)
+ return;
+
+ switch (data->verdict.code) {
+ case NFT_JUMP:
+ case NFT_GOTO:
+ chain = data->verdict.chain;
+
+ if (!nft_chain_is_bound(chain))
+ break;
+
+ chain_ctx = *ctx;
+ chain_ctx.chain = chain;
+
+ list_for_each_entry(rule, &chain->rules, list)
+ nf_tables_rule_release(&chain_ctx, rule);
+
+ nf_tables_chain_destroy(&chain_ctx);
+ break;
+ default:
+ break;
+ }
+}
+
static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr)
{
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
@@ -170,6 +220,7 @@ static const struct nft_expr_ops nft_imm_ops = {
.init = nft_immediate_init,
.activate = nft_immediate_activate,
.deactivate = nft_immediate_deactivate,
+ .destroy = nft_immediate_destroy,
.dump = nft_immediate_dump,
.validate = nft_immediate_validate,
.offload = nft_immediate_offload,