From 694cf23999eea468dc3124f1269f333d47a75a5e Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Sun, 19 Jan 2020 22:57:09 +0000 Subject: 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 Signed-off-by: Pablo Neira Ayuso --- src/netlink_linearize.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) (limited to 'src/netlink_linearize.c') 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,9 +545,36 @@ 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; @@ -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) { -- cgit v1.2.3