nftables/0032-netlink-Introduce-struct-nft_data_linearize-byteorde.patch
Phil Sutter 66e3c74b83 nftables-1.1.5-4.el10
* Tue Feb 24 2026 Phil Sutter <psutter@redhat.com> [1.1.5-4.el10]
- spec: Require libnftnl-1.3.0-3 for nftnl_{expr,set_elem}_set_imm() (Phil Sutter) [RHEL-128553]
- tests: py: Adjust payloads to changed userdata printing (Phil Sutter) [RHEL-128553]
- tests: py: Update payload records (Phil Sutter) [RHEL-128553]
- tests: py: objects.t: must use input, not output (Phil Sutter) [RHEL-128553]
- tests: py: tools: Add regen_payloads.sh (Phil Sutter) [RHEL-128553]
- netlink: Make use of nftnl_{expr,set_elem}_set_imm() (Phil Sutter) [RHEL-128553]
- netlink: No need to reference array when passing as pointer (Phil Sutter) [RHEL-128553]
- netlink: Introduce struct nft_data_linearize::sizes (Phil Sutter) [RHEL-128553]
- netlink: Introduce struct nft_data_linearize::byteorder (Phil Sutter) [RHEL-128553]
- expression: Set range expression 'len' field (Phil Sutter) [RHEL-128553]
- intervals: Convert byte order implicitly (Phil Sutter) [RHEL-128553]
- mergesort: Align concatenation sort order with Big Endian (Phil Sutter) [RHEL-128553]
- mergesort: Fix sorting of string values (Phil Sutter) [RHEL-128553]
- segtree: Fix range aggregation on Big Endian (Phil Sutter) [RHEL-128553]
Resolves: RHEL-128553
2026-02-24 16:17:31 +01:00

219 lines
7.2 KiB
Diff

From 1f034c281e4e41eb260f7ad5667f9d8df638ed70 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Tue, 24 Feb 2026 15:53:23 +0100
Subject: [PATCH] netlink: Introduce struct nft_data_linearize::byteorder
JIRA: https://issues.redhat.com/browse/RHEL-128553
Upstream Status: nftables commit c06b480ea54bbdc997e69f047360541d141b00e1
commit c06b480ea54bbdc997e69f047360541d141b00e1
Author: Phil Sutter <phil@nwl.cc>
Date: Thu Nov 13 17:11:15 2025 +0100
netlink: Introduce struct nft_data_linearize::byteorder
Bits in this field indicate data is in host byte order and thus may need
conversion when being printed "byte-by-byte" in libnftnl.
With regular immediate values, this field's value has boolean properties
(if non-zero, data is in host byte order). Concatenations may contain
components in different byte order, so with them each bit (at index N)
indicates whether a component (at the same index) is in host byte order.
Communicate a possible byte order conversion in
__netlink_gen_concat_key() back to caller since this has to be respected
when setting 'byteorder' field in struct nft_data_linearize.
String-based values are special: While defined as being in host byte
order in nftables, libnftnl shall print them without prior conversion
like Big Endian values.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
include/netlink.h | 1 +
src/netlink.c | 60 +++++++++++++++++++++++++++++++++++++++--------
2 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/include/netlink.h b/include/netlink.h
index 2737d57..a762cb4 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -106,6 +106,7 @@ struct nft_data_linearize {
char chain[NFT_CHAIN_MAXNAMELEN];
uint32_t chain_id;
int verdict;
+ uint32_t byteorder;
};
struct nft_data_delinearize {
diff --git a/src/netlink.c b/src/netlink.c
index b5da33e..939552a 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -248,6 +248,7 @@ void netlink_gen_raw_data(const mpz_t value, enum byteorder byteorder,
assert(len > 0);
mpz_export_data(data->value, value, byteorder, len);
data->len = len;
+ data->byteorder = byteorder == BYTEORDER_HOST_ENDIAN ? UINT32_MAX : 0;
}
static int netlink_export_pad(unsigned char *data, const mpz_t v,
@@ -265,12 +266,15 @@ static void byteorder_switch_expr_value(mpz_t v, const struct expr *e)
}
static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
- unsigned char *data)
+ unsigned char *data,
+ enum byteorder *byteorder)
{
struct expr *expr;
mpz_t value;
int ret;
+ *byteorder = i->byteorder;
+
switch (i->etype) {
case EXPR_RANGE:
if (flags & EXPR_F_INTERVAL_END)
@@ -281,8 +285,10 @@ static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
mpz_init_set(value, expr->value);
if (expr_basetype(expr)->type == TYPE_INTEGER &&
- expr->byteorder == BYTEORDER_HOST_ENDIAN)
+ expr->byteorder == BYTEORDER_HOST_ENDIAN) {
byteorder_switch_expr_value(value, expr);
+ *byteorder = BYTEORDER_BIG_ENDIAN;
+ }
i = expr;
break;
@@ -293,8 +299,10 @@ static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
mpz_init_set(value, i->range.low);
if (expr_basetype(i)->type == TYPE_INTEGER &&
- i->byteorder == BYTEORDER_HOST_ENDIAN)
+ i->byteorder == BYTEORDER_HOST_ENDIAN) {
byteorder_switch_expr_value(value, i);
+ *byteorder = BYTEORDER_BIG_ENDIAN;
+ }
break;
case EXPR_PREFIX:
@@ -304,8 +312,10 @@ static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
mpz_init_bitmask(v, i->len - i->prefix_len);
- if (i->byteorder == BYTEORDER_HOST_ENDIAN)
+ if (i->byteorder == BYTEORDER_HOST_ENDIAN) {
byteorder_switch_expr_value(v, i);
+ *byteorder = BYTEORDER_BIG_ENDIAN;
+ }
mpz_add(v, i->prefix->value, v);
count = netlink_export_pad(data, v, i);
@@ -323,9 +333,12 @@ static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
break;
expr = (struct expr *)i;
+
if (expr_basetype(expr)->type == TYPE_INTEGER &&
- expr->byteorder == BYTEORDER_HOST_ENDIAN)
+ expr->byteorder == BYTEORDER_HOST_ENDIAN) {
byteorder_switch_expr_value(value, expr);
+ *byteorder = BYTEORDER_BIG_ENDIAN;
+ }
break;
default:
BUG("invalid expression type '%s' in set", expr_ops(i)->name);
@@ -352,16 +365,24 @@ static void netlink_gen_concat_key(const struct expr *expr,
{
unsigned int len = netlink_padded_len(expr->len) / BITS_PER_BYTE;
unsigned char data[NFT_MAX_EXPR_LEN_BYTES];
+ enum byteorder byteorder;
unsigned int offset = 0;
const struct expr *i;
+ int n = 0;
if (len > sizeof(data))
BUG("Value export of %u bytes would overflow", len);
memset(data, 0, sizeof(data));
- list_for_each_entry(i, &expr_concat(expr)->expressions, list)
- offset += __netlink_gen_concat_key(expr->flags, i, data + offset);
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list) {
+ offset += __netlink_gen_concat_key(expr->flags, i,
+ data + offset, &byteorder);
+ if (byteorder == BYTEORDER_HOST_ENDIAN &&
+ expr_basetype(i)->type != TYPE_STRING)
+ nld->byteorder |= 1 << n;
+ n++;
+ }
nft_data_memcpy(nld, data, len);
}
@@ -418,17 +439,28 @@ static void __netlink_gen_concat_expand(const struct expr *expr,
unsigned char data[NFT_MAX_EXPR_LEN_BYTES];
unsigned int offset = 0;
const struct expr *i;
+ int n = 0;
if (len > sizeof(data))
BUG("Value export of %u bytes would overflow", len);
memset(data, 0, sizeof(data));
- list_for_each_entry(i, &expr_concat(expr)->expressions, list)
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list) {
offset += __netlink_gen_concat_data(false, i, data + offset);
+ if (i->byteorder == BYTEORDER_HOST_ENDIAN &&
+ expr_basetype(i)->type != TYPE_STRING)
+ nld->byteorder |= 1 << n;
+ n++;
+ }
- list_for_each_entry(i, &expr_concat(expr)->expressions, list)
+ 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 &&
+ expr_basetype(i)->type != TYPE_STRING)
+ nld->byteorder |= 1 << n;
+ n++;
+ }
nft_data_memcpy(nld, data, len);
}
@@ -440,14 +472,20 @@ static void __netlink_gen_concat(const struct expr *expr,
unsigned char data[NFT_MAX_EXPR_LEN_BYTES];
unsigned int offset = 0;
const struct expr *i;
+ int n = 0;
if (len > sizeof(data))
BUG("Value export of %u bytes would overflow", len);
memset(data, 0, sizeof(data));
- list_for_each_entry(i, &expr_concat(expr)->expressions, list)
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list) {
offset += __netlink_gen_concat_data(expr->flags, i, data + offset);
+ if (i->byteorder == BYTEORDER_HOST_ENDIAN &&
+ expr_basetype(i)->type != TYPE_STRING)
+ nld->byteorder |= 1 << n;
+ n++;
+ }
nft_data_memcpy(nld, data, len);
}
@@ -467,6 +505,8 @@ static void netlink_gen_constant_data(const struct expr *expr,
assert(expr->etype == EXPR_VALUE);
netlink_gen_raw_data(expr->value, expr->byteorder,
div_round_up(expr->len, BITS_PER_BYTE), data);
+ if (expr_basetype(expr)->type == TYPE_STRING)
+ data->byteorder = 0;
}
static void netlink_gen_chain(const struct expr *expr,