diff options
author | Florian Westphal <fw@strlen.de> | 2016-03-02 13:56:43 +0100 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2016-03-02 13:56:43 +0100 |
commit | 45e5e4e92a2c882b22e95a807026611612d57729 (patch) | |
tree | 7033161bdc8b1ccb910d830fc58af0b257604b28 /src/netlink_delinearize.c | |
parent | 3bfe9a0323df8e23fa5150b88282cc7b4a6379f0 (diff) |
netlink_delinearize: handle extension header templates with odd sizes
This enables nft to display
frag frag-off 33
... by considering a mask during binop postprocess in case
the initial template lookup done when the exthdr expression was
created did not yield a match.
In the above example, kernel netlink data specifies 16bits,
but the frag field is only 13bits wide.
We use the implicit binop mask to re-do the template lookup with
corrected offset and size information.
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r-- | src/netlink_delinearize.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 30c5f62e..fae6e33d 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -1218,7 +1218,9 @@ static void binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr) unsigned int shift; if ((left->ops->type == EXPR_PAYLOAD && - payload_expr_trim(left, mask, &ctx->pctx, &shift))) { + payload_expr_trim(left, mask, &ctx->pctx, &shift)) || + (left->ops->type == EXPR_EXTHDR && + exthdr_find_template(left, mask, &shift))) { /* mask is implicit, binop needs to be removed. * * Fix all values of the expression according to the mask @@ -1226,7 +1228,7 @@ static void binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr) * sizes and offsets we're interested in. * * Finally, convert the expression to 1) by replacing - * the binop with the binop payload expr. + * the binop with the binop payload/exthdr expression. */ if (value->ops->type == EXPR_VALUE) { assert(value->len >= expr->left->right->len); @@ -1238,8 +1240,10 @@ static void binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr) assert(binop->left == left); expr->left = expr_get(left); expr_free(binop); - - payload_match_postprocess(ctx, expr, left); + if (left->ops->type == EXPR_PAYLOAD) + payload_match_postprocess(ctx, expr, left); + else if (left->ops->type == EXPR_EXTHDR) + expr_set_type(expr->right, left->dtype, left->byteorder); } } |