All of lore.kernel.org
 help / color / mirror / Atom feed
* [nft PATCH 00/15] Fix netlink debug output on Big Endian
@ 2021-11-24 17:22 Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 01/15] tests/py: Avoid duplicate records in *.got files Phil Sutter
                   ` (14 more replies)
  0 siblings, 15 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Make use of recent changes to libnftnl and make tests/py testsuite pass
on Big Endian systems.

Patches 1, 2 and 3 are more or less unrelated fallout from the actual
work but simple enough to not deserve separate submission.

Patches 4-9 fix actual bugs on Big Endian.

Patch 10 is part convenience and part preparation for the following
patches.

Patches 11 and 12 prepare for patch 13 which fixes set element dumping.

Patch 14 adds a shell script which regenerates all payload records,
respecting the separation into family-specific files where used.

Patch 15 contains the big mess of regenerated payload records from using
the previous patch's script. It is at the same time too large to read
and a clear illustration of this and the respective libnftnl's patch
series' effect.

Phil Sutter (15):
  tests/py: Avoid duplicate records in *.got files
  exthdr: Fix for segfault with unknown exthdr
  mnl: Fix for missing info in rule dumps
  src: Fix payload statement mask on Big Endian
  meta: Fix {g,u}id_type on Big Endian
  meta: Fix hour_type size
  datatype: Fix size of time_type
  ct: Fix ct label value parser
  netlink_delinearize: Fix for escaped asterisk strings on Big Endian
  Make string-based data types Big Endian
  evaluate: Fix key byteorder value in range sets/maps
  include: Use struct nftnl_set_desc
  mnl: Provide libnftnl with set element meta info when dumping
  tests/py/tools: Add regen_payloads.sh
  tests/py: Regenerate payload records

 include/rule.h                          |   11 +-
 src/ct.c                                |    7 +-
 src/datatype.c                          |   18 +-
 src/evaluate.c                          |   60 +-
 src/expression.c                        |    2 +-
 src/exthdr.c                            |   12 +-
 src/fib.c                               |    2 +-
 src/json.c                              |    2 +-
 src/meta.c                              |   41 +-
 src/mnl.c                               |   88 +-
 src/netlink.c                           |   10 +-
 src/netlink_delinearize.c               |   67 +-
 src/netlink_linearize.c                 |   13 +-
 src/osf.c                               |    2 +-
 src/parser_bison.y                      |   16 +-
 tests/py/any/counter.t.payload          |    9 +-
 tests/py/any/ct.t.payload               |  242 +--
 tests/py/any/limit.t.payload            |    7 +-
 tests/py/any/log.t.payload              |    1 +
 tests/py/any/meta.t.payload             |  447 ++---
 tests/py/any/queue.t.payload            |   23 +-
 tests/py/any/quota.t.payload            |   26 +-
 tests/py/any/rawpayload.t.payload       |   28 +-
 tests/py/any/rt.t.payload               |   12 +-
 tests/py/any/tcpopt.t.payload           |  128 +-
 tests/py/arp/arp.t.payload              |  134 +-
 tests/py/arp/arp.t.payload.netdev       |  298 ++--
 tests/py/bridge/ether.t.payload         |   42 +-
 tests/py/bridge/icmpX.t.payload         |   24 +-
 tests/py/bridge/meta.t.payload          |   21 +-
 tests/py/bridge/reject.t.payload        |   50 +-
 tests/py/bridge/vlan.t.payload          |  255 +--
 tests/py/bridge/vlan.t.payload.netdev   |  335 ++--
 tests/py/inet/ah.t.payload              |  172 +-
 tests/py/inet/comp.t.payload            |   98 +-
 tests/py/inet/ct.t.payload              |   11 +-
 tests/py/inet/dccp.t.payload            |   98 +-
 tests/py/inet/dnat.t.payload            |   56 +-
 tests/py/inet/esp.t.payload             |   86 +-
 tests/py/inet/ether-ip.t.payload        |   23 +-
 tests/py/inet/ether-ip.t.payload.netdev |   26 +-
 tests/py/inet/ether.t.payload           |   20 +-
 tests/py/inet/ether.t.payload.bridge    |   16 +-
 tests/py/inet/ether.t.payload.ip        |   20 +-
 tests/py/inet/fib.t.payload             |   15 +-
 tests/py/inet/icmp.t.payload            |   48 +-
 tests/py/inet/icmpX.t.payload           |   35 +-
 tests/py/inet/ip.t.payload              |   11 +-
 tests/py/inet/ip.t.payload.bridge       |    9 +-
 tests/py/inet/ip.t.payload.inet         |    8 +-
 tests/py/inet/ip.t.payload.netdev       |   24 +-
 tests/py/inet/ip_tcp.t.payload          |   41 +-
 tests/py/inet/ip_tcp.t.payload.bridge   |   43 +-
 tests/py/inet/ip_tcp.t.payload.netdev   |   43 +-
 tests/py/inet/ipsec.t.payload           |   24 +-
 tests/py/inet/map.t.payload             |   14 +-
 tests/py/inet/map.t.payload.ip          |   14 +-
 tests/py/inet/map.t.payload.netdev      |   14 +-
 tests/py/inet/meta.t.payload            |   67 +-
 tests/py/inet/osf.t.payload             |   49 +-
 tests/py/inet/reject.t.payload.inet     |   38 +-
 tests/py/inet/rt.t.payload              |    6 +-
 tests/py/inet/sctp.t.payload            |  308 ++--
 tests/py/inet/sets.t.payload.bridge     |   32 +-
 tests/py/inet/sets.t.payload.inet       |   25 +-
 tests/py/inet/sets.t.payload.netdev     |   33 +-
 tests/py/inet/snat.t.payload            |   31 +-
 tests/py/inet/socket.t.payload          |   21 +-
 tests/py/inet/synproxy.t.payload        |   12 +-
 tests/py/inet/tcp.t.payload             |  641 +++----
 tests/py/inet/tproxy.t.payload          |   58 +-
 tests/py/inet/udp.t.payload             |  217 +--
 tests/py/inet/udplite.t.payload         |  142 +-
 tests/py/ip/ct.t.payload                |   45 +-
 tests/py/ip/dnat.t.payload.ip           |  136 +-
 tests/py/ip/dup.t.payload               |   18 +-
 tests/py/ip/ether.t.payload             |   36 +-
 tests/py/ip/flowtable.t.payload         |    4 +-
 tests/py/ip/hash.t.payload              |    9 +-
 tests/py/ip/icmp.t.payload.ip           |  399 ++---
 tests/py/ip/igmp.t.payload              |   92 +-
 tests/py/ip/ip.t.payload                |  271 +--
 tests/py/ip/ip.t.payload.bridge         |  550 +++---
 tests/py/ip/ip.t.payload.inet           |  434 ++---
 tests/py/ip/ip.t.payload.netdev         |  564 +++---
 tests/py/ip/ip_tcp.t.payload            |   10 +-
 tests/py/ip/masquerade.t.payload        |   80 +-
 tests/py/ip/meta.t.payload              |   33 +-
 tests/py/ip/numgen.t.payload            |   12 +-
 tests/py/ip/objects.t.payload           |   41 +-
 tests/py/ip/redirect.t.payload          |  132 +-
 tests/py/ip/reject.t.payload            |    2 +-
 tests/py/ip/rt.t.payload                |    2 +-
 tests/py/ip/sets.t.payload.inet         |   49 +-
 tests/py/ip/sets.t.payload.ip           |   23 +-
 tests/py/ip/sets.t.payload.netdev       |   53 +-
 tests/py/ip/snat.t.payload              |  111 +-
 tests/py/ip/tcp.t.payload               |   10 +-
 tests/py/ip/tproxy.t.payload            |   40 +-
 tests/py/ip6/dnat.t.payload.ip6         |   45 +-
 tests/py/ip6/dst.t.payload.inet         |   97 +-
 tests/py/ip6/dst.t.payload.ip6          |   51 +-
 tests/py/ip6/dup.t.payload              |   18 +-
 tests/py/ip6/ether.t.payload            |   37 +-
 tests/py/ip6/exthdr.t.payload.ip6       |   24 +-
 tests/py/ip6/flowtable.t.payload        |    4 +-
 tests/py/ip6/frag.t.payload.inet        |  152 +-
 tests/py/ip6/frag.t.payload.ip6         |   96 +-
 tests/py/ip6/frag.t.payload.netdev      | 2080 +++++++++--------------
 tests/py/ip6/hbh.t.payload.inet         |   80 +-
 tests/py/ip6/hbh.t.payload.ip6          |   48 +-
 tests/py/ip6/icmpv6.t.payload.ip6       |  350 ++--
 tests/py/ip6/ip6.t.payload.inet         |  408 ++---
 tests/py/ip6/ip6.t.payload.ip6          |  234 +--
 tests/py/ip6/map.t.payload              |    6 +-
 tests/py/ip6/masquerade.t.payload.ip6   |   80 +-
 tests/py/ip6/meta.t.payload             |   39 +-
 tests/py/ip6/mh.t.payload.inet          |  163 +-
 tests/py/ip6/mh.t.payload.ip6           |   97 +-
 tests/py/ip6/redirect.t.payload.ip6     |  116 +-
 tests/py/ip6/reject.t.payload.ip6       |    2 +-
 tests/py/ip6/rt.t.payload.inet          |  148 +-
 tests/py/ip6/rt.t.payload.ip6           |   88 +-
 tests/py/ip6/rt0.t.payload              |    2 +-
 tests/py/ip6/sets.t.payload.inet        |   15 +-
 tests/py/ip6/sets.t.payload.netdev      |   14 +-
 tests/py/ip6/snat.t.payload.ip6         |   26 +-
 tests/py/ip6/srh.t.payload              |   22 +-
 tests/py/ip6/tproxy.t.payload           |   40 +-
 tests/py/ip6/vmap.t.payload.inet        |  252 +--
 tests/py/ip6/vmap.t.payload.ip6         |  168 +-
 tests/py/ip6/vmap.t.payload.netdev      |  336 ++--
 tests/py/netdev/dup.t.payload           |   10 +-
 tests/py/netdev/fwd.t.payload           |   16 +-
 tests/py/netdev/reject.t.payload        |   92 +-
 tests/py/nft-test.py                    |   29 +-
 tests/py/tools/regen_payloads.sh        |   72 +
 137 files changed, 6695 insertions(+), 7100 deletions(-)
 create mode 100755 tests/py/tools/regen_payloads.sh

-- 
2.33.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [nft PATCH 01/15] tests/py: Avoid duplicate records in *.got files
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 02/15] exthdr: Fix for segfault with unknown exthdr Phil Sutter
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

If payloads don't contain family-specific bits, they may sit in a single
*.payload file for all tested families. In such case, nft-test.py will
consequently write dissenting payloads into a single *.got file. To
avoid the duplicate entries, check if a matching record exists already
before writing it out.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 tests/py/nft-test.py | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/tests/py/nft-test.py b/tests/py/nft-test.py
index f8f9341c11515..04dac8d77b25f 100755
--- a/tests/py/nft-test.py
+++ b/tests/py/nft-test.py
@@ -809,17 +809,26 @@ def rule_add(rule, filename, lineno, force_all_family_option, filename_path):
             if state == "ok" and not payload_check(table_payload_expected,
                                                    payload_log, cmd):
                 error += 1
-                gotf = open("%s.got" % payload_path, 'a')
+
+                try:
+                    gotf = open("%s.got" % payload_path)
+                    gotf_payload_expected = payload_find_expected(gotf, rule[0])
+                    gotf.close()
+                except:
+                    gotf_payload_expected = None
                 payload_log.seek(0, 0)
-                gotf.write("# %s\n" % rule[0])
-                while True:
-                    line = payload_log.readline()
-                    if line == "":
-                        break
-                    gotf.write(line)
-                gotf.close()
-                print_warning("Wrote payload for rule %s" % rule[0],
-                              gotf.name, 1)
+                if not payload_check(gotf_payload_expected, payload_log, cmd):
+                    gotf = open("%s.got" % payload_path, 'a')
+                    payload_log.seek(0, 0)
+                    gotf.write("# %s\n" % rule[0])
+                    while True:
+                        line = payload_log.readline()
+                        if line == "":
+                            break
+                        gotf.write(line)
+                    gotf.close()
+                    print_warning("Wrote payload for rule %s" % rule[0],
+                                  gotf.name, 1)
 
             # Check for matching ruleset listing
             numeric_proto_old = nftables.set_numeric_proto_output(True)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 02/15] exthdr: Fix for segfault with unknown exthdr
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 01/15] tests/py: Avoid duplicate records in *.got files Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 03/15] mnl: Fix for missing info in rule dumps Phil Sutter
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Unknown exthdr type with NFT_EXTHDR_F_PRESENT flag set caused
NULL-pointer deref. Fix this by moving the conditional exthdr.desc deref
atop the function and use the result in all cases.

Fixes: e02bd59c4009b ("exthdr: Implement existence check")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/exthdr.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/exthdr.c b/src/exthdr.c
index 22a08b0c9c2bf..7a29e63d4d536 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -46,6 +46,9 @@ static const struct exthdr_desc *exthdr_find_desc(enum exthdr_desc_id desc_id)
 
 static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
 {
+	const char *name = expr->exthdr.desc ?
+		expr->exthdr.desc->name : "unknown-exthdr";
+
 	if (expr->exthdr.op == NFT_EXTHDR_OP_TCPOPT) {
 		/* Offset calculation is a bit hacky at this point.
 		 * There might be a tcp option one day with another
@@ -65,14 +68,14 @@ static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
 			return;
 		}
 
-		nft_print(octx, "tcp option %s", expr->exthdr.desc->name);
+		nft_print(octx, "tcp option %s", name);
 		if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
 			return;
 		if (offset)
 			nft_print(octx, "%d", offset);
 		nft_print(octx, " %s", expr->exthdr.tmpl->token);
 	} else if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
-		nft_print(octx, "ip option %s", expr->exthdr.desc->name);
+		nft_print(octx, "ip option %s", name);
 		if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
 			return;
 		nft_print(octx, " %s", expr->exthdr.tmpl->token);
@@ -83,10 +86,9 @@ static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
 		nft_print(octx, " %s", expr->exthdr.tmpl->token);
 	} else {
 		if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
-			nft_print(octx, "exthdr %s", expr->exthdr.desc->name);
+			nft_print(octx, "exthdr %s", name);
 		else {
-			nft_print(octx, "%s %s",
-				  expr->exthdr.desc ? expr->exthdr.desc->name : "unknown-exthdr",
+			nft_print(octx, "%s %s", name,
 				  expr->exthdr.tmpl->token);
 		}
 	}
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 03/15] mnl: Fix for missing info in rule dumps
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 01/15] tests/py: Avoid duplicate records in *.got files Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 02/15] exthdr: Fix for segfault with unknown exthdr Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 04/15] src: Fix payload statement mask on Big Endian Phil Sutter
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Commit 0e52cab1e64ab improved error reporting by adding rule's table and
chain names to netlink message directly, prefixed by their location
info. This in turn caused netlink dumps of the rule to not contain table
and chain name anymore. Fix this by inserting the missing info before
dumping and remove it afterwards to not cause duplicated entries in
netlink message.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/netlink_linearize.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 111102fd43346..34a6e1a941b56 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -1673,5 +1673,16 @@ void netlink_linearize_rule(struct netlink_ctx *ctx,
 		nftnl_udata_buf_free(udata);
 	}
 
-	netlink_dump_rule(lctx->nlr, ctx);
+	if (ctx->nft->debug_mask & NFT_DEBUG_NETLINK) {
+		nftnl_rule_set_str(lctx->nlr, NFTNL_RULE_TABLE,
+				   rule->handle.table.name);
+		if (rule->handle.chain.name)
+			nftnl_rule_set_str(lctx->nlr, NFTNL_RULE_CHAIN,
+					   rule->handle.chain.name);
+
+		netlink_dump_rule(lctx->nlr, ctx);
+
+		nftnl_rule_unset(lctx->nlr, NFTNL_RULE_CHAIN);
+		nftnl_rule_unset(lctx->nlr, NFTNL_RULE_TABLE);
+	}
 }
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 04/15] src: Fix payload statement mask on Big Endian
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (2 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 03/15] mnl: Fix for missing info in rule dumps Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 05/15] meta: Fix {g,u}id_type " Phil Sutter
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

The mask used to select bits to keep must be exported in the same
byteorder as the payload statement itself, also the length of the
exported data must match the number of bytes extracted earlier.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/evaluate.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index eebd992159a11..49fb8f84fe76b 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2556,9 +2556,9 @@ static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
 	mpz_clear(ff);
 
 	assert(sizeof(data) * BITS_PER_BYTE >= masklen);
-	mpz_export_data(data, bitmask, BYTEORDER_HOST_ENDIAN, sizeof(data));
+	mpz_export_data(data, bitmask, payload->byteorder, payload_byte_size);
 	mask = constant_expr_alloc(&payload->location, expr_basetype(payload),
-				   BYTEORDER_HOST_ENDIAN, masklen, data);
+				   payload->byteorder, masklen, data);
 	mpz_clear(bitmask);
 
 	payload_bytes = payload_expr_alloc(&payload->location, NULL, 0);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 05/15] meta: Fix {g,u}id_type on Big Endian
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (3 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 04/15] src: Fix payload statement mask on Big Endian Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 06/15] meta: Fix hour_type size Phil Sutter
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Using a 64bit variable to temporarily hold the parsed value works only
on Little Endian. uid_t and gid_t (and therefore also pw->pw_uid and
gr->gr_gid) are 32bit.
To fix this, use uid_t/gid_t for the temporary variable but keep the
64bit one for numeric parsing so values exceeding 32bits are still
detected.

Fixes: e0ed4c45d9ad2 ("meta: relax restriction on UID/GID parsing")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/meta.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/src/meta.c b/src/meta.c
index bdd10269569d2..1794495ebba1c 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -220,18 +220,20 @@ static struct error_record *uid_type_parse(struct parse_ctx *ctx,
 					   struct expr **res)
 {
 	struct passwd *pw;
-	uint64_t uid;
+	uid_t uid;
 	char *endptr = NULL;
 
 	pw = getpwnam(sym->identifier);
 	if (pw != NULL)
 		uid = pw->pw_uid;
 	else {
-		uid = strtoull(sym->identifier, &endptr, 10);
-		if (uid > UINT32_MAX)
+		uint64_t _uid = strtoull(sym->identifier, &endptr, 10);
+
+		if (_uid > UINT32_MAX)
 			return error(&sym->location, "Value too large");
 		else if (*endptr)
 			return error(&sym->location, "User does not exist");
+		uid = _uid;
 	}
 
 	*res = constant_expr_alloc(&sym->location, sym->dtype,
@@ -274,18 +276,20 @@ static struct error_record *gid_type_parse(struct parse_ctx *ctx,
 					   struct expr **res)
 {
 	struct group *gr;
-	uint64_t gid;
+	gid_t gid;
 	char *endptr = NULL;
 
 	gr = getgrnam(sym->identifier);
 	if (gr != NULL)
 		gid = gr->gr_gid;
 	else {
-		gid = strtoull(sym->identifier, &endptr, 0);
-		if (gid > UINT32_MAX)
+		uint64_t _gid = strtoull(sym->identifier, &endptr, 0);
+
+		if (_gid > UINT32_MAX)
 			return error(&sym->location, "Value too large");
 		else if (*endptr)
 			return error(&sym->location, "Group does not exist");
+		gid = _gid;
 	}
 
 	*res = constant_expr_alloc(&sym->location, sym->dtype,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 06/15] meta: Fix hour_type size
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (4 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 05/15] meta: Fix {g,u}id_type " Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 07/15] datatype: Fix size of time_type Phil Sutter
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

In kernel as well as when parsing, hour_type is assumed to be 32bits.
Having the struct datatype field set to 64bits breaks Big Endian and so
does passing a 64bit value and 32 as length to constant_expr_alloc() as
it makes it import the upper 32bits. Fix this by turning 'result' into a
uint32_t and introduce a temporary uint64_t just for the call to
time_parse() which expects that.

Fixes: f8f32deda31df ("meta: Introduce new conditions 'time', 'day' and 'hour'")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/meta.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/meta.c b/src/meta.c
index 1794495ebba1c..23b1fd2759483 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -516,7 +516,8 @@ static struct error_record *hour_type_parse(struct parse_ctx *ctx,
 {
 	struct error_record *er;
 	struct tm tm, *cur_tm;
-	uint64_t result = 0;
+	uint32_t result;
+	uint64_t tmp;
 	char *endptr;
 	time_t ts;
 
@@ -544,8 +545,8 @@ static struct error_record *hour_type_parse(struct parse_ctx *ctx,
 	if (endptr && *endptr)
 		return error(&sym->location, "Can't parse trailing input: \"%s\"\n", endptr);
 
-	if ((er = time_parse(&sym->location, sym->identifier, &result)) == NULL) {
-		result /= 1000;
+	if ((er = time_parse(&sym->location, sym->identifier, &tmp)) == NULL) {
+		result = tmp / 1000;
 		goto convert;
 	}
 
@@ -599,7 +600,7 @@ const struct datatype hour_type = {
 	.name = "hour",
 	.desc = "Hour of day of packet reception",
 	.byteorder = BYTEORDER_HOST_ENDIAN,
-	.size = sizeof(uint64_t) * BITS_PER_BYTE,
+	.size = sizeof(uint32_t) * BITS_PER_BYTE,
 	.basetype = &integer_type,
 	.print = hour_type_print,
 	.parse = hour_type_parse,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 07/15] datatype: Fix size of time_type
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (5 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 06/15] meta: Fix hour_type size Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 08/15] ct: Fix ct label value parser Phil Sutter
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Used by 'ct expiration', time_type is supposed to be 32bits. Passing a
64bits variable to constant_expr_alloc() causes the value to be always
zero on Big Endian.

Fixes: 0974fa84f162a ("datatype: seperate time parsing/printing from time_type")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/datatype.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/datatype.c b/src/datatype.c
index a06c39960fa0c..b2e667cef2c62 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -1068,6 +1068,7 @@ static struct error_record *time_type_parse(struct parse_ctx *ctx,
 					    struct expr **res)
 {
 	struct error_record *erec;
+	uint32_t s32;
 	uint64_t s;
 
 	erec = time_parse(&sym->location, sym->identifier, &s);
@@ -1077,9 +1078,10 @@ static struct error_record *time_type_parse(struct parse_ctx *ctx,
 	if (s > UINT32_MAX)
 		return error(&sym->location, "value too large");
 
+	s32 = s;
 	*res = constant_expr_alloc(&sym->location, &time_type,
 				   BYTEORDER_HOST_ENDIAN,
-				   sizeof(uint32_t) * BITS_PER_BYTE, &s);
+				   sizeof(uint32_t) * BITS_PER_BYTE, &s32);
 	return NULL;
 }
 
@@ -1088,7 +1090,7 @@ const struct datatype time_type = {
 	.name		= "time",
 	.desc		= "relative time",
 	.byteorder	= BYTEORDER_HOST_ENDIAN,
-	.size		= 8 * BITS_PER_BYTE,
+	.size		= 4 * BITS_PER_BYTE,
 	.basetype	= &integer_type,
 	.print		= time_type_print,
 	.json		= time_type_json,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 08/15] ct: Fix ct label value parser
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (6 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 07/15] datatype: Fix size of time_type Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 09/15] netlink_delinearize: Fix for escaped asterisk strings on Big Endian Phil Sutter
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Size of array to export the bit value into was eight times too large, so
on Big Endian the data written into the data reg was always zero.

Fixes: 2fcce8b0677b3 ("ct: connlabel matching support")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/ct.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/ct.c b/src/ct.c
index 2218ecc7a684d..6049157198ad9 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -176,7 +176,7 @@ static struct error_record *ct_label_type_parse(struct parse_ctx *ctx,
 {
 	const struct symbolic_constant *s;
 	const struct datatype *dtype;
-	uint8_t data[CT_LABEL_BIT_SIZE];
+	uint8_t data[CT_LABEL_BIT_SIZE / BITS_PER_BYTE];
 	uint64_t bit;
 	mpz_t value;
 
@@ -211,8 +211,7 @@ static struct error_record *ct_label_type_parse(struct parse_ctx *ctx,
 	mpz_export_data(data, value, BYTEORDER_HOST_ENDIAN, sizeof(data));
 
 	*res = constant_expr_alloc(&sym->location, dtype,
-				   dtype->byteorder, sizeof(data),
-				   data);
+				   dtype->byteorder, CT_LABEL_BIT_SIZE, data);
 	mpz_clear(value);
 	return NULL;
 }
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 09/15] netlink_delinearize: Fix for escaped asterisk strings on Big Endian
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (7 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 08/15] ct: Fix ct label value parser Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 10/15] Make string-based data types " Phil Sutter
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

The original nul-char detection was not functional on Big Endian.
Instead, go a simpler route by exporting the string and working on the
exported data to check for a nul-char and escape a trailing asterisk if
present. With the data export already happening in the caller, fold
escaped_string_wildcard_expr_alloc() into it as well.

Fixes: b851ba4731d9f ("src: add interface wildcard matching")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/netlink_delinearize.c | 57 ++++++++++++---------------------------
 1 file changed, 17 insertions(+), 40 deletions(-)

diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 0c2b439eac6fb..db58e8c386c00 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -2422,56 +2422,33 @@ static struct expr *string_wildcard_expr_alloc(struct location *loc,
 				   expr->len + BITS_PER_BYTE, data);
 }
 
-static void escaped_string_wildcard_expr_alloc(struct expr **exprp,
-					       unsigned int len)
-{
-	struct expr *expr = *exprp, *tmp;
-	char data[len + 3];
-	int pos;
-
-	mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
-	pos = div_round_up(len, BITS_PER_BYTE);
-	data[pos - 1] = '\\';
-	data[pos] = '*';
-
-	tmp = constant_expr_alloc(&expr->location, expr->dtype,
-				  BYTEORDER_HOST_ENDIAN,
-				  expr->len + BITS_PER_BYTE, data);
-	expr_free(expr);
-	*exprp = tmp;
-}
-
 /* This calculates the string length and checks if it is nul-terminated, this
  * function is quite a hack :)
  */
 static bool __expr_postprocess_string(struct expr **exprp)
 {
 	struct expr *expr = *exprp;
-	unsigned int len = expr->len;
-	bool nulterminated = false;
-	mpz_t tmp;
-
-	mpz_init(tmp);
-	while (len >= BITS_PER_BYTE) {
-		mpz_bitmask(tmp, BITS_PER_BYTE);
-		mpz_lshift_ui(tmp, len - BITS_PER_BYTE);
-		mpz_and(tmp, tmp, expr->value);
-		if (mpz_cmp_ui(tmp, 0))
-			break;
-		else
-			nulterminated = true;
-		len -= BITS_PER_BYTE;
-	}
+	unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
+	char data[len + 1];
 
-	mpz_rshift_ui(tmp, len - BITS_PER_BYTE);
+	mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
 
-	if (nulterminated &&
-	    mpz_cmp_ui(tmp, '*') == 0)
-		escaped_string_wildcard_expr_alloc(exprp, len);
+	if (data[len - 1] != '\0')
+		return false;
 
-	mpz_clear(tmp);
+	len = strlen(data);
+	if (len && data[len - 1] == '*') {
+		data[len - 1]	= '\\';
+		data[len]	= '*';
+		data[len + 1]	= '\0';
+		expr = constant_expr_alloc(&expr->location, expr->dtype,
+					   BYTEORDER_HOST_ENDIAN,
+					   (len + 2) * BITS_PER_BYTE, data);
+		expr_free(*exprp);
+		*exprp = expr;
+	}
 
-	return nulterminated;
+	return true;
 }
 
 static struct expr *expr_postprocess_string(struct expr *expr)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 10/15] Make string-based data types Big Endian
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (8 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 09/15] netlink_delinearize: Fix for escaped asterisk strings on Big Endian Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 11/15] evaluate: Fix key byteorder value in range sets/maps Phil Sutter
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Byte-ordering in strings is fixed despite machine's Endianness, so
declaring them Big Endian is more appropriate than Host Endian.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/ct.c                  |  2 +-
 src/datatype.c            | 12 ++++++------
 src/evaluate.c            | 14 +++++++-------
 src/expression.c          |  2 +-
 src/fib.c                 |  2 +-
 src/json.c                |  2 +-
 src/meta.c                | 16 ++++++++--------
 src/mnl.c                 |  4 ++--
 src/netlink.c             | 10 +++++-----
 src/netlink_delinearize.c | 14 +++++++-------
 src/osf.c                 |  2 +-
 src/parser_bison.y        | 16 ++++++++--------
 12 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/src/ct.c b/src/ct.c
index 6049157198ad9..11ee270b21862 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -259,7 +259,7 @@ const struct ct_template ct_templates[__NFT_CT_MAX] = {
 					      BYTEORDER_HOST_ENDIAN,
 					      4 * BITS_PER_BYTE),
 	[NFT_CT_HELPER]		= CT_TEMPLATE("helper",	    &string_type,
-					      BYTEORDER_HOST_ENDIAN,
+					      BYTEORDER_BIG_ENDIAN,
 					      NF_CT_HELPER_NAME_LEN * BITS_PER_BYTE),
 	[NFT_CT_L3PROTOCOL]	= CT_TEMPLATE("l3proto",    &nfproto_type,
 					      BYTEORDER_HOST_ENDIAN,
diff --git a/src/datatype.c b/src/datatype.c
index b2e667cef2c62..e72e5a5a797cd 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -259,7 +259,7 @@ void expr_chain_export(const struct expr *e, char *chain_name)
 		BUG("verdict expression length %u is too large (%u bits max)",
 		    e->len, NFT_CHAIN_MAXNAMELEN * BITS_PER_BYTE);
 
-	mpz_export_data(chain_name, e->value, BYTEORDER_HOST_ENDIAN, len);
+	mpz_export_data(chain_name, e->value, BYTEORDER_BIG_ENDIAN, len);
 }
 
 static void verdict_jump_chain_print(const char *what, const struct expr *e,
@@ -326,7 +326,7 @@ static struct error_record *verdict_type_parse(struct parse_ctx *ctx,
 					       struct expr **res)
 {
 	*res = constant_expr_alloc(&sym->location, &string_type,
-				   BYTEORDER_HOST_ENDIAN,
+				   BYTEORDER_BIG_ENDIAN,
 				   (strlen(sym->identifier) + 1) * BITS_PER_BYTE,
 				   sym->identifier);
 	return NULL;
@@ -431,7 +431,7 @@ static void string_type_print(const struct expr *expr, struct output_ctx *octx)
 	unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
 	char data[len+1];
 
-	mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
+	mpz_export_data(data, expr->value, BYTEORDER_BIG_ENDIAN, len);
 	data[len] = '\0';
 	nft_print(octx, "\"%s\"", data);
 }
@@ -441,7 +441,7 @@ static struct error_record *string_type_parse(struct parse_ctx *ctx,
 	      				      struct expr **res)
 {
 	*res = constant_expr_alloc(&sym->location, &string_type,
-				   BYTEORDER_HOST_ENDIAN,
+				   BYTEORDER_BIG_ENDIAN,
 				   (strlen(sym->identifier) + 1) * BITS_PER_BYTE,
 				   sym->identifier);
 	return NULL;
@@ -451,7 +451,7 @@ const struct datatype string_type = {
 	.type		= TYPE_STRING,
 	.name		= "string",
 	.desc		= "string",
-	.byteorder	= BYTEORDER_HOST_ENDIAN,
+	.byteorder	= BYTEORDER_BIG_ENDIAN,
 	.print		= string_type_print,
 	.json		= string_type_json,
 	.parse		= string_type_parse,
@@ -1309,7 +1309,7 @@ static struct error_record *priority_type_parse(struct parse_ctx *ctx,
 	} else {
 		erec_destroy(erec);
 		*res = constant_expr_alloc(&sym->location, &string_type,
-					   BYTEORDER_HOST_ENDIAN,
+					   BYTEORDER_BIG_ENDIAN,
 					   strlen(sym->identifier) * BITS_PER_BYTE,
 					   sym->identifier);
 	}
diff --git a/src/evaluate.c b/src/evaluate.c
index 49fb8f84fe76b..fbf3aa8d19139 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -293,7 +293,7 @@ static int expr_evaluate_string(struct eval_ctx *ctx, struct expr **exprp)
 	}
 
 	memset(data + len, 0, data_len - len);
-	mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
+	mpz_export_data(data, expr->value, BYTEORDER_BIG_ENDIAN, len);
 
 	if (strlen(data) == 0)
 		return expr_error(ctx->msgs, expr,
@@ -305,7 +305,7 @@ static int expr_evaluate_string(struct eval_ctx *ctx, struct expr **exprp)
 		 * expression length to avoid problems on big endian.
 		 */
 		value = constant_expr_alloc(&expr->location, ctx->ectx.dtype,
-					    BYTEORDER_HOST_ENDIAN,
+					    BYTEORDER_BIG_ENDIAN,
 					    expr->len, data);
 		expr_free(expr);
 		*exprp = value;
@@ -323,21 +323,21 @@ static int expr_evaluate_string(struct eval_ctx *ctx, struct expr **exprp)
 		xstrunescape(data, unescaped_str);
 
 		value = constant_expr_alloc(&expr->location, ctx->ectx.dtype,
-					    BYTEORDER_HOST_ENDIAN,
+					    BYTEORDER_BIG_ENDIAN,
 					    expr->len, unescaped_str);
 		expr_free(expr);
 		*exprp = value;
 		return 0;
 	}
 	value = constant_expr_alloc(&expr->location, ctx->ectx.dtype,
-				    BYTEORDER_HOST_ENDIAN,
+				    BYTEORDER_BIG_ENDIAN,
 				    datalen * BITS_PER_BYTE, data);
 
 	prefix = prefix_expr_alloc(&expr->location, value,
 				   datalen * BITS_PER_BYTE);
 	datatype_set(prefix, ctx->ectx.dtype);
 	prefix->flags |= EXPR_F_CONSTANT;
-	prefix->byteorder = BYTEORDER_HOST_ENDIAN;
+	prefix->byteorder = BYTEORDER_BIG_ENDIAN;
 
 	expr_free(expr);
 	*exprp = prefix;
@@ -3582,7 +3582,7 @@ static int stmt_evaluate_log_prefix(struct eval_ctx *ctx, struct stmt *stmt)
 		return stmt_error(ctx, stmt, "log prefix is too long");
 
 	expr = constant_expr_alloc(&stmt->log.prefix->location, &string_type,
-				   BYTEORDER_HOST_ENDIAN,
+				   BYTEORDER_BIG_ENDIAN,
 				   strlen(prefix) * BITS_PER_BYTE, prefix);
 	expr_free(stmt->log.prefix);
 	stmt->log.prefix = expr;
@@ -4045,7 +4045,7 @@ static bool evaluate_priority(struct eval_ctx *ctx, struct prio_spec *prio,
 	if (prio->expr->dtype->type == TYPE_INTEGER)
 		return true;
 
-	mpz_export_data(prio_str, prio->expr->value, BYTEORDER_HOST_ENDIAN,
+	mpz_export_data(prio_str, prio->expr->value, BYTEORDER_BIG_ENDIAN,
 			NFT_NAME_MAXLEN);
 	loc = prio->expr->location;
 
diff --git a/src/expression.c b/src/expression.c
index 4c0874fe99500..24f908cd8136d 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -186,7 +186,7 @@ void expr_to_string(const struct expr *expr, char *string)
 
 	assert(expr->dtype == &string_type);
 
-	mpz_export_data(string, expr->value, BYTEORDER_HOST_ENDIAN, len);
+	mpz_export_data(string, expr->value, BYTEORDER_BIG_ENDIAN, len);
 }
 
 void expr_set_type(struct expr *expr, const struct datatype *dtype,
diff --git a/src/fib.c b/src/fib.c
index c6ad0f9c5d15d..e06e8c69ce050 100644
--- a/src/fib.c
+++ b/src/fib.c
@@ -192,7 +192,7 @@ struct expr *fib_expr_alloc(const struct location *loc,
 		type = &boolean_type;
 
 	expr = expr_alloc(loc, EXPR_FIB, type,
-			  BYTEORDER_HOST_ENDIAN, len);
+			  type->byteorder, len);
 
 	expr->fib.result = result;
 	expr->fib.flags	= flags;
diff --git a/src/json.c b/src/json.c
index 63b325afc8d1c..f03b635ea9235 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1020,7 +1020,7 @@ json_t *string_type_json(const struct expr *expr, struct output_ctx *octx)
 	unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
 	char data[len+1];
 
-	mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
+	mpz_export_data(data, expr->value, BYTEORDER_BIG_ENDIAN, len);
 	data[len] = '\0';
 
 	return json_string(data);
diff --git a/src/meta.c b/src/meta.c
index 23b1fd2759483..97e79b9e6d9ab 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -378,7 +378,7 @@ const struct datatype ifname_type = {
 	.type		= TYPE_IFNAME,
 	.name		= "ifname",
 	.desc		= "network interface name",
-	.byteorder	= BYTEORDER_HOST_ENDIAN,
+	.byteorder	= BYTEORDER_BIG_ENDIAN,
 	.size		= IFNAMSIZ * BITS_PER_BYTE,
 	.basetype	= &string_type,
 };
@@ -623,14 +623,14 @@ const struct meta_template meta_templates[] = {
 						4 * 8, BYTEORDER_HOST_ENDIAN),
 	[NFT_META_IIFNAME]	= META_TEMPLATE("iifname",   &ifname_type,
 						IFNAMSIZ * BITS_PER_BYTE,
-						BYTEORDER_HOST_ENDIAN),
+						BYTEORDER_BIG_ENDIAN),
 	[NFT_META_IIFTYPE]	= META_TEMPLATE("iiftype",   &arphrd_type,
 						2 * 8, BYTEORDER_HOST_ENDIAN),
 	[NFT_META_OIF]		= META_TEMPLATE("oif",	     &ifindex_type,
 						4 * 8, BYTEORDER_HOST_ENDIAN),
 	[NFT_META_OIFNAME]	= META_TEMPLATE("oifname",   &ifname_type,
 						IFNAMSIZ * BITS_PER_BYTE,
-						BYTEORDER_HOST_ENDIAN),
+						BYTEORDER_BIG_ENDIAN),
 	[NFT_META_OIFTYPE]	= META_TEMPLATE("oiftype",   &arphrd_type,
 						2 * 8, BYTEORDER_HOST_ENDIAN),
 	[NFT_META_SKUID]	= META_TEMPLATE("skuid",     &uid_type,
@@ -643,10 +643,10 @@ const struct meta_template meta_templates[] = {
 						4 * 8, BYTEORDER_HOST_ENDIAN),
 	[NFT_META_BRI_IIFNAME]	= META_TEMPLATE("ibrname",  &ifname_type,
 						IFNAMSIZ * BITS_PER_BYTE,
-						BYTEORDER_HOST_ENDIAN),
+						BYTEORDER_BIG_ENDIAN),
 	[NFT_META_BRI_OIFNAME]	= META_TEMPLATE("obrname",  &ifname_type,
 						IFNAMSIZ * BITS_PER_BYTE,
-						BYTEORDER_HOST_ENDIAN),
+						BYTEORDER_BIG_ENDIAN),
 	[NFT_META_PKTTYPE]	= META_TEMPLATE("pkttype",   &pkttype_type,
 						BITS_PER_BYTE,
 						BYTEORDER_HOST_ENDIAN),
@@ -669,10 +669,10 @@ const struct meta_template meta_templates[] = {
 						BITS_PER_BYTE, BYTEORDER_HOST_ENDIAN),
 	[NFT_META_IIFKIND]	= META_TEMPLATE("iifkind",   &ifname_type,
 						IFNAMSIZ * BITS_PER_BYTE,
-						BYTEORDER_HOST_ENDIAN),
+						BYTEORDER_BIG_ENDIAN),
 	[NFT_META_OIFKIND]	= META_TEMPLATE("oifkind",   &ifname_type,
 						IFNAMSIZ * BITS_PER_BYTE,
-						BYTEORDER_HOST_ENDIAN),
+						BYTEORDER_BIG_ENDIAN),
 	[NFT_META_BRI_IIFPVID]	= META_TEMPLATE("ibrpvid",   &integer_type,
 						2 * BITS_PER_BYTE,
 						BYTEORDER_HOST_ENDIAN),
@@ -695,7 +695,7 @@ const struct meta_template meta_templates[] = {
 						BYTEORDER_HOST_ENDIAN),
 	[NFT_META_SDIFNAME]	= META_TEMPLATE("sdifname", &ifname_type,
 						IFNAMSIZ * BITS_PER_BYTE,
-						BYTEORDER_HOST_ENDIAN),
+						BYTEORDER_BIG_ENDIAN),
 };
 
 static bool meta_key_is_unqualified(enum nft_meta_keys key)
diff --git a/src/mnl.c b/src/mnl.c
index 4a10647f9f179..a3ee32680a77a 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -722,7 +722,7 @@ int mnl_nft_chain_add(struct netlink_ctx *ctx, struct cmd *cmd,
 				ifname_len = div_round_up(expr->len, BITS_PER_BYTE);
 				memset(ifname, 0, sizeof(ifname));
 				mpz_export_data(ifname, expr->value,
-						BYTEORDER_HOST_ENDIAN,
+						BYTEORDER_BIG_ENDIAN,
 						ifname_len);
 				dev_array[i++] = xstrdup(ifname);
 				if (i == dev_array_len) {
@@ -1820,7 +1820,7 @@ static const char **nft_flowtable_dev_array(struct cmd *cmd)
 	list_for_each_entry(expr, &cmd->flowtable->dev_expr->expressions, list) {
 		ifname_len = div_round_up(expr->len, BITS_PER_BYTE);
 		memset(ifname, 0, sizeof(ifname));
-		mpz_export_data(ifname, expr->value, BYTEORDER_HOST_ENDIAN,
+		mpz_export_data(ifname, expr->value, BYTEORDER_BIG_ENDIAN,
 				ifname_len);
 		dev_array[i++] = xstrdup(ifname);
 	}
diff --git a/src/netlink.c b/src/netlink.c
index ab90d0c05acaf..d1531070dcc93 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -345,7 +345,7 @@ static void netlink_gen_chain(const struct expr *expr,
 	memset(chain, 0, sizeof(chain));
 
 	mpz_export_data(chain, expr->chain->value,
-			BYTEORDER_HOST_ENDIAN, len);
+			BYTEORDER_BIG_ENDIAN, len);
 	snprintf(data->chain, NFT_CHAIN_MAXNAMELEN, "%s", chain);
 }
 
@@ -438,7 +438,7 @@ static struct expr *netlink_alloc_verdict(const struct location *loc,
 	case NFT_JUMP:
 	case NFT_GOTO:
 		chain = constant_expr_alloc(loc, &string_type,
-					    BYTEORDER_HOST_ENDIAN,
+					    BYTEORDER_BIG_ENDIAN,
 					    strlen(nld->chain) * BITS_PER_BYTE,
 					    nld->chain);
 		break;
@@ -895,6 +895,7 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
 		objtype = nftnl_set_get_u32(nls, NFTNL_SET_OBJ_TYPE);
 		assert(!datatype);
 		datatype = &string_type;
+		databyteorder = BYTEORDER_BIG_ENDIAN;
 	}
 
 	set = set_alloc(&netlink_location);
@@ -1328,8 +1329,7 @@ key_end:
 
 		data = netlink_alloc_value(&netlink_location, &nld);
 		data->dtype = &string_type;
-		data->byteorder = BYTEORDER_HOST_ENDIAN;
-		mpz_switch_byteorder(data->value, data->len / BITS_PER_BYTE);
+		data->byteorder = BYTEORDER_BIG_ENDIAN;
 		expr = mapping_expr_alloc(&netlink_location, expr, data);
 	}
 out:
@@ -1771,7 +1771,7 @@ static void trace_print_verdict(const struct nftnl_trace *nlt,
 		chain = xstrdup(nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET));
 		chain_expr = constant_expr_alloc(&netlink_location,
 						 &string_type,
-						 BYTEORDER_HOST_ENDIAN,
+						 BYTEORDER_BIG_ENDIAN,
 						 strlen(chain) * BITS_PER_BYTE,
 						 chain);
 	}
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index db58e8c386c00..872c36f186c0f 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -979,7 +979,7 @@ static void netlink_parse_log(struct netlink_parse_ctx *ctx,
 	if (nftnl_expr_is_set(nle, NFTNL_EXPR_LOG_PREFIX)) {
 		stmt->log.prefix = constant_expr_alloc(&internal_location,
 						       &string_type,
-						       BYTEORDER_HOST_ENDIAN,
+						       BYTEORDER_BIG_ENDIAN,
 						       (strlen(prefix) + 1) * BITS_PER_BYTE,
 						       prefix);
 		stmt->log.flags |= STMT_LOG_PREFIX;
@@ -1703,7 +1703,7 @@ static void netlink_parse_objref(struct netlink_parse_ctx *ctx,
 					   &nld.len);
 		expr = netlink_alloc_value(&netlink_location, &nld);
 		datatype_set(expr, &string_type);
-		expr->byteorder = BYTEORDER_HOST_ENDIAN;
+		expr->byteorder = BYTEORDER_BIG_ENDIAN;
 	} else if (nftnl_expr_is_set(nle, NFTNL_EXPR_OBJREF_SET_SREG)) {
 		struct expr *left, *right;
 		enum nft_registers sreg;
@@ -1732,7 +1732,7 @@ static void netlink_parse_objref(struct netlink_parse_ctx *ctx,
 
 		right = set_ref_expr_alloc(loc, set);
 		expr = map_expr_alloc(loc, left, right);
-		expr_set_type(expr, &string_type, BYTEORDER_HOST_ENDIAN);
+		expr_set_type(expr, &string_type, BYTEORDER_BIG_ENDIAN);
 		type = set->objtype;
 	} else {
 		netlink_error(ctx, loc, "unknown objref expression type %u",
@@ -2413,12 +2413,12 @@ static struct expr *string_wildcard_expr_alloc(struct location *loc,
 	char data[len + 2];
 	int pos;
 
-	mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
+	mpz_export_data(data, expr->value, BYTEORDER_BIG_ENDIAN, len);
 	pos = div_round_up(expr_mask_to_prefix(mask), BITS_PER_BYTE);
 	data[pos] = '*';
 	data[pos + 1] = '\0';
 
-	return constant_expr_alloc(loc, expr->dtype, BYTEORDER_HOST_ENDIAN,
+	return constant_expr_alloc(loc, expr->dtype, BYTEORDER_BIG_ENDIAN,
 				   expr->len + BITS_PER_BYTE, data);
 }
 
@@ -2431,7 +2431,7 @@ static bool __expr_postprocess_string(struct expr **exprp)
 	unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
 	char data[len + 1];
 
-	mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
+	mpz_export_data(data, expr->value, BYTEORDER_BIG_ENDIAN, len);
 
 	if (data[len - 1] != '\0')
 		return false;
@@ -2442,7 +2442,7 @@ static bool __expr_postprocess_string(struct expr **exprp)
 		data[len]	= '*';
 		data[len + 1]	= '\0';
 		expr = constant_expr_alloc(&expr->location, expr->dtype,
-					   BYTEORDER_HOST_ENDIAN,
+					   BYTEORDER_BIG_ENDIAN,
 					   (len + 2) * BITS_PER_BYTE, data);
 		expr_free(*exprp);
 		*exprp = expr;
diff --git a/src/osf.c b/src/osf.c
index cb58315d714d1..863646109927b 100644
--- a/src/osf.c
+++ b/src/osf.c
@@ -67,7 +67,7 @@ struct expr *osf_expr_alloc(const struct location *loc, const uint8_t ttl,
 	struct expr *expr;
 
 	expr = expr_alloc(loc, EXPR_OSF, type,
-			  BYTEORDER_HOST_ENDIAN, len);
+			  BYTEORDER_BIG_ENDIAN, len);
 	expr->osf.ttl = ttl;
 	expr->osf.flags = flags;
 
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 81d75ecb2fe8a..87294b9a56026 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -2143,7 +2143,7 @@ flowtable_list_expr	:	flowtable_expr_member
 flowtable_expr_member	:	STRING
 			{
 				$$ = constant_expr_alloc(&@$, &string_type,
-							 BYTEORDER_HOST_ENDIAN,
+							 BYTEORDER_BIG_ENDIAN,
 							 strlen($1) * BITS_PER_BYTE, $1);
 				xfree($1);
 			}
@@ -2406,7 +2406,7 @@ extended_prio_spec	:	int_num
 				struct prio_spec spec = {0};
 
 				spec.expr = constant_expr_alloc(&@$, &string_type,
-								BYTEORDER_HOST_ENDIAN,
+								BYTEORDER_BIG_ENDIAN,
 								strlen($1) * BITS_PER_BYTE,
 								$1);
 				xfree($1);
@@ -2419,7 +2419,7 @@ extended_prio_spec	:	int_num
 				char str[NFT_NAME_MAXLEN];
 				snprintf(str, sizeof(str), "%s + %" PRIu64, $1, $3);
 				spec.expr = constant_expr_alloc(&@$, &string_type,
-								BYTEORDER_HOST_ENDIAN,
+								BYTEORDER_BIG_ENDIAN,
 								strlen(str) * BITS_PER_BYTE,
 								str);
 				xfree($1);
@@ -2432,7 +2432,7 @@ extended_prio_spec	:	int_num
 
 				snprintf(str, sizeof(str), "%s - %" PRIu64, $1, $3);
 				spec.expr = constant_expr_alloc(&@$, &string_type,
-								BYTEORDER_HOST_ENDIAN,
+								BYTEORDER_BIG_ENDIAN,
 								strlen(str) * BITS_PER_BYTE,
 								str);
 				xfree($1);
@@ -2449,7 +2449,7 @@ dev_spec		:	DEVICE	string
 				struct expr *expr;
 
 				expr = constant_expr_alloc(&@$, &string_type,
-							   BYTEORDER_HOST_ENDIAN,
+							   BYTEORDER_BIG_ENDIAN,
 							   strlen($2) * BITS_PER_BYTE, $2);
 				xfree($2);
 				$$ = compound_expr_alloc(&@$, EXPR_LIST);
@@ -2944,7 +2944,7 @@ log_arg			:	PREFIX			string
 				/* No variables in log prefix, skip. */
 				if (!strchr($2, '$')) {
 					expr = constant_expr_alloc(&@$, &string_type,
-								   BYTEORDER_HOST_ENDIAN,
+								   BYTEORDER_BIG_ENDIAN,
 								   (strlen($2) + 1) * BITS_PER_BYTE, $2);
 					xfree($2);
 					$<stmt>0->log.prefix = expr;
@@ -2981,7 +2981,7 @@ log_arg			:	PREFIX			string
 
 						*end = '\0';
 						item = constant_expr_alloc(&@$, &string_type,
-									   BYTEORDER_HOST_ENDIAN,
+									   BYTEORDER_BIG_ENDIAN,
 									   (strlen(start) + 1) * BITS_PER_BYTE,
 									   start);
 						compound_expr_add(expr, item);
@@ -4861,7 +4861,7 @@ chain_expr		:	variable_expr
 			|	identifier
 			{
 				$$ = constant_expr_alloc(&@$, &string_type,
-							 BYTEORDER_HOST_ENDIAN,
+							 BYTEORDER_BIG_ENDIAN,
 							 strlen($1) * BITS_PER_BYTE,
 							 $1);
 				xfree($1);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 11/15] evaluate: Fix key byteorder value in range sets/maps
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (9 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 10/15] Make string-based data types " Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 12/15] include: Use struct nftnl_set_desc Phil Sutter
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

In interval sets/maps, elements are always Big Endian, set
key->byteorder accordingly. This becomes relevant when dumping set
elements for debug output.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/evaluate.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index fbf3aa8d19139..983808d65714b 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1617,9 +1617,12 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
 	map->flags |= EXPR_F_CONSTANT;
 
 	/* Data for range lookups needs to be in big endian order */
-	if (map->mappings->set->flags & NFT_SET_INTERVAL &&
-	    byteorder_conversion(ctx, &map->map, BYTEORDER_BIG_ENDIAN) < 0)
-		return -1;
+	if (map->mappings->set->flags & NFT_SET_INTERVAL) {
+		if (byteorder_conversion(ctx, &map->map,
+					 BYTEORDER_BIG_ENDIAN) < 0)
+			return -1;
+		map->mappings->set->key->byteorder = BYTEORDER_BIG_ENDIAN;
+	}
 
 	return 0;
 }
@@ -2077,10 +2080,14 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
 				return expr_error(ctx->msgs, left,
 						  "specify either ip or ip6 for address matching");
 
+			if (!(right->set->flags & NFT_SET_INTERVAL))
+				break;
+
 			/* Data for range lookups needs to be in big endian order */
-			if (right->set->flags & NFT_SET_INTERVAL &&
-			    byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0)
+			if (byteorder_conversion(ctx, &rel->left,
+						 BYTEORDER_BIG_ENDIAN) < 0)
 				return -1;
+			right->set->key->byteorder = BYTEORDER_BIG_ENDIAN;
 			break;
 		case EXPR_CONCAT:
 			return expr_binary_error(ctx->msgs, left, right,
@@ -3759,9 +3766,12 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
 	map->flags |= EXPR_F_CONSTANT;
 
 	/* Data for range lookups needs to be in big endian order */
-	if (map->mappings->set->flags & NFT_SET_INTERVAL &&
-	    byteorder_conversion(ctx, &map->map, BYTEORDER_BIG_ENDIAN) < 0)
-		return -1;
+	if (map->mappings->set->flags & NFT_SET_INTERVAL) {
+		if (byteorder_conversion(ctx, &map->map,
+					 BYTEORDER_BIG_ENDIAN) < 0)
+			return -1;
+		map->mappings->set->key->byteorder = BYTEORDER_BIG_ENDIAN;
+	}
 
 	return 0;
 }
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 12/15] include: Use struct nftnl_set_desc
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (10 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 11/15] evaluate: Fix key byteorder value in range sets/maps Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 13/15] mnl: Provide libnftnl with set element meta info when dumping Phil Sutter
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Since libnftnl now exports the data structure, use it in struct set.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 include/rule.h | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index be31695636df4..5e6647f9d6cca 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -6,6 +6,7 @@
 #include <list.h>
 #include <netinet/in.h>
 #include <libnftnl/object.h>	/* For NFTNL_CTTIMEOUT_ARRAY_MAX. */
+#include <libnftnl/set.h>
 #include <linux/netfilter/nf_tables.h>
 #include <string.h>
 #include <cache.h>
@@ -330,9 +331,7 @@ void rule_stmt_insert_at(struct rule *rule, struct stmt *nstmt,
  * @policy:	set mechanism policy
  * @automerge:	merge adjacents and overlapping elements, if possible
  * @comment:	comment
- * @desc.size:		count of set elements
- * @desc.field_len:	length of single concatenated fields, bytes
- * @desc.field_count:	count of concatenated fields
+ * @desc:	set element meta data
  */
 struct set {
 	struct list_head	list;
@@ -354,11 +353,7 @@ struct set {
 	bool			automerge;
 	bool			key_typeof_valid;
 	const char		*comment;
-	struct {
-		uint32_t	size;
-		uint8_t		field_len[NFT_REG32_COUNT];
-		uint8_t		field_count;
-	} desc;
+	struct nftnl_set_desc	desc;
 };
 
 extern struct set *set_alloc(const struct location *loc);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 13/15] mnl: Provide libnftnl with set element meta info when dumping
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (11 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 12/15] include: Use struct nftnl_set_desc Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-24 17:22 ` [nft PATCH 14/15] tests/py/tools: Add regen_payloads.sh Phil Sutter
  2021-11-30 13:47 ` [nft PATCH 00/15] Fix netlink debug output on Big Endian Pablo Neira Ayuso
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

To consistently print set elements' data regs irrespective of host byte
order, libnftnl needs to be provided with data reg sizes and byteorder.

To collect sizes, generalize the population of 'field_len' and
'field_count' fields to non-interval concat keys, too. Perform the same
data collection for target data in maps as well, making use of
'data_len' and 'data_count' fields in set desc.

Collect individual data reg fields' byteorder info on demand by
inspecting the constructed data types of concatenated keys/values.

To pass above data along to nftnl_set_elem_snprintf_desc() when dumping
set elements, pass a pointer to the relevant struct set when calling
mnl_nft_setelem_batch().

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/evaluate.c | 16 ++++++----
 src/mnl.c      | 84 ++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 81 insertions(+), 19 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index 983808d65714b..5a875eaf8b17c 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1582,13 +1582,13 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
 		map = *expr;
 		map->mappings->set->flags |= map->mappings->set->init->set_flags;
 
-		if (map->mappings->set->flags & NFT_SET_INTERVAL &&
-		    map->map->etype == EXPR_CONCAT) {
+		if (map->map->etype == EXPR_CONCAT) {
 			memcpy(&map->mappings->set->desc.field_len, &map->map->field_len,
 			       sizeof(map->mappings->set->desc.field_len));
 			map->mappings->set->desc.field_count = map->map->field_count;
 			map->mappings->flags |= NFT_SET_CONCAT;
 		}
+
 		break;
 	case EXPR_SYMBOL:
 		if (expr_evaluate(ctx, &map->mappings) < 0)
@@ -3974,7 +3974,7 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
 						  set->key->dtype, type);
 	}
 
-	if (set->flags & NFT_SET_INTERVAL && set->key->etype == EXPR_CONCAT) {
+	if (set->key->etype == EXPR_CONCAT) {
 		memcpy(&set->desc.field_len, &set->key->field_len,
 		       sizeof(set->desc.field_len));
 		set->desc.field_count = set->key->field_count;
@@ -3986,9 +3986,13 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
 			return set_error(ctx, set, "map definition does not "
 					 "specify mapping data type");
 
-		if (set->data->etype == EXPR_CONCAT &&
-		    set_expr_evaluate_concat(ctx, &set->data) < 0)
-			return -1;
+		if (set->data->etype == EXPR_CONCAT) {
+			if (expr_evaluate_concat(ctx, &set->data) < 0)
+				return -1;
+			memcpy(&set->desc.data_len, &set->data->field_len,
+			       sizeof(set->desc.data_len));
+			set->desc.data_count = set->data->field_count;
+		}
 
 		if (set->data->flags & EXPR_F_INTERVAL)
 			set->data->len *= 2;
diff --git a/src/mnl.c b/src/mnl.c
index a3ee32680a77a..5bb6dcad81a09 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1063,6 +1063,44 @@ static void set_key_expression(struct netlink_ctx *ctx,
 /*
  * Set
  */
+
+static uint16_t dtype_byteorder_bits(const struct datatype *dtype,
+				     enum byteorder byteorder)
+{
+	const struct datatype *subtype;
+	uint16_t bits = 0;
+	int n, dsz, i = 0;
+
+	if (dtype->type == TYPE_VERDICT)
+		return 0;
+
+	if (!(dtype->type & ~TYPE_MASK)) {
+		/* XXX: is this right? does set->key->byteorder take
+		 *      precedence over set->key->dtype->byteorder?
+		 *      if not, respect byteorder only if
+		 *      dtype->byteorder == BYTEORDER_INVALID
+		 */
+		if (dtype->byteorder == BYTEORDER_BIG_ENDIAN ||
+		    byteorder == BYTEORDER_BIG_ENDIAN)
+			return -1;
+		return 0;
+	}
+	n = div_round_up(fls(dtype->type), TYPE_BITS);
+	while (n > 0 && concat_subtype_id(dtype->type, --n)) {
+		subtype = concat_subtype_lookup(dtype->type, n);
+		if (!subtype)
+			break;
+
+		for (dsz = subtype->size;
+		     dsz > 0;
+		     dsz -= sizeof(uint32_t) * BITS_PER_BYTE) {
+			bits |= (subtype->byteorder ==
+				 BYTEORDER_BIG_ENDIAN) << i++;
+		}
+	}
+	return bits;
+}
+
 int mnl_nft_set_add(struct netlink_ctx *ctx, struct cmd *cmd,
 		    unsigned int flags)
 {
@@ -1535,16 +1573,36 @@ static bool mnl_nft_attr_nest_overflow(struct nlmsghdr *nlh,
 	return false;
 }
 
-static void netlink_dump_setelem(const struct nftnl_set_elem *nlse,
-				 struct netlink_ctx *ctx)
+static void set_to_desc(struct nftnl_set_desc *desc, const struct set *set)
+{
+	if (!set)
+		return;
+
+	memcpy(desc, &set->desc, sizeof(*desc));
+
+	desc->byteorder = dtype_byteorder_bits(set->key->dtype,
+					       set->key->byteorder);
+
+	if (!set_is_datamap(set->flags))
+		return;
+
+	desc->byteorder |= dtype_byteorder_bits(set->data->dtype,
+						set->data->byteorder) << 16;
+}
+
+static void netlink_dump_setelem(struct nftnl_set_elem *nlse,
+				 struct netlink_ctx *ctx, const struct set *set)
 {
 	FILE *fp = ctx->nft->output.output_fp;
+	struct nftnl_set_desc desc;
 	char buf[4096];
 
 	if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
 		return;
 
-	nftnl_set_elem_snprintf(buf, sizeof(buf), nlse, NFTNL_OUTPUT_DEFAULT, 0);
+	set_to_desc(&desc, set);
+	nftnl_set_elem_snprintf_desc(buf, sizeof(buf), nlse, &desc,
+				     NFTNL_OUTPUT_DEFAULT, 0);
 	fprintf(fp, "\t%s", buf);
 }
 
@@ -1562,8 +1620,8 @@ static int mnl_nft_setelem_batch(const struct nftnl_set *nls,
 				 struct nftnl_batch *batch,
 				 enum nf_tables_msg_types cmd,
 				 unsigned int flags, uint32_t seqnum,
-				 const struct expr *set,
-				 struct netlink_ctx *ctx)
+				 const struct expr *init,
+				 struct netlink_ctx *ctx, const struct set *set)
 {
 	struct nlattr *nest1, *nest2;
 	struct nftnl_set_elem *nlse;
@@ -1574,8 +1632,8 @@ static int mnl_nft_setelem_batch(const struct nftnl_set *nls,
 	if (cmd == NFT_MSG_NEWSETELEM)
 		flags |= NLM_F_CREATE;
 
-	if (set)
-		expr = list_first_entry(&set->expressions, struct expr, list);
+	if (init)
+		expr = list_first_entry(&init->expressions, struct expr, list);
 
 next:
 	nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch), cmd,
@@ -1595,15 +1653,15 @@ next:
 				 htonl(nftnl_set_get_u32(nls, NFTNL_SET_ID)));
 	}
 
-	if (!set || list_empty(&set->expressions))
+	if (!init || list_empty(&init->expressions))
 		return 0;
 
 	assert(expr);
 	nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
-	list_for_each_entry_from(expr, &set->expressions, list) {
-		nlse = alloc_nftnl_setelem(set, expr);
+	list_for_each_entry_from(expr, &init->expressions, list) {
+		nlse = alloc_nftnl_setelem(init, expr);
 		nest2 = nftnl_set_elem_nlmsg_build(nlh, nlse, ++i);
-		netlink_dump_setelem(nlse, ctx);
+		netlink_dump_setelem(nlse, ctx, set);
 		nftnl_set_elem_free(nlse);
 		if (mnl_nft_attr_nest_overflow(nlh, nest1, nest2)) {
 			mnl_attr_nest_end(nlh, nest1);
@@ -1641,7 +1699,7 @@ int mnl_nft_setelem_add(struct netlink_ctx *ctx, const struct set *set,
 	netlink_dump_set(nls, ctx);
 
 	err = mnl_nft_setelem_batch(nls, ctx->batch, NFT_MSG_NEWSETELEM,
-				    flags, ctx->seqnum, expr, ctx);
+				    flags, ctx->seqnum, expr, ctx, set);
 	nftnl_set_free(nls);
 
 	return err;
@@ -1697,7 +1755,7 @@ int mnl_nft_setelem_del(struct netlink_ctx *ctx, const struct cmd *cmd)
 	netlink_dump_set(nls, ctx);
 
 	err = mnl_nft_setelem_batch(nls, ctx->batch, NFT_MSG_DELSETELEM, 0,
-				    ctx->seqnum, cmd->expr, ctx);
+				    ctx->seqnum, cmd->expr, ctx, cmd->elem.set);
 	nftnl_set_free(nls);
 
 	return err;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [nft PATCH 14/15] tests/py/tools: Add regen_payloads.sh
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (12 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 13/15] mnl: Provide libnftnl with set element meta info when dumping Phil Sutter
@ 2021-11-24 17:22 ` Phil Sutter
  2021-11-30 13:47 ` [nft PATCH 00/15] Fix netlink debug output on Big Endian Pablo Neira Ayuso
  14 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-24 17:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

The script used to regenerate all payload records after massive changes
to libnftnl debug output formatting.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 tests/py/tools/regen_payloads.sh | 72 ++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)
 create mode 100755 tests/py/tools/regen_payloads.sh

diff --git a/tests/py/tools/regen_payloads.sh b/tests/py/tools/regen_payloads.sh
new file mode 100755
index 0000000000000..ed937584d780b
--- /dev/null
+++ b/tests/py/tools/regen_payloads.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+# update payload records in an automated fashion, trying to reduce diff sizes
+
+
+# scan payloadfile and print record for cmd (if found)
+find_payload() { # (payloadfile, cmd)
+	local found=false
+
+	readarray -t pl <"$1"
+	for l in "${pl[@]}"; do
+		if [[ "$l" == "# "* ]]; then
+			$found && return
+			[[ "$l" == "$2" ]] && found=true
+		fi
+		$found && echo "$l"
+	done
+	$found || echo "Warning: Command '$2' not found in '$1'" >&2
+}
+
+cd $(dirname $0)/../
+
+# make sure no stray output files get in the way
+rm -f */*.got */*.gotgot
+
+# store payload records for later
+# clear payload files to force regenerating (but leave them in place)
+for pl in */*.payload*; do
+	[[ $pl == *.bak ]] && continue # ignore leftover .bak files
+	cp "$pl" "${pl}.bak"
+	echo >"$pl"
+done
+
+# run the testsuite to create .got files
+# pass -f to keep going despite missing payloads
+./nft-test.py -f
+
+# restore old payload records
+for plbak in */*.bak; do
+	cp "$plbak" "${plbak%.bak}"
+done
+
+# sort created got files to match order in old payload records
+for g in ${@:-*/*.got}; do
+	pl=${g%.got}
+
+	[[ -f $g ]] || continue
+	[[ -f $pl ]] || continue
+
+	readarray -t ploads <"$g"
+	readarray -t cmds <<< $(grep '^# ' $pl)
+	for cmd in "${cmds[@]}"; do
+		found=false
+		for l in "${ploads[@]}"; do
+			if [[ "$l" == "# "* ]]; then
+				$found && break
+				[[ "$l" == "$cmd" ]] && found=true
+			fi
+			$found && echo "$l"
+		done
+		$found || echo "Warning: Command '$cmd' not found in '$g'" >&2
+	done >${g}got
+
+	cp "${g}" "${g}.unsorted"
+	cp "${g}got" "${g}.sorted"
+	mv "${g}got" "${g}"
+done
+
+# overwrite old payload records with new ones
+for got in */*.got; do
+	mv "${got}" "${got%.got}"
+done
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [nft PATCH 00/15] Fix netlink debug output on Big Endian
  2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
                   ` (13 preceding siblings ...)
  2021-11-24 17:22 ` [nft PATCH 14/15] tests/py/tools: Add regen_payloads.sh Phil Sutter
@ 2021-11-30 13:47 ` Pablo Neira Ayuso
  2021-11-30 13:55   ` Phil Sutter
  14 siblings, 1 reply; 17+ messages in thread
From: Pablo Neira Ayuso @ 2021-11-30 13:47 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netfilter-devel

On Wed, Nov 24, 2021 at 06:22:36PM +0100, Phil Sutter wrote:
> Make use of recent changes to libnftnl and make tests/py testsuite pass
> on Big Endian systems.
> 
> Patches 1, 2 and 3 are more or less unrelated fallout from the actual
> work but simple enough to not deserve separate submission.
> 
> Patches 4-9 fix actual bugs on Big Endian.

I think up to patch 9 should be good to be merged upstream as these
are asorted updates + actual Big Endian bugs as you describe.

Let's discuss patches start 10 and your libnftnl updates separately,
OK?

> Patch 10 is part convenience and part preparation for the following
> patches.
> 
> Patches 11 and 12 prepare for patch 13 which fixes set element dumping.
> 
> Patch 14 adds a shell script which regenerates all payload records,
> respecting the separation into family-specific files where used.
> 
> Patch 15 contains the big mess of regenerated payload records from using
> the previous patch's script. It is at the same time too large to read
> and a clear illustration of this and the respective libnftnl's patch
> series' effect.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [nft PATCH 00/15] Fix netlink debug output on Big Endian
  2021-11-30 13:47 ` [nft PATCH 00/15] Fix netlink debug output on Big Endian Pablo Neira Ayuso
