summaryrefslogtreecommitdiffstats
path: root/iptables/nft-shared.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2018-05-10 23:25:27 +0200
committerFlorian Westphal <fw@strlen.de>2018-06-25 11:51:29 +0200
commitdb84371beafd011e1f1cbe9688241c4dff1649f7 (patch)
tree07e655d24fd693336f0127f2a8692b99823d9d12 /iptables/nft-shared.c
parent20eac2ad174e43a3d4a4275c3d44f99c12bd04b9 (diff)
xtables: translate nft meta trace set 1 to -j TRACE
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>
Diffstat (limited to 'iptables/nft-shared.c')
-rw-r--r--iptables/nft-shared.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index ed0d0ee9..eb2af851 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -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: