netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Subject: [PATCH nft 2/2] src: improve rule error reporting
Date: Mon, 19 Oct 2020 14:50:12 +0200	[thread overview]
Message-ID: <20201019125012.14373-2-pablo@netfilter.org> (raw)
In-Reply-To: <20201019125012.14373-1-pablo@netfilter.org>

Kernel provides information regarding expression since
83d9dcba06c5 ("netfilter: nf_tables: extended netlink error reporting for
expressions").

A common mistake is to reference a chain which does not exist, e.g.

 # nft add rule x y jump test
 Error: Could not process rule: No such file or directory
 add rule x y jump test
                   ^^^^

Use the existing netlink extended error reporting infrastructure to
provide better error reporting as in the example above.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/netlink.h       |  27 ++++++-
 src/mnl.c               |  65 ++++++++++++++-
 src/netlink_linearize.c | 171 ++++++++++++++++++++++++++--------------
 3 files changed, 201 insertions(+), 62 deletions(-)

diff --git a/include/netlink.h b/include/netlink.h
index b78277a8ce30..9730c6bb2cb6 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -123,9 +123,11 @@ extern struct expr *netlink_alloc_data(const struct location *loc,
 				       enum nft_registers dreg);
 
 extern int netlink_list_rules(struct netlink_ctx *ctx, const struct handle *h);
+
+struct netlink_linearize_ctx;
 extern void netlink_linearize_rule(struct netlink_ctx *ctx,
-				   struct nftnl_rule *nlr,
-				   const struct rule *rule);
+				   const struct rule *rule,
+				   struct netlink_linearize_ctx *lctx);
 extern struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
 					     struct nftnl_rule *r);
 
@@ -215,4 +217,25 @@ enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype);
 void expr_handler_init(void);
 void expr_handler_exit(void);
 
+void netlink_linearize_init(struct netlink_linearize_ctx *lctx,
+			    struct nftnl_rule *nlr);
+void netlink_linearize_fini(struct netlink_linearize_ctx *lctx);
+
+struct netlink_linearize_ctx {
+	struct nftnl_rule	*nlr;
+	unsigned int		reg_low;
+	struct list_head	*expr_loc_htable;
+};
+
+#define NFT_EXPR_LOC_HSIZE      128
+
+struct nft_expr_loc {
+	struct list_head        hlist;
+	const struct nftnl_expr *nle;
+	struct location         loc;
+};
+
+struct nft_expr_loc *nft_expr_loc_find(const struct nftnl_expr *nle,
+				       struct netlink_linearize_ctx *ctx);
+
 #endif /* NFTABLES_NETLINK_H */
diff --git a/src/mnl.c b/src/mnl.c
index adb55d4dec90..f776a1db6452 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -426,13 +426,55 @@ int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list,
 	return 0;
 }
 
+struct mnl_nft_rule_build_ctx {
+	struct netlink_linearize_ctx	*lctx;
+	struct nlmsghdr			*nlh;
+	struct cmd			*cmd;
+};
+
+static int mnl_nft_expr_build_cb(struct nftnl_expr *nle, void *data)
+{
+	struct mnl_nft_rule_build_ctx *ctx = data;
+	struct nlmsghdr *nlh = ctx->nlh;
+	struct cmd *cmd = ctx->cmd;
+	struct nft_expr_loc *eloc;
+	struct nlattr *nest;
+
+	eloc = nft_expr_loc_find(nle, ctx->lctx);
+	if (eloc)
+		cmd_add_loc(cmd, nlh->nlmsg_len, &eloc->loc);
+
+	nest = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
+	nftnl_expr_build_payload(nlh, nle);
+	mnl_attr_nest_end(nlh, nest);
+
+	nftnl_rule_del_expr(nle);
+	nftnl_expr_free(nle);
+
+	return 0;
+}
+
+static void mnl_nft_rule_build_ctx_init(struct mnl_nft_rule_build_ctx *rule_ctx,
+					struct nlmsghdr *nlh,
+					struct cmd *cmd,
+					struct netlink_linearize_ctx *lctx)
+{
+	memset(rule_ctx, 0, sizeof(*rule_ctx));
+	rule_ctx->nlh = nlh;
+	rule_ctx->cmd = cmd;
+	rule_ctx->lctx = lctx;
+}
+
 int mnl_nft_rule_add(struct netlink_ctx *ctx, struct cmd *cmd,
 		     unsigned int flags)
 {
+	struct mnl_nft_rule_build_ctx rule_ctx;
+	struct netlink_linearize_ctx lctx;
 	struct rule *rule = cmd->rule;
 	struct handle *h = &rule->handle;
 	struct nftnl_rule *nlr;
 	struct nlmsghdr *nlh;
+	struct nlattr *nest;
 
 	nlr = nftnl_rule_alloc();
 	if (!nlr)
@@ -446,7 +488,8 @@ int mnl_nft_rule_add(struct netlink_ctx *ctx, struct cmd *cmd,
 	if (h->position_id)
 		nftnl_rule_set_u32(nlr, NFTNL_RULE_POSITION_ID, h->position_id);
 
-	netlink_linearize_rule(ctx, nlr, rule);
+	netlink_linearize_init(&lctx, nlr);
+	netlink_linearize_rule(ctx, rule, &lctx);
 	nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
 				    NFT_MSG_NEWRULE,
 				    cmd->handle.family,
@@ -461,8 +504,15 @@ int mnl_nft_rule_add(struct netlink_ctx *ctx, struct cmd *cmd,
 	else
 		mnl_attr_put_strz(nlh, NFTA_RULE_CHAIN, h->chain.name);
 
+	mnl_nft_rule_build_ctx_init(&rule_ctx, nlh, cmd, &lctx);
+
+	nest = mnl_attr_nest_start(nlh, NFTA_RULE_EXPRESSIONS);
+	nftnl_expr_foreach(nlr, mnl_nft_expr_build_cb, &rule_ctx);
+	mnl_attr_nest_end(nlh, nest);
+
 	nftnl_rule_nlmsg_build_payload(nlh, nlr);
 	nftnl_rule_free(nlr);
+	netlink_linearize_fini(&lctx);
 
 	mnl_nft_batch_continue(ctx->batch);
 
@@ -471,11 +521,14 @@ int mnl_nft_rule_add(struct netlink_ctx *ctx, struct cmd *cmd,
 
 int mnl_nft_rule_replace(struct netlink_ctx *ctx, struct cmd *cmd)
 {
+	struct mnl_nft_rule_build_ctx rule_ctx;
+	struct netlink_linearize_ctx lctx;
 	struct rule *rule = cmd->rule;
 	struct handle *h = &rule->handle;
 	unsigned int flags = 0;
 	struct nftnl_rule *nlr;
 	struct nlmsghdr *nlh;
+	struct nlattr *nest;
 
 	if (nft_output_echo(&ctx->nft->output))
 		flags |= NLM_F_ECHO;
@@ -486,7 +539,8 @@ int mnl_nft_rule_replace(struct netlink_ctx *ctx, struct cmd *cmd)
 
 	nftnl_rule_set_u32(nlr, NFTNL_RULE_FAMILY, h->family);
 
-	netlink_linearize_rule(ctx, nlr, rule);
+	netlink_linearize_init(&lctx, nlr);
+	netlink_linearize_rule(ctx, rule, &lctx);
 	nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
 				    NFT_MSG_NEWRULE,
 				    cmd->handle.family,
@@ -499,8 +553,15 @@ int mnl_nft_rule_replace(struct netlink_ctx *ctx, struct cmd *cmd)
 	cmd_add_loc(cmd, nlh->nlmsg_len, &h->handle.location);
 	mnl_attr_put_u64(nlh, NFTA_RULE_HANDLE, htobe64(h->handle.id));
 
+	mnl_nft_rule_build_ctx_init(&rule_ctx, nlh, cmd, &lctx);
+
+	nest = mnl_attr_nest_start(nlh, NFTA_RULE_EXPRESSIONS);
+	nftnl_expr_foreach(nlr, mnl_nft_expr_build_cb, &rule_ctx);
+	mnl_attr_nest_end(nlh, nest);
+
 	nftnl_rule_nlmsg_build_payload(nlh, nlr);
 	nftnl_rule_free(nlr);
+	netlink_linearize_fini(&lctx);
 
 	mnl_nft_batch_continue(ctx->batch);
 
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index e5f601d4bc94..28c1afbfe518 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -24,11 +24,34 @@
 #include <linux/netfilter.h>
 #include <libnftnl/udata.h>
 
+struct nft_expr_loc *nft_expr_loc_find(const struct nftnl_expr *nle,
+				       struct netlink_linearize_ctx *ctx)
+{
+	struct nft_expr_loc *eloc;
+	uint32_t hash;
+
+	hash = (uint64_t)nle % NFT_EXPR_LOC_HSIZE;
+	list_for_each_entry(eloc, &ctx->expr_loc_htable[hash], hlist) {
+		if (eloc->nle == nle)
+			return eloc;
+	}
+
+	return NULL;
+}
 
-struct netlink_linearize_ctx {
-	struct nftnl_rule	*nlr;
-	unsigned int		reg_low;
-};
+static void nft_expr_loc_add(const struct nftnl_expr *nle,
+			     const struct location *loc,
+			     struct netlink_linearize_ctx *ctx)
+{
+	struct nft_expr_loc *eloc;
+	uint32_t hash;
+
+	eloc = xmalloc(sizeof(*eloc));
+	eloc->nle = nle;
+	eloc->loc = *loc;
+	hash = (uint64_t)nle % NFT_EXPR_LOC_HSIZE;
+	list_add_tail(&eloc->hlist, &ctx->expr_loc_htable[hash]);
+}
 
 static void netlink_put_register(struct nftnl_expr *nle,
 				 uint32_t attr, uint32_t reg)
@@ -105,6 +128,14 @@ static void netlink_gen_concat(struct netlink_linearize_ctx *ctx,
 	}
 }
 
+static void nft_rule_add_expr(struct netlink_linearize_ctx *ctx,
+			      struct nftnl_expr *nle,
+			      const struct location *loc)
+{
+	nft_expr_loc_add(nle, loc, ctx);
+	nftnl_rule_add_expr(ctx->nlr, nle);
+}
+
 static void netlink_gen_fib(struct netlink_linearize_ctx *ctx,
 			    const struct expr *expr,
 			    enum nft_registers dreg)
@@ -116,7 +147,7 @@ static void netlink_gen_fib(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_FIB_RESULT, expr->fib.result);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_FIB_FLAGS, expr->fib.flags);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_hash(struct netlink_linearize_ctx *ctx,
@@ -144,7 +175,7 @@ static void netlink_gen_hash(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_SEED, expr->hash.seed);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_OFFSET, expr->hash.offset);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_TYPE, expr->hash.type);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_payload(struct netlink_linearize_ctx *ctx,
@@ -162,7 +193,7 @@ static void netlink_gen_payload(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_PAYLOAD_LEN,
 			   div_round_up(expr->len, BITS_PER_BYTE));
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_exthdr(struct netlink_linearize_ctx *ctx,
@@ -181,7 +212,7 @@ static void netlink_gen_exthdr(struct netlink_linearize_ctx *ctx,
 			   div_round_up(expr->len, BITS_PER_BYTE));
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_OP, expr->exthdr.op);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_FLAGS, expr->exthdr.flags);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_meta(struct netlink_linearize_ctx *ctx,
@@ -193,7 +224,7 @@ static void netlink_gen_meta(struct netlink_linearize_ctx *ctx,
 	nle = alloc_nft_expr("meta");
 	netlink_put_register(nle, NFTNL_EXPR_META_DREG, dreg);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_META_KEY, expr->meta.key);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_rt(struct netlink_linearize_ctx *ctx,
@@ -205,7 +236,7 @@ static void netlink_gen_rt(struct netlink_linearize_ctx *ctx,
 	nle = alloc_nft_expr("rt");
 	netlink_put_register(nle, NFTNL_EXPR_RT_DREG, dreg);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_RT_KEY, expr->rt.key);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_socket(struct netlink_linearize_ctx *ctx,
@@ -217,7 +248,7 @@ static void netlink_gen_socket(struct netlink_linearize_ctx *ctx,
 	nle = alloc_nft_expr("socket");
 	netlink_put_register(nle, NFTNL_EXPR_SOCKET_DREG, dreg);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_SOCKET_KEY, expr->socket.key);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_osf(struct netlink_linearize_ctx *ctx,
@@ -230,7 +261,7 @@ static void netlink_gen_osf(struct netlink_linearize_ctx *ctx,
 	netlink_put_register(nle, NFTNL_EXPR_OSF_DREG, dreg);
 	nftnl_expr_set_u8(nle, NFTNL_EXPR_OSF_TTL, expr->osf.ttl);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_OSF_FLAGS, expr->osf.flags);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_numgen(struct netlink_linearize_ctx *ctx,
@@ -244,7 +275,7 @@ static void netlink_gen_numgen(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_TYPE, expr->numgen.type);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_MODULUS, expr->numgen.mod);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_OFFSET, expr->numgen.offset);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_ct(struct netlink_linearize_ctx *ctx,
@@ -260,7 +291,7 @@ static void netlink_gen_ct(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set_u8(nle, NFTNL_EXPR_CT_DIR,
 				  expr->ct.direction);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_map(struct netlink_linearize_ctx *ctx,
@@ -298,7 +329,7 @@ static void netlink_gen_map(struct netlink_linearize_ctx *ctx,
 	if (dreg == NFT_REG_VERDICT)
 		release_register(ctx, expr->map);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_lookup(struct netlink_linearize_ctx *ctx,
@@ -324,7 +355,7 @@ static void netlink_gen_lookup(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set_u32(nle, NFTNL_EXPR_LOOKUP_FLAGS, NFT_LOOKUP_F_INV);
 
 	release_register(ctx, expr->left);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static enum nft_cmp_ops netlink_gen_cmp_op(enum ops op)
@@ -370,7 +401,7 @@ static struct expr *netlink_gen_prefix(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_BITWISE_LEN, nld.len);
 	nftnl_expr_set(nle, NFTNL_EXPR_BITWISE_MASK, &nld.value, nld.len);
 	nftnl_expr_set(nle, NFTNL_EXPR_BITWISE_XOR, &zero.value, zero.len);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 
 	return expr->right->prefix;
 }
@@ -400,7 +431,7 @@ static void netlink_gen_range(struct netlink_linearize_ctx *ctx,
 		netlink_gen_data(range->right, &nld);
 		nftnl_expr_set(nle, NFTNL_EXPR_RANGE_TO_DATA,
 			       nld.value, nld.len);
-		nftnl_rule_add_expr(ctx->nlr, nle);
+		nft_rule_add_expr(ctx, nle, &expr->location);
 		break;
 	case OP_EQ:
 	case OP_IMPLICIT:
@@ -410,7 +441,7 @@ static void netlink_gen_range(struct netlink_linearize_ctx *ctx,
 				   netlink_gen_cmp_op(OP_GTE));
 		netlink_gen_data(range->left, &nld);
 		nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len);
-		nftnl_rule_add_expr(ctx->nlr, nle);
+		nft_rule_add_expr(ctx, nle, &expr->location);
 
 		nle = alloc_nft_expr("cmp");
 		netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg);
@@ -418,7 +449,7 @@ static void netlink_gen_range(struct netlink_linearize_ctx *ctx,
 				   netlink_gen_cmp_op(OP_LTE));
 		netlink_gen_data(range->right, &nld);
 		nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len);
-		nftnl_rule_add_expr(ctx->nlr, nle);
+		nft_rule_add_expr(ctx, nle, &expr->location);
 		break;
 	default:
 		BUG("invalid range operation %u\n", expr->op);
@@ -455,13 +486,13 @@ static void netlink_gen_flagcmp(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_BITWISE_LEN, len);
 	nftnl_expr_set(nle, NFTNL_EXPR_BITWISE_MASK, &nld2.value, nld2.len);
 	nftnl_expr_set(nle, NFTNL_EXPR_BITWISE_XOR, &nld.value, nld.len);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 
 	nle = alloc_nft_expr("cmp");
 	netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_NEQ);
 	nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 
 	mpz_clear(zero);
 	release_register(ctx, expr->left);
@@ -534,7 +565,7 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, len);
 	release_register(ctx, expr->left);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void combine_binop(mpz_t mask, mpz_t xor, const mpz_t m, const mpz_t x)
@@ -570,7 +601,7 @@ static void netlink_gen_shift(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set(nle, NFTNL_EXPR_BITWISE_DATA, nld.value,
 		       nld.len);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_bitwise(struct netlink_linearize_ctx *ctx,
@@ -640,7 +671,7 @@ static void netlink_gen_bitwise(struct netlink_linearize_ctx *ctx,
 	mpz_clear(xor);
 	mpz_clear(mask);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_binop(struct netlink_linearize_ctx *ctx,
@@ -695,15 +726,16 @@ static void netlink_gen_unary(struct netlink_linearize_ctx *ctx,
 			   byte_size);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_BYTEORDER_OP,
 			   netlink_gen_unary_op(expr->op));
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_immediate(struct netlink_linearize_ctx *ctx,
 				  const struct expr *expr,
 				  enum nft_registers dreg)
 {
-	struct nftnl_expr *nle;
+	const struct location *loc = &expr->location;
 	struct nft_data_linearize nld;
+	struct nftnl_expr *nle;
 
 	nle = alloc_nft_expr("immediate");
 	netlink_put_register(nle, NFTNL_EXPR_IMM_DREG, dreg);
@@ -716,6 +748,7 @@ static void netlink_gen_immediate(struct netlink_linearize_ctx *ctx,
 		if (expr->chain) {
 			nftnl_expr_set_str(nle, NFTNL_EXPR_IMM_CHAIN,
 					   nld.chain);
+			loc = &expr->chain->location;
 		} else if (expr->chain_id) {
 			nftnl_expr_set_u32(nle, NFTNL_EXPR_IMM_CHAIN_ID,
 					   nld.chain_id);
@@ -725,7 +758,7 @@ static void netlink_gen_immediate(struct netlink_linearize_ctx *ctx,
 	default:
 		break;
 	}
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, loc);
 }
 
 static void netlink_gen_xfrm(struct netlink_linearize_ctx *ctx,
@@ -739,7 +772,7 @@ static void netlink_gen_xfrm(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_XFRM_KEY, expr->xfrm.key);
 	nftnl_expr_set_u8(nle, NFTNL_EXPR_XFRM_DIR, expr->xfrm.direction);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_XFRM_SPNUM, expr->xfrm.spnum);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_expr(struct netlink_linearize_ctx *ctx,
@@ -822,7 +855,7 @@ static void netlink_gen_objref_stmt(struct netlink_linearize_ctx *ctx,
 	default:
 		BUG("unsupported expression %u\n", expr->etype);
 	}
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static struct nftnl_expr *netlink_gen_connlimit_stmt(const struct stmt *stmt)
@@ -941,7 +974,7 @@ static void netlink_gen_exthdr_stmt(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_LEN,
 			   div_round_up(expr->len, BITS_PER_BYTE));
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_OP, expr->exthdr.op);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_payload_stmt(struct netlink_linearize_ctx *ctx,
@@ -983,7 +1016,7 @@ static void netlink_gen_payload_stmt(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set_u32(nle, NFTNL_EXPR_PAYLOAD_FLAGS,
 				   NFT_PAYLOAD_L4CSUM_PSEUDOHDR);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &expr->location);
 }
 
 static void netlink_gen_meta_stmt(struct netlink_linearize_ctx *ctx,
@@ -999,7 +1032,7 @@ static void netlink_gen_meta_stmt(struct netlink_linearize_ctx *ctx,
 	nle = alloc_nft_expr("meta");
 	netlink_put_register(nle, NFTNL_EXPR_META_SREG, sreg);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_META_KEY, stmt->meta.key);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_log_stmt(struct netlink_linearize_ctx *ctx,
@@ -1030,7 +1063,7 @@ static void netlink_gen_log_stmt(struct netlink_linearize_ctx *ctx,
 			nftnl_expr_set_u32(nle, NFTNL_EXPR_LOG_FLAGS,
 					   stmt->log.logflags);
 	}
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_reject_stmt(struct netlink_linearize_ctx *ctx,
@@ -1044,7 +1077,7 @@ static void netlink_gen_reject_stmt(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set_u8(nle, NFTNL_EXPR_REJECT_CODE,
 				  stmt->reject.icmp_code);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static unsigned int nat_addrlen(uint8_t family)
@@ -1175,7 +1208,7 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
 		registers--;
 	}
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_tproxy_stmt(struct netlink_linearize_ctx *ctx,
@@ -1214,7 +1247,7 @@ static void netlink_gen_tproxy_stmt(struct netlink_linearize_ctx *ctx,
 		registers--;
 	}
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_synproxy_stmt(struct netlink_linearize_ctx *ctx,
@@ -1229,7 +1262,7 @@ static void netlink_gen_synproxy_stmt(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_SYNPROXY_FLAGS,
 			   stmt->synproxy.flags);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_dup_stmt(struct netlink_linearize_ctx *ctx,
@@ -1260,7 +1293,7 @@ static void netlink_gen_dup_stmt(struct netlink_linearize_ctx *ctx,
 	if (stmt->dup.to != NULL)
 		release_register(ctx, stmt->dup.to);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_fwd_stmt(struct netlink_linearize_ctx *ctx,
@@ -1287,7 +1320,7 @@ static void netlink_gen_fwd_stmt(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set_u32(nle, NFTNL_EXPR_FWD_NFPROTO,
 				   stmt->fwd.family);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_queue_stmt(struct netlink_linearize_ctx *ctx,
@@ -1312,7 +1345,7 @@ static void netlink_gen_queue_stmt(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set_u16(nle, NFTNL_EXPR_QUEUE_FLAGS,
 				   stmt->queue.flags);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 
 	mpz_clear(low);
 	mpz_clear(high);
@@ -1335,7 +1368,7 @@ static void netlink_gen_ct_stmt(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set_u8(nle, NFTNL_EXPR_CT_DIR,
 				  stmt->ct.direction);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_notrack_stmt(struct netlink_linearize_ctx *ctx,
@@ -1344,7 +1377,7 @@ static void netlink_gen_notrack_stmt(struct netlink_linearize_ctx *ctx,
 	struct nftnl_expr *nle;
 
 	nle = alloc_nft_expr("notrack");
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_flow_offload_stmt(struct netlink_linearize_ctx *ctx,
@@ -1355,7 +1388,7 @@ static void netlink_gen_flow_offload_stmt(struct netlink_linearize_ctx *ctx,
 	nle = alloc_nft_expr("flow_offload");
 	nftnl_expr_set_str(nle, NFTNL_EXPR_FLOW_TABLE_NAME,
 			   stmt->flow.table_name);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx,
@@ -1377,7 +1410,7 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_OP, stmt->set.op);
 	nftnl_expr_set_str(nle, NFTNL_EXPR_DYNSET_SET_NAME, set->handle.set.name);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 
 	if (stmt->set.stmt)
 		nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
@@ -1413,7 +1446,7 @@ static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx,
 		nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
 			       netlink_gen_stmt_stateful(stmt->map.stmt), 0);
 
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_meter_stmt(struct netlink_linearize_ctx *ctx,
@@ -1444,7 +1477,7 @@ static void netlink_gen_meter_stmt(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id);
 	nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
 		       netlink_gen_stmt_stateful(stmt->meter.stmt), 0);
-	nftnl_rule_add_expr(ctx->nlr, nle);
+	nft_rule_add_expr(ctx, nle, &stmt->location);
 }
 
 static void netlink_gen_chain_stmt(struct netlink_linearize_ctx *ctx,
@@ -1496,7 +1529,7 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
 	case STMT_LIMIT:
 	case STMT_QUOTA:
 		nle = netlink_gen_stmt_stateful(stmt);
-		nftnl_rule_add_expr(ctx->nlr, nle);
+		nft_rule_add_expr(ctx, nle, &stmt->location);
 		break;
 	case STMT_NOTRACK:
 		return netlink_gen_notrack_stmt(ctx, stmt);
@@ -1513,18 +1546,40 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
 	}
 }
 
-void netlink_linearize_rule(struct netlink_ctx *ctx, struct nftnl_rule *nlr,
-			    const struct rule *rule)
+void netlink_linearize_init(struct netlink_linearize_ctx *lctx,
+			    struct nftnl_rule *nlr)
 {
-	struct netlink_linearize_ctx lctx;
-	const struct stmt *stmt;
+	int i;
+
+	memset(lctx, 0, sizeof(*lctx));
+	lctx->reg_low = NFT_REG_1;
+	lctx->nlr = nlr;
+	lctx->expr_loc_htable =
+		xmalloc(sizeof(struct list_head) * NFT_EXPR_LOC_HSIZE);
+	for (i = 0; i < NFT_EXPR_LOC_HSIZE; i++)
+		init_list_head(&lctx->expr_loc_htable[i]);
+}
 
-	memset(&lctx, 0, sizeof(lctx));
-	lctx.reg_low = NFT_REG_1;
-	lctx.nlr = nlr;
+void netlink_linearize_fini(struct netlink_linearize_ctx *lctx)
+{
+	struct nft_expr_loc *eloc, *next;
+	int i;
+
+	for (i = 0; i < NFT_EXPR_LOC_HSIZE; i++) {
+		list_for_each_entry_safe(eloc, next, &lctx->expr_loc_htable[i], hlist)
+			xfree(eloc);
+	}
+	xfree(lctx->expr_loc_htable);
+}
+
+void netlink_linearize_rule(struct netlink_ctx *ctx,
+			    const struct rule *rule,
+			    struct netlink_linearize_ctx *lctx)
+{
+	const struct stmt *stmt;
 
 	list_for_each_entry(stmt, &rule->stmts, list)
-		netlink_gen_stmt(&lctx, stmt);
+		netlink_gen_stmt(lctx, stmt);
 
 	if (rule->comment) {
 		struct nftnl_udata_buf *udata;
@@ -1536,12 +1591,12 @@ void netlink_linearize_rule(struct netlink_ctx *ctx, struct nftnl_rule *nlr,
 		if (!nftnl_udata_put_strz(udata, NFTNL_UDATA_RULE_COMMENT,
 					  rule->comment))
 			memory_allocation_error();
-		nftnl_rule_set_data(nlr, NFTNL_RULE_USERDATA,
+		nftnl_rule_set_data(lctx->nlr, NFTNL_RULE_USERDATA,
 				    nftnl_udata_buf_data(udata),
 				    nftnl_udata_buf_len(udata));
 
 		nftnl_udata_buf_free(udata);
 	}
 
-	netlink_dump_rule(nlr, ctx);
+	netlink_dump_rule(lctx->nlr, ctx);
 }
-- 
2.20.1


      reply	other threads:[~2020-10-19 12:50 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-19 12:50 [PATCH nft 1/2] rule: larger number of error locations Pablo Neira Ayuso
2020-10-19 12:50 ` Pablo Neira Ayuso [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201019125012.14373-2-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).