This array holds each concat component's actual length in bytes. It is crucial because component data is padded to match register lengths and if libnftnl has to print data "in reverse" (to print Little Endian values byte-by-byte), it will print extra leading zeroes with odd data lengths and thus indicate number of printed bytes does no longer correctly reflect actual data length. Signed-off-by: Phil Sutter --- include/netlink.h | 1 + src/netlink.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/netlink.h b/include/netlink.h index a762cb485784f..aa25094dc7c1d 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -107,6 +107,7 @@ struct nft_data_linearize { uint32_t chain_id; int verdict; uint32_t byteorder; + uint8_t sizes[NFT_REG32_COUNT]; }; struct nft_data_delinearize { diff --git a/src/netlink.c b/src/netlink.c index 2a4315c691059..9d6cc31e40fb5 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -365,7 +365,7 @@ static void netlink_gen_concat_key(const struct expr *expr, offset += __netlink_gen_concat_key(expr->flags, i, data + offset); if (i->byteorder == BYTEORDER_HOST_ENDIAN) nld->byteorder |= 1 << n; - n++; + nld->sizes[n++] = div_round_up(i->len, BITS_PER_BYTE); } nft_data_memcpy(nld, data, len); @@ -434,14 +434,14 @@ static void __netlink_gen_concat_expand(const struct expr *expr, offset += __netlink_gen_concat_data(false, i, data + offset); if (i->byteorder == BYTEORDER_HOST_ENDIAN) nld->byteorder |= 1 << n; - n++; + nld->sizes[n++] = div_round_up(i->len, BITS_PER_BYTE); } list_for_each_entry(i, &expr_concat(expr)->expressions, list) { offset += __netlink_gen_concat_data(true, i, data + offset); if (i->byteorder == BYTEORDER_HOST_ENDIAN) nld->byteorder |= 1 << n; - n++; + nld->sizes[n++] = div_round_up(i->len, BITS_PER_BYTE); } nft_data_memcpy(nld, data, len); @@ -465,7 +465,7 @@ static void __netlink_gen_concat(const struct expr *expr, offset += __netlink_gen_concat_data(expr->flags, i, data + offset); if (i->byteorder == BYTEORDER_HOST_ENDIAN) nld->byteorder |= 1 << n; - n++; + nld->sizes[n++] = div_round_up(i->len, BITS_PER_BYTE); } nft_data_memcpy(nld, data, len); @@ -541,6 +541,8 @@ static void netlink_gen_range(const struct expr *expr, offset = netlink_export_pad(data, expr->left->value, expr->left); netlink_export_pad(data + offset, expr->right->value, expr->right); nft_data_memcpy(nld, data, len); + nld->sizes[0] = div_round_up(expr->left->len, BITS_PER_BYTE); + nld->sizes[1] = div_round_up(expr->right->len, BITS_PER_BYTE); } static void netlink_gen_range_value(const struct expr *expr, @@ -557,6 +559,8 @@ static void netlink_gen_range_value(const struct expr *expr, offset = netlink_export_pad(data, expr->range.low, expr); netlink_export_pad(data + offset, expr->range.high, expr); nft_data_memcpy(nld, data, len); + nld->sizes[0] = div_round_up(expr->len, BITS_PER_BYTE); + nld->sizes[1] = nld->sizes[0]; } static void netlink_gen_prefix(const struct expr *expr, @@ -577,6 +581,8 @@ static void netlink_gen_prefix(const struct expr *expr, mpz_clear(v); nft_data_memcpy(nld, data, len); + nld->sizes[0] = div_round_up(expr->prefix->len, BITS_PER_BYTE); + nld->sizes[1] = nld->sizes[0]; } static void netlink_gen_key(const struct expr *expr, -- 2.51.0