netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nft 1/2] rule: larger number of error locations
@ 2020-10-19 12:50 Pablo Neira Ayuso
  2020-10-19 12:50 ` [PATCH nft 2/2] src: improve rule error reporting Pablo Neira Ayuso
  0 siblings, 1 reply; 2+ messages in thread
From: Pablo Neira Ayuso @ 2020-10-19 12:50 UTC (permalink / raw)
  To: netfilter-devel

Statically store up to 32 locations per command, if the number of
locations is larger than 32, then skip rather than hit assertion.

Revisit this later to dynamically store location per command using a
hashtable.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/rule.h | 2 +-
 src/rule.c     | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index ffe8daab6f1c..10e71047fb07 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -666,7 +666,7 @@ struct monitor {
 struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event);
 void monitor_free(struct monitor *m);
 
-#define NFT_NLATTR_LOC_MAX 8
+#define NFT_NLATTR_LOC_MAX 32
 
 /**
  * struct cmd - command statement
diff --git a/src/rule.c b/src/rule.c
index 4719fd6158f2..e57009b23c8e 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1475,7 +1475,9 @@ struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
 
 void cmd_add_loc(struct cmd *cmd, uint16_t offset, struct location *loc)
 {
-	assert(cmd->num_attrs < NFT_NLATTR_LOC_MAX);
+	if (cmd->num_attrs > NFT_NLATTR_LOC_MAX)
+		return;
+
 	cmd->attr[cmd->num_attrs].offset = offset;
 	cmd->attr[cmd->num_attrs].location = loc;
 	cmd->num_attrs++;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH nft 2/2] src: improve rule error reporting
  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
  0 siblings, 0 replies; 2+ messages in thread
From: Pablo Neira Ayuso @ 2020-10-19 12:50 UTC (permalink / raw)
  To: netfilter-devel

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


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-10-19 12:50 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-19 12:50 [PATCH nft 1/2] rule: larger number of error locations Pablo Neira Ayuso
2020-10-19 12:50 ` [PATCH nft 2/2] src: improve rule error reporting Pablo Neira Ayuso

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).