summaryrefslogtreecommitdiffstats
path: root/src/netlink_linearize.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/netlink_linearize.c')
-rw-r--r--src/netlink_linearize.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 7715a287..7ff3b004 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -181,6 +181,18 @@ static void netlink_gen_payload(struct netlink_linearize_ctx *ctx,
netlink_gen_payload_mask(ctx, expr, dreg);
}
+static void netlink_gen_exthdr_mask(struct netlink_linearize_ctx *ctx,
+ const struct expr *expr,
+ enum nft_registers dreg)
+{
+ unsigned int shift, offset;
+
+ offset = expr->exthdr.tmpl->offset % BITS_PER_BYTE;
+ shift = payload_shift_calc(expr, offset);
+ if (shift || offset)
+ netlink_gen_mask(ctx, expr, shift, dreg);
+}
+
static void netlink_gen_exthdr(struct netlink_linearize_ctx *ctx,
const struct expr *expr,
enum nft_registers dreg)
@@ -194,8 +206,10 @@ static void netlink_gen_exthdr(struct netlink_linearize_ctx *ctx,
nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_OFFSET,
expr->exthdr.tmpl->offset / BITS_PER_BYTE);
nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_LEN,
- expr->len / BITS_PER_BYTE);
+ div_round_up(expr->len, BITS_PER_BYTE));
nftnl_rule_add_expr(ctx->nlr, nle);
+
+ netlink_gen_exthdr_mask(ctx, expr, dreg);
}
static void netlink_gen_meta(struct netlink_linearize_ctx *ctx,
@@ -306,10 +320,17 @@ static void netlink_gen_range(struct netlink_linearize_ctx *ctx,
static void payload_shift_value(const struct expr *left, struct expr *right)
{
- if (right->ops->type != EXPR_VALUE ||
- left->ops->type != EXPR_PAYLOAD)
+ if (right->ops->type != EXPR_VALUE)
return;
+ switch (left->ops->type) {
+ case EXPR_PAYLOAD:
+ case EXPR_EXTHDR:
+ break;
+ default:
+ return;
+ }
+
mpz_lshift_ui(right->value,
payload_shift_calc(left, left->payload.offset));
}