summaryrefslogtreecommitdiffstats
path: root/src/netlink_linearize.c
diff options
context:
space:
mode:
authorJeremy Sowden <jeremy@azazel.net>2020-01-19 22:57:09 +0000
committerPablo Neira Ayuso <pablo@netfilter.org>2020-01-28 20:16:02 +0100
commit694cf23999eea468dc3124f1269f333d47a75a5e (patch)
tree10f61ff69b87508a9a2e61bcf94b116bdd1f6a8c /src/netlink_linearize.c
parent21099e5e2dc0650e88ec7bbe6b3b3e56cb20bc65 (diff)
netlink: add support for handling shift expressions.
The kernel supports bitwise shift operations, so add support to the netlink linearization and delinearization code. The number of bits (the righthand operand) is expected to be a 32-bit value in host endianness. Signed-off-by: Jeremy Sowden <jeremy@azazel.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink_linearize.c')
-rw-r--r--src/netlink_linearize.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 92617964..b542aa3b 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -545,10 +545,37 @@ 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_ops op = expr->op == OP_LSHIFT ?
+ NFT_BITWISE_LSHIFT : NFT_BITWISE_RSHIFT;
+ unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
+ struct nft_data_linearize nld;
+ 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_OP, op);
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_BITWISE_LEN, len);
+
+ netlink_gen_raw_data(expr->right->value, expr->right->byteorder,
+ sizeof(uint32_t), &nld);
+
+ nftnl_expr_set(nle, NFTNL_EXPR_BITWISE_DATA, nld.value,
+ nld.len);
+
+ 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;
struct expr *left, *i;
@@ -562,8 +589,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--;
@@ -598,6 +626,7 @@ static void netlink_gen_binop(struct netlink_linearize_ctx *ctx,
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_OP, NFT_BITWISE_BOOL);
nftnl_expr_set_u32(nle, NFTNL_EXPR_BITWISE_LEN, len);
netlink_gen_raw_data(mask, expr->byteorder, len, &nld);
@@ -613,6 +642,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) {