]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
xtables: translate nft meta trace set 1 to -j TRACE
authorFlorian Westphal <fw@strlen.de>
Thu, 10 May 2018 21:25:27 +0000 (23:25 +0200)
committerFlorian Westphal <fw@strlen.de>
Mon, 25 Jun 2018 09:51:29 +0000 (11:51 +0200)
nft meta expr enables the nfnetlink based trace infrastruvture, so
prefer to use that rather than xt_TRACE.

Signed-off-by: Florian Westphal <fw@strlen.de>
iptables/nft-shared.c
iptables/nft-shared.h
iptables/nft.c

index ed0d0ee96b0dd42295627adae4bfdb880f43f0eb..eb2af851dc11888eb18a04a140e1b3e05e7ee2de 100644 (file)
@@ -414,10 +414,54 @@ void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv)
                *inv = false;
 }
 
+static void nft_meta_set_to_target(struct nft_xt_ctx *ctx)
+{
+       const struct nft_family_ops *ops;
+       struct xtables_target *target;
+       struct xt_entry_target *t;
+       unsigned int size;
+       const char *targname;
+
+       switch (ctx->meta.key) {
+       case NFT_META_NFTRACE:
+               if (ctx->immediate.data[0] == 0)
+                       return;
+               targname = "TRACE";
+               break;
+       default:
+               return;
+       }
+
+       target = xtables_find_target(targname, XTF_TRY_LOAD);
+       if (target == NULL)
+               return;
+
+       size = XT_ALIGN(sizeof(struct xt_entry_target)) + target->size;
+
+       t = xtables_calloc(1, size);
+       t->u.target_size = size;
+       t->u.user.revision = target->revision;
+       strcpy(t->u.user.name, targname);
+
+       target->t = t;
+
+       ops = nft_family_ops_lookup(ctx->family);
+       ops->parse_target(target, nft_get_data(ctx));
+}
+
 void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 {
-       ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
        ctx->meta.key = nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY);
+
+       if (nftnl_expr_is_set(e, NFTNL_EXPR_META_SREG) &&
+           (ctx->flags & NFT_XT_CTX_IMMEDIATE) &&
+            nftnl_expr_get_u32(e, NFTNL_EXPR_META_SREG) == ctx->immediate.reg) {
+               ctx->flags &= ~NFT_XT_CTX_IMMEDIATE;
+               nft_meta_set_to_target(ctx);
+               return;
+       }
+
+       ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
        ctx->flags |= NFT_XT_CTX_META;
 }
 
@@ -473,13 +517,30 @@ void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters)
 
 void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 {
-       int verdict = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_VERDICT);
        const char *chain = nftnl_expr_get_str(e, NFTNL_EXPR_IMM_CHAIN);
        struct nft_family_ops *ops;
        const char *jumpto = NULL;
        bool nft_goto = false;
        void *data = nft_get_data(ctx);
+       int verdict;
+
+       if (nftnl_expr_is_set(e, NFTNL_EXPR_IMM_DATA)) {
+               const void *imm_data;
+               uint32_t len;
+
+               imm_data = nftnl_expr_get_data(e, NFTNL_EXPR_IMM_DATA, &len);
+
+               if (len > sizeof(ctx->immediate.data))
+                       return;
+
+               memcpy(ctx->immediate.data, imm_data, len);
+               ctx->immediate.len = len;
+               ctx->immediate.reg = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_DREG);
+               ctx->flags |= NFT_XT_CTX_IMMEDIATE;
+               return;
+       }
 
+       verdict = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_VERDICT);
        /* Standard target? */
        switch(verdict) {
        case NF_ACCEPT:
index 6d04b1a49ee3f8ea344e1d49d90a6f0b8296c8b7..d74eeb0063a74d09f2c8cef977a1bcdad9902a2e 100644 (file)
@@ -43,6 +43,7 @@ enum {
        NFT_XT_CTX_PAYLOAD      = (1 << 0),
        NFT_XT_CTX_META         = (1 << 1),
        NFT_XT_CTX_BITWISE      = (1 << 2),
+       NFT_XT_CTX_IMMEDIATE    = (1 << 3),
 };
 
 struct nft_xt_ctx {
@@ -62,6 +63,10 @@ struct nft_xt_ctx {
        struct {
                uint32_t key;
        } meta;
+       struct {
+               uint32_t data[4];
+               uint32_t len, reg;
+       } immediate;
        struct {
                uint32_t mask[4];
                uint32_t xor[4];
index 08cbdc86450c63d0af6f7bc4bc1b6185005fcf41..64307375f99ba76078d6f97cb159830119f0312a 100644 (file)
@@ -929,11 +929,36 @@ static int __add_target(struct nftnl_expr *e, struct xt_entry_target *t)
        return 0;
 }
 
+static int add_meta_nftrace(struct nftnl_rule *r)
+{
+       struct nftnl_expr *expr;
+
+       expr = nftnl_expr_alloc("immediate");
+       if (expr == NULL)
+               return -ENOMEM;
+
+       nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_DREG, NFT_REG32_01);
+       nftnl_expr_set_u8(expr, NFTNL_EXPR_IMM_DATA, 1);
+       nftnl_rule_add_expr(r, expr);
+
+       expr = nftnl_expr_alloc("meta");
+       if (expr == NULL)
+               return -ENOMEM;
+       nftnl_expr_set_u32(expr, NFTNL_EXPR_META_KEY, NFT_META_NFTRACE);
+       nftnl_expr_set_u32(expr, NFTNL_EXPR_META_SREG, NFT_REG32_01);
+
+       nftnl_rule_add_expr(r, expr);
+       return 0;
+}
+
 int add_target(struct nftnl_rule *r, struct xt_entry_target *t)
 {
        struct nftnl_expr *expr;
        int ret;
 
+       if (strcmp(t->u.user.name, "TRACE") == 0)
+               return add_meta_nftrace(r);
+
        expr = nftnl_expr_alloc("target");
        if (expr == NULL)
                return -ENOMEM;