netfilter: nf_tables: store data in offload context registers
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 1 Aug 2019 12:09:26 +0000 (14:09 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 13 Aug 2019 10:10:01 +0000 (12:10 +0200)
Store immediate data into offload context register. This allows follow
up instructions to take it from the corresponding source register.

This patch is required to support for payload mangling, although other
instructions that take data from source register will benefit from this
too.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_tables_offload.h
net/netfilter/nft_immediate.c

index 3196663a10e30e24880f571fb59a30e2e2cabfb7..4977fbe7ed08aa2e00c7856f27d4fb0053fb6275 100644 (file)
@@ -9,6 +9,7 @@ struct nft_offload_reg {
        u32             len;
        u32             base_offset;
        u32             offset;
+       struct nft_data data;
        struct nft_data mask;
 };
 
index ca2ae4b95a8dadf858f1cf61357be7fc167f8c80..c7f0ef73d9397a666223150cad18ea927e742ee2 100644 (file)
@@ -125,17 +125,13 @@ static int nft_immediate_validate(const struct nft_ctx *ctx,
        return 0;
 }
 
-static int nft_immediate_offload(struct nft_offload_ctx *ctx,
-                                struct nft_flow_rule *flow,
-                                const struct nft_expr *expr)
+static int nft_immediate_offload_verdict(struct nft_offload_ctx *ctx,
+                                        struct nft_flow_rule *flow,
+                                        const struct nft_immediate_expr *priv)
 {
-       const struct nft_immediate_expr *priv = nft_expr_priv(expr);
        struct flow_action_entry *entry;
        const struct nft_data *data;
 
-       if (priv->dreg != NFT_REG_VERDICT)
-               return -EOPNOTSUPP;
-
        entry = &flow->rule->action.entries[ctx->num_actions++];
 
        data = &priv->data;
@@ -153,6 +149,20 @@ static int nft_immediate_offload(struct nft_offload_ctx *ctx,
        return 0;
 }
 
+static int nft_immediate_offload(struct nft_offload_ctx *ctx,
+                                struct nft_flow_rule *flow,
+                                const struct nft_expr *expr)
+{
+       const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+
+       if (priv->dreg == NFT_REG_VERDICT)
+               return nft_immediate_offload_verdict(ctx, flow, priv);
+
+       memcpy(&ctx->regs[priv->dreg].data, &priv->data, sizeof(priv->data));
+
+       return 0;
+}
+
 static const struct nft_expr_ops nft_imm_ops = {
        .type           = &nft_imm_type,
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)),