@ 2021-11-30 13:55   ` Phil Sutter
  0 siblings, 0 replies; 17+ messages in thread
From: Phil Sutter @ 2021-11-30 13:55 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Hi Pablo,

On Tue, Nov 30, 2021 at 02:47:49PM +0100, Pablo Neira Ayuso wrote:
> On Wed, Nov 24, 2021 at 06:22:36PM +0100, Phil Sutter wrote:
> > Make use of recent changes to libnftnl and make tests/py testsuite pass
> > on Big Endian systems.
> > 
> > Patches 1, 2 and 3 are more or less unrelated fallout from the actual
> > work but simple enough to not deserve separate submission.
> > 
> > Patches 4-9 fix actual bugs on Big Endian.
> 
> I think up to patch 9 should be good to be merged upstream as these
> are asorted updates + actual Big Endian bugs as you describe.
> 
> Let's discuss patches start 10 and your libnftnl updates separately,
> OK?

Fine with me, thanks for the (quick) review. I'll push patches 1-9, will
get back at your remarks on the libnftnl series later. Then we'll see
what remains from patches 10-15 here.

Thanks, Phil

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2021-11-30 13:55 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-24 17:22 [nft PATCH 00/15] Fix netlink debug output on Big Endian Phil Sutter
2021-11-24 17:22 ` [nft PATCH 01/15] tests/py: Avoid duplicate records in *.got files Phil Sutter
2021-11-24 17:22 ` [nft PATCH 02/15] exthdr: Fix for segfault with unknown exthdr Phil Sutter
2021-11-24 17:22 ` [nft PATCH 03/15] mnl: Fix for missing info in rule dumps Phil Sutter
2021-11-24 17:22 ` [nft PATCH 04/15] src: Fix payload statement mask on Big Endian Phil Sutter
2021-11-24 17:22 ` [nft PATCH 05/15] meta: Fix {g,u}id_type " Phil Sutter
2021-11-24 17:22 ` [nft PATCH 06/15] meta: Fix hour_type size Phil Sutter
2021-11-24 17:22 ` [nft PATCH 07/15] datatype: Fix size of time_type Phil Sutter
2021-11-24 17:22 ` [nft PATCH 08/15] ct: Fix ct label value parser Phil Sutter
2021-11-24 17:22 ` [nft PATCH 09/15] netlink_delinearize: Fix for escaped asterisk strings on Big Endian Phil Sutter
2021-11-24 17:22 ` [nft PATCH 10/15] Make string-based data types " Phil Sutter
2021-11-24 17:22 ` [nft PATCH 11/15] evaluate: Fix key byteorder value in range sets/maps Phil Sutter
2021-11-24 17:22 ` [nft PATCH 12/15] include: Use struct nftnl_set_desc Phil Sutter
2021-11-24 17:22 ` [nft PATCH 13/15] mnl: Provide libnftnl with set element meta info when dumping Phil Sutter
2021-11-24 17:22 ` [nft PATCH 14/15] tests/py/tools: Add regen_payloads.sh Phil Sutter
2021-11-30 13:47 ` [nft PATCH 00/15] Fix netlink debug output on Big Endian Pablo Neira Ayuso
2021-11-30 13:55   ` Phil Sutter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.