* 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
219 lines
7.2 KiB
Diff
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,
|