diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/netlink_linearize.c | 27 |
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)); } |