[PATCH nft 6/7] netlink: add support for handling shift expressions.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The kernel supports bitwise shift operations, so add support to the
netlink linearization and delinearization code.

Signed-off-by: Jeremy Sowden <jeremy@xxxxxxxxxx>
---
 include/linux/netfilter/nf_tables.h |  4 +++
 src/netlink_delinearize.c           | 19 +++++++++++++
 src/netlink_linearize.c             | 42 ++++++++++++++++++++++++++---
 3 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index c556ccd3dbf7..12dbb2adbbdf 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -490,6 +490,8 @@ enum nft_immediate_attributes {
  * @NFTA_BITWISE_LEN: length of operands (NLA_U32)
  * @NFTA_BITWISE_MASK: mask value (NLA_NESTED: nft_data_attributes)
  * @NFTA_BITWISE_XOR: xor value (NLA_NESTED: nft_data_attributes)
+ * @NFTA_BITWISE_LSHIFT: left shift value (NLA_U32)
+ * @NFTA_BITWISE_RSHIFT: right shift value (NLA_U32)
  *
  * The bitwise expression performs the following operation:
  *
@@ -510,6 +512,8 @@ enum nft_bitwise_attributes {
 	NFTA_BITWISE_LEN,
 	NFTA_BITWISE_MASK,
 	NFTA_BITWISE_XOR,
+	NFTA_BITWISE_LSHIFT,
+	NFTA_BITWISE_RSHIFT,
 	__NFTA_BITWISE_MAX
 };
 #define NFTA_BITWISE_MAX	(__NFTA_BITWISE_MAX - 1)
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 8f2a5dfacd3e..a45ad924b216 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -372,6 +372,24 @@ static void netlink_parse_bitwise(struct netlink_parse_ctx *ctx,
 				     "Bitwise expression has no left "
 				     "hand side");
 
+	nld.value = nftnl_expr_get(nle, NFTNL_EXPR_BITWISE_LSHIFT, &nld.len);
+	if (nld.value != NULL) {
+		struct expr *right = netlink_alloc_value(loc, &nld);
+
+		expr = binop_expr_alloc(loc, OP_LSHIFT, left, right);
+		expr->len = left->len;
+		goto dreg;
+	}
+
+	nld.value = nftnl_expr_get(nle, NFTNL_EXPR_BITWISE_RSHIFT, &nld.len);
+	if (nld.value != NULL) {
+		struct expr *right = netlink_alloc_value(loc, &nld);
+
+		expr = binop_expr_alloc(loc, OP_RSHIFT, left, right);
+		expr->len = left->len;
+		goto dreg;
+	}
+
 	expr = left;
 
 	nld.value = nftnl_expr_get(nle, NFTNL_EXPR_BITWISE_MASK, &nld.len);
@@ -423,6 +441,7 @@ static void netlink_parse_bitwise(struct netlink_parse_ctx *ctx,
 	mpz_clear(x);
 	mpz_clear(o);
 
+dreg:
 	dreg = netlink_parse_register(nle, NFTNL_EXPR_BITWISE_DREG);
 	netlink_set_register(ctx, dreg, expr);
 }
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index d5e177d5e75c..19a513021fcb 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -545,9 +545,29 @@ static void combine_binop(mpz_t mask, mpz_t xor, const mpz_t m, const mpz_t x)
 	mpz_and(mask, mask, m);
 }
 
-static void netlink_gen_binop(struct netlink_linearize_ctx *ctx,
+static void netlink_gen_shift(struct netlink_linearize_ctx *ctx,
 			      const struct expr *expr,
 			      enum nft_registers dreg)
+{
+	enum nft_bitwise_attributes shift_attr = expr->op == OP_LSHIFT ?
+		NFTNL_EXPR_BITWISE_LSHIFT : NFTNL_EXPR_BITWISE_RSHIFT;
+	unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
+	struct nftnl_expr *nle;
+
+	netlink_gen_expr(ctx, expr->left, dreg);
+
+	nle = alloc_nft_expr("bitwise");
+	netlink_put_register(nle, NFTNL_EXPR_BITWISE_SREG, dreg);
+	netlink_put_register(nle, NFTNL_EXPR_BITWISE_DREG, dreg);
+	nftnl_expr_set_u32(nle, NFTNL_EXPR_BITWISE_LEN, len);
+	nftnl_expr_set_u32(nle, shift_attr, mpz_get_uint32(expr->right->value));
+
+	nftnl_rule_add_expr(ctx->nlr, nle);
+}
+
+static void netlink_gen_bitwise(struct netlink_linearize_ctx *ctx,
+				const struct expr *expr,
+				enum nft_registers dreg)
 {
 	struct nftnl_expr *nle;
 	struct nft_data_linearize nld;
@@ -562,8 +582,9 @@ static void netlink_gen_binop(struct netlink_linearize_ctx *ctx,
 	mpz_init(val);
 	mpz_init(tmp);
 
-	binops[n++] = left = (void *)expr;
-	while (left->etype == EXPR_BINOP && left->left != NULL)
+	binops[n++] = left = (struct expr *) expr;
+	while (left->etype == EXPR_BINOP && left->left != NULL &&
+	       (left->op == OP_AND || left->op == OP_OR || left->op == OP_XOR))
 		binops[n++] = left = left->left;
 	n--;
 
@@ -613,6 +634,21 @@ static void netlink_gen_binop(struct netlink_linearize_ctx *ctx,
 	nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
+static void netlink_gen_binop(struct netlink_linearize_ctx *ctx,
+			      const struct expr *expr,
+			      enum nft_registers dreg)
+{
+	switch(expr->op) {
+	case OP_LSHIFT:
+	case OP_RSHIFT:
+		netlink_gen_shift(ctx, expr, dreg);
+		break;
+	default:
+		netlink_gen_bitwise(ctx, expr, dreg);
+		break;
+	}
+}
+
 static enum nft_byteorder_ops netlink_gen_unary_op(enum ops op)
 {
 	switch (op) {
-- 
2.24.1




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux