From 45e5e4e92a2c882b22e95a807026611612d57729 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 2 Mar 2016 13:56:43 +0100 Subject: 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 Acked-by: Pablo Neira Ayuso --- src/exthdr.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/exthdr.c') diff --git a/src/exthdr.c b/src/exthdr.c index 512de0ae..f392cffe 100644 --- a/src/exthdr.c +++ b/src/exthdr.c @@ -102,6 +102,37 @@ void exthdr_init_raw(struct expr *expr, uint8_t type, } } +static unsigned int mask_length(const struct expr *mask) +{ + unsigned long off = mpz_scan1(mask->value, 0); + + return mpz_scan0(mask->value, off + 1); +} + +bool exthdr_find_template(struct expr *expr, const struct expr *mask, unsigned int *shift) +{ + unsigned int off, mask_offset, mask_len; + + if (expr->exthdr.tmpl != &exthdr_unknown_template) + return false; + + mask_offset = mpz_scan1(mask->value, 0); + mask_len = mask_length(mask); + + off = expr->exthdr.offset; + off += round_up(mask->len, BITS_PER_BYTE) - mask_len; + + exthdr_init_raw(expr, expr->exthdr.desc->type, + off, mask_len - mask_offset); + + /* still failed to find a template... Bug. */ + if (expr->exthdr.tmpl == &exthdr_unknown_template) + return false; + + *shift = mask_offset; + return true; +} + #define HDR_TEMPLATE(__name, __dtype, __type, __member) \ PROTO_HDR_TEMPLATE(__name, __dtype, \ BYTEORDER_BIG_ENDIAN, \ -- cgit v1.2.3