[libnftnl PATCH v2 1/7] src: add infrastructure to infer byteorder from keys

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>

This patch adds a new .byteorder callback to expressions to allow infer
the data byteorder that is placed in registers. Given that keys have a
fixed datatype, this patch tracks register operations to obtain the data
byteorder. This new infrastructure is internal and it is only used by
the nftnl_rule_snprintf() function to make it portable regardless the
endianess.

A few examples after this patch running on x86_64:

netdev
  [ meta load protocol => reg 1 ]
  [ cmp eq reg 1 0x00000008 ]
  [ immediate reg 1 0x01020304 ]
  [ payload write reg 1 => 4b @ network header + 12 csum_type 1 csum_off 10 csum_flags 0x1 ]

root@salvia:/home/pablo/devel/scm/git-netfilter/libnftnl# nft --debug=netlink add rule netdev x z ip saddr 1.2.3.4
netdev
  [ meta load protocol => reg 1 ]
  [ cmp eq reg 1 0x00000008 ]
  [ payload load 4b @ network header + 12 => reg 1 ]
  [ cmp eq reg 1 0x01020304 ]

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
Signed-off-by: Phil Sutter <phil@xxxxxx>
---
Changes since v1:
- Fix calls to changed nftnl_data_reg_snprintf().
- Add more byteorder callbacks
- expr/xfrm: Fix SPI endianness, was recently corrected in nftables
- ct helper: Strings are always "big endian"
- expr/cmp: Boundary comparisons are always Big Endian
- expr/range: Ranges are always in network byte order
---
 include/common.h     | 29 +++++++++++++++++++++++++
 include/data_reg.h   |  4 +++-
 include/expr.h       |  2 +-
 include/expr_ops.h   |  2 ++
 src/expr.c           | 51 ++++++++++++++++++++++++++++++++++++++++++++
 src/expr/bitwise.c   | 30 +++++++++++++++++++-------
 src/expr/byteorder.c | 21 ++++++++++++++++++
 src/expr/cmp.c       | 21 +++++++++++++++++-
 src/expr/ct.c        | 30 ++++++++++++++++++++++++++
 src/expr/data_reg.c  | 18 +++++++++++-----
 src/expr/dup.c       | 14 ++++++++++++
 src/expr/exthdr.c    | 14 ++++++++++++
 src/expr/fib.c       | 18 ++++++++++++++++
 src/expr/fwd.c       | 14 ++++++++++++
 src/expr/immediate.c | 17 ++++++++++++---
 src/expr/masq.c      | 16 ++++++++++++++
 src/expr/meta.c      | 28 ++++++++++++++++++++++++
 src/expr/nat.c       | 22 +++++++++++++++++++
 src/expr/numgen.c    | 12 +++++++++++
 src/expr/osf.c       | 12 +++++++++++
 src/expr/payload.c   | 14 ++++++++++++
 src/expr/queue.c     | 12 +++++++++++
 src/expr/range.c     | 11 ++++++++--
 src/expr/redir.c     | 16 ++++++++++++++
 src/expr/rt.c        | 19 +++++++++++++++++
 src/expr/socket.c    | 12 +++++++++++
 src/expr/tproxy.c    | 14 ++++++++++++
 src/expr/tunnel.c    | 12 +++++++++++
 src/expr/xfrm.c      | 18 ++++++++++++++++
 src/rule.c           |  7 ++++++
 src/set_elem.c       |  9 +++++---
 31 files changed, 495 insertions(+), 24 deletions(-)

diff --git a/include/common.h b/include/common.h
index d05a81ad542c1..13d709b247f92 100644
--- a/include/common.h
+++ b/include/common.h
@@ -18,4 +18,33 @@ enum nftnl_parse_input {
 	NFTNL_PARSE_FILE,
 };
 
+enum nftnl_byteorder {
+	NFTNL_BYTEORDER_UNKNOWN	= 0,
+	NFTNL_BYTEORDER_HOST,
+	NFTNL_BYTEORDER_NETWORK,
+};
+
+#define NFTNL_CTX_BYTEORDER_MAX_EXPRS	16
+
+struct nftnl_byteorder_ctx {
+	struct {
+		const struct nftnl_expr	*expr;
+		enum nftnl_byteorder	byteorder;
+	} expr[NFT_REG32_15 + 1];
+	struct {
+		uint32_t		reg;
+		struct nftnl_expr	*expr;
+	} pending[NFTNL_CTX_BYTEORDER_MAX_EXPRS];
+	uint32_t			num_pending;
+};
+
+void nftnl_reg_byteorder_set(struct nftnl_byteorder_ctx *ctx, uint32_t reg,
+			     enum nftnl_byteorder byteorder);
+enum nftnl_byteorder nftnl_reg_byteorder_get(struct nftnl_byteorder_ctx *ctx,
+					     uint32_t reg);
+void nftnl_reg_byteorder_unknown(struct nftnl_byteorder_ctx *ctx, uint32_t reg,
+				 struct nftnl_expr *expr);
+void nftnl_reg_byteorder_resolve(struct nftnl_byteorder_ctx *ctx, uint32_t reg,
+				 enum nftnl_byteorder byteorder);
+
 #endif
diff --git a/include/data_reg.h b/include/data_reg.h
index 6d2dc66858bf8..3f24b6725e148 100644
--- a/include/data_reg.h
+++ b/include/data_reg.h
@@ -5,6 +5,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <unistd.h>
+#include "common.h"
 
 enum {
 	DATA_NONE,
@@ -31,7 +32,8 @@ union nftnl_data_reg {
 
 int nftnl_data_reg_snprintf(char *buf, size_t size,
 			    const union nftnl_data_reg *reg,
-			    uint32_t flags, int reg_type);
+			    uint32_t flags, int reg_type,
+			    enum nftnl_byteorder byteorder);
 struct nlattr;
 
 int nftnl_parse_data(union nftnl_data_reg *data, struct nlattr *attr, int *type);
diff --git a/include/expr.h b/include/expr.h
index be45e954df5b6..50959724492e7 100644
--- a/include/expr.h
+++ b/include/expr.h
@@ -6,6 +6,7 @@ struct expr_ops;
 struct nftnl_expr {
 	struct list_head	head;
 	uint32_t		flags;
+	uint32_t		byteorder;
 	struct expr_ops		*ops;
 	uint8_t			data[];
 };
@@ -15,5 +16,4 @@ struct nlmsghdr;
 void nftnl_expr_build_payload(struct nlmsghdr *nlh, struct nftnl_expr *expr);
 struct nftnl_expr *nftnl_expr_parse(struct nlattr *attr);
 
-
 #endif
diff --git a/include/expr_ops.h b/include/expr_ops.h
index 7a6aa23f9bd1d..161babdade596 100644
--- a/include/expr_ops.h
+++ b/include/expr_ops.h
@@ -7,6 +7,7 @@
 struct nlattr;
 struct nlmsghdr;
 struct nftnl_expr;
+struct nftnl_print_ctx;
 
 struct expr_ops {
 	const char *name;
@@ -18,6 +19,7 @@ struct expr_ops {
 	const void *(*get)(const struct nftnl_expr *e, uint16_t type, uint32_t *data_len);
 	int 	(*parse)(struct nftnl_expr *e, struct nlattr *attr);
 	void	(*build)(struct nlmsghdr *nlh, const struct nftnl_expr *e);
+	void	(*byteorder)(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e);
 	int	(*snprintf)(char *buf, size_t len, uint32_t flags, const struct nftnl_expr *e);
 };
 
diff --git a/src/expr.c b/src/expr.c
index 277bbdeeb5d02..d958bab98e925 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -301,3 +301,54 @@ int nftnl_expr_fprintf(FILE *fp, const struct nftnl_expr *expr, uint32_t type,
 	return nftnl_fprintf(fp, expr, NFTNL_CMD_UNSPEC, type, flags,
 			     nftnl_expr_do_snprintf);
 }
+
+void nftnl_reg_byteorder_set(struct nftnl_byteorder_ctx *ctx, uint32_t reg,
+			     enum nftnl_byteorder byteorder)
+{
+       if (reg > NFT_REG32_15)
+	       return;
+
+       ctx->expr[reg].byteorder = byteorder;
+}
+
+enum nftnl_byteorder nftnl_reg_byteorder_get(struct nftnl_byteorder_ctx *ctx,
+					     uint32_t reg)
+{
+       if (reg > NFT_REG32_15)
+	       return NFTNL_BYTEORDER_UNKNOWN;
+
+       return ctx->expr[reg].byteorder;
+}
+
+void nftnl_reg_byteorder_unknown(struct nftnl_byteorder_ctx *ctx, uint32_t reg,
+				 struct nftnl_expr *expr)
+{
+       int k;
+
+       if (reg > NFT_REG32_15)
+	       return;
+
+       k = ctx->num_pending++;
+       if (k >= NFTNL_CTX_BYTEORDER_MAX_EXPRS)
+	       return;
+
+       ctx->pending[k].reg = reg;
+       ctx->pending[k].expr = expr;
+}
+
+void nftnl_reg_byteorder_resolve(struct nftnl_byteorder_ctx *ctx, uint32_t reg,
+				 enum nftnl_byteorder byteorder)
+{
+       struct nftnl_expr *expr;
+       int i;
+
+       for (i = 0; i < ctx->num_pending; i++) {
+	       if (!ctx->pending[i].expr)
+		       continue;
+	       if (ctx->pending[i].reg == reg) {
+		       expr = ctx->pending[i].expr;
+		       expr->byteorder = byteorder;
+		       ctx->pending[i].expr = NULL;
+	       }
+       }
+}
diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c
index d0c7827eacec9..a21dec01d286f 100644
--- a/src/expr/bitwise.c
+++ b/src/expr/bitwise.c
@@ -209,9 +209,18 @@ nftnl_expr_bitwise_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return ret;
 }
 
+static void
+nftnl_expr_bitwise_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_bitwise *bitwise = nftnl_expr_data(e);
+
+	e->byteorder = nftnl_reg_byteorder_get(ctx, bitwise->sreg);
+}
+
 static int
 nftnl_expr_bitwise_snprintf_bool(char *buf, size_t remain,
-				 const struct nftnl_expr_bitwise *bitwise)
+				 const struct nftnl_expr_bitwise *bitwise,
+				 enum nftnl_byteorder byteorder)
 {
 	int offset = 0, ret;
 
@@ -220,14 +229,14 @@ nftnl_expr_bitwise_snprintf_bool(char *buf, size_t remain,
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->mask,
-				      0, DATA_VALUE);
+				      0, DATA_VALUE, byteorder);
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = snprintf(buf + offset, remain, ") ^ ");
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->xor,
-				      0, DATA_VALUE);
+				      0, DATA_VALUE, byteorder);
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	return offset;
@@ -235,7 +244,8 @@ nftnl_expr_bitwise_snprintf_bool(char *buf, size_t remain,
 
 static int
 nftnl_expr_bitwise_snprintf_shift(char *buf, size_t remain, const char *op,
-				  const struct nftnl_expr_bitwise *bitwise)
+				  const struct nftnl_expr_bitwise *bitwise,
+				  enum nftnl_byteorder byteorder)
 {	int offset = 0, ret;
 
 	ret = snprintf(buf, remain, "reg %u = ( reg %u %s ",
@@ -243,7 +253,7 @@ nftnl_expr_bitwise_snprintf_shift(char *buf, size_t remain, const char *op,
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->data,
-				      0, DATA_VALUE);
+				      0, DATA_VALUE, byteorder);
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = snprintf(buf + offset, remain, ") ");
@@ -261,13 +271,16 @@ nftnl_expr_bitwise_snprintf(char *buf, size_t size,
 
 	switch (bitwise->op) {
 	case NFT_BITWISE_BOOL:
-		err = nftnl_expr_bitwise_snprintf_bool(buf, size, bitwise);
+		err = nftnl_expr_bitwise_snprintf_bool(buf, size, bitwise,
+						       e->byteorder);
 		break;
 	case NFT_BITWISE_LSHIFT:
-		err = nftnl_expr_bitwise_snprintf_shift(buf, size, "<<", bitwise);
+		err = nftnl_expr_bitwise_snprintf_shift(buf, size, "<<",
+							bitwise, e->byteorder);
 		break;
 	case NFT_BITWISE_RSHIFT:
-		err = nftnl_expr_bitwise_snprintf_shift(buf, size, ">>", bitwise);
+		err = nftnl_expr_bitwise_snprintf_shift(buf, size, ">>",
+							bitwise, e->byteorder);
 		break;
 	}
 
@@ -282,5 +295,6 @@ struct expr_ops expr_ops_bitwise = {
 	.get		= nftnl_expr_bitwise_get,
 	.parse		= nftnl_expr_bitwise_parse,
 	.build		= nftnl_expr_bitwise_build,
+	.byteorder	= nftnl_expr_bitwise_byteorder,
 	.snprintf	= nftnl_expr_bitwise_snprintf,
 };
diff --git a/src/expr/byteorder.c b/src/expr/byteorder.c
index d299745fc57b4..ae67ee6ef2b35 100644
--- a/src/expr/byteorder.c
+++ b/src/expr/byteorder.c
@@ -197,6 +197,26 @@ static inline int nftnl_str2ntoh(const char *op)
 	}
 }
 
+static void nftnl_expr_byteorder_byteorder(struct nftnl_byteorder_ctx *ctx,
+					   struct nftnl_expr *e)
+{
+	struct nftnl_expr_byteorder *byteorder = nftnl_expr_data(e);
+	enum nftnl_byteorder bo;
+
+	switch (byteorder->op) {
+	case NFT_BYTEORDER_NTOH:
+		bo = NFTNL_BYTEORDER_HOST;
+		break;
+	case NFT_BYTEORDER_HTON:
+		bo = NFTNL_BYTEORDER_NETWORK;
+		break;
+	default:
+		bo = NFTNL_BYTEORDER_UNKNOWN;
+		break;
+	}
+	nftnl_reg_byteorder_set(ctx, byteorder->dreg, bo);
+}
+
 static int
 nftnl_expr_byteorder_snprintf(char *buf, size_t remain,
 			      uint32_t flags, const struct nftnl_expr *e)
@@ -220,5 +240,6 @@ struct expr_ops expr_ops_byteorder = {
 	.get		= nftnl_expr_byteorder_get,
 	.parse		= nftnl_expr_byteorder_parse,
 	.build		= nftnl_expr_byteorder_build,
+	.byteorder	= nftnl_expr_byteorder_byteorder,
 	.snprintf	= nftnl_expr_byteorder_snprintf,
 };
diff --git a/src/expr/cmp.c b/src/expr/cmp.c
index 6030693f15d86..846a112a03231 100644
--- a/src/expr/cmp.c
+++ b/src/expr/cmp.c
@@ -176,6 +176,24 @@ static inline int nftnl_str2cmp(const char *op)
 	}
 }
 
+static void
+nftnl_expr_cmp_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_cmp *cmp = nftnl_expr_data(e);
+
+	switch (cmp->op) {
+	case NFT_CMP_LT:
+	case NFT_CMP_LTE:
+	case NFT_CMP_GT:
+	case NFT_CMP_GTE:
+		e->byteorder = NFTNL_BYTEORDER_NETWORK;
+		break;
+	default:
+		e->byteorder = nftnl_reg_byteorder_get(ctx, cmp->sreg);
+		break;
+	}
+}
+
 static int
 nftnl_expr_cmp_snprintf(char *buf, size_t remain,
 			uint32_t flags, const struct nftnl_expr *e)
@@ -188,7 +206,7 @@ nftnl_expr_cmp_snprintf(char *buf, size_t remain,
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = nftnl_data_reg_snprintf(buf + offset, remain, &cmp->data,
-				      0, DATA_VALUE);
+				      0, DATA_VALUE, e->byteorder);
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	return offset;
@@ -202,5 +220,6 @@ struct expr_ops expr_ops_cmp = {
 	.get		= nftnl_expr_cmp_get,
 	.parse		= nftnl_expr_cmp_parse,
 	.build		= nftnl_expr_cmp_build,
+	.byteorder	= nftnl_expr_cmp_byteorder,
 	.snprintf	= nftnl_expr_cmp_snprintf,
 };
diff --git a/src/expr/ct.c b/src/expr/ct.c
index d5dfc81cfe0d1..fe4fc43688eb5 100644
--- a/src/expr/ct.c
+++ b/src/expr/ct.c
@@ -222,6 +222,35 @@ static inline int str2ctdir(const char *str, uint8_t *ctdir)
 	return -1;
 }
 
+static void
+nftnl_expr_ct_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_ct *ct = nftnl_expr_data(e);
+
+	switch (ct->key) {
+	case NFT_CT_HELPER:
+	case NFT_CT_SRC:
+	case NFT_CT_DST:
+	case NFT_CT_PROTOCOL:
+	case NFT_CT_PROTO_SRC:
+	case NFT_CT_PROTO_DST:
+	case NFT_CT_SRC_IP:
+	case NFT_CT_DST_IP:
+	case NFT_CT_SRC_IP6:
+	case NFT_CT_DST_IP6:
+	case NFT_CT_ID:
+		e->byteorder = NFTNL_BYTEORDER_NETWORK;
+		break;
+	default:
+		e->byteorder = NFTNL_BYTEORDER_HOST;
+	}
+
+	if (e->flags & (1 << NFTNL_EXPR_CT_SREG))
+		nftnl_reg_byteorder_resolve(ctx, ct->sreg, e->byteorder);
+	if (e->flags & (1 << NFTNL_EXPR_CT_DREG))
+		nftnl_reg_byteorder_set(ctx, ct->dreg, e->byteorder);
+}
+
 static int
 nftnl_expr_ct_snprintf(char *buf, size_t remain,
 		       uint32_t flags, const struct nftnl_expr *e)
@@ -258,5 +287,6 @@ struct expr_ops expr_ops_ct = {
 	.get		= nftnl_expr_ct_get,
 	.parse		= nftnl_expr_ct_parse,
 	.build		= nftnl_expr_ct_build,
+	.byteorder	= nftnl_expr_ct_byteorder,
 	.snprintf	= nftnl_expr_ct_snprintf,
 };
diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c
index 2633a775c90cc..789958ea66c0d 100644
--- a/src/expr/data_reg.c
+++ b/src/expr/data_reg.c
@@ -27,16 +27,22 @@
 static int
 nftnl_data_reg_value_snprintf_default(char *buf, size_t remain,
 				      const union nftnl_data_reg *reg,
-				      uint32_t flags)
+				      uint32_t flags,
+				      enum nftnl_byteorder byteorder)
 {
 	const char *pfx = flags & DATA_F_NOPFX ? "" : "0x";
 	int offset = 0, ret, i;
+	uint32_t value;
 
 
 
 	for (i = 0; i < div_round_up(reg->len, sizeof(uint32_t)); i++) {
-		ret = snprintf(buf + offset, remain,
-			       "%s%.8x ", pfx, reg->val[i]);
+		if (byteorder == NFTNL_BYTEORDER_NETWORK)
+			value = ntohl(reg->val[i]);
+		else
+			value = reg->val[i];
+
+		ret = snprintf(buf + offset, remain, "%s%.8x ", pfx, value);
 		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 	}
 
@@ -63,12 +69,14 @@ nftnl_data_reg_verdict_snprintf_def(char *buf, size_t size,
 
 int nftnl_data_reg_snprintf(char *buf, size_t size,
 			    const union nftnl_data_reg *reg,
-			    uint32_t flags, int reg_type)
+			    uint32_t flags, int reg_type,
+			    enum nftnl_byteorder byteorder)
 {
 	switch(reg_type) {
 	case DATA_VALUE:
 		return nftnl_data_reg_value_snprintf_default(buf, size,
-							     reg, flags);
+							     reg, flags,
+							     byteorder);
 	case DATA_VERDICT:
 	case DATA_CHAIN:
 		return nftnl_data_reg_verdict_snprintf_def(buf, size,
diff --git a/src/expr/dup.c b/src/expr/dup.c
index f041b551a7e78..58c3fe6989e91 100644
--- a/src/expr/dup.c
+++ b/src/expr/dup.c
@@ -111,6 +111,19 @@ static int nftnl_expr_dup_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return ret;
 }
 
+static void
+nftnl_expr_dup_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_dup *dup = nftnl_expr_data(e);
+
+	if (e->flags & (1 << NFTNL_EXPR_DUP_SREG_ADDR))
+		nftnl_reg_byteorder_resolve(ctx, dup->sreg_addr,
+					    NFTNL_BYTEORDER_NETWORK);
+	if (e->flags & (1 << NFTNL_EXPR_DUP_SREG_DEV))
+		nftnl_reg_byteorder_resolve(ctx, dup->sreg_dev,
+					    NFTNL_BYTEORDER_HOST);
+}
+
 static int nftnl_expr_dup_snprintf(char *buf, size_t remain,
 				   uint32_t flags, const struct nftnl_expr *e)
 {
@@ -138,5 +151,6 @@ struct expr_ops expr_ops_dup = {
 	.get		= nftnl_expr_dup_get,
 	.parse		= nftnl_expr_dup_parse,
 	.build		= nftnl_expr_dup_build,
+	.byteorder	= nftnl_expr_dup_byteorder,
 	.snprintf	= nftnl_expr_dup_snprintf,
 };
diff --git a/src/expr/exthdr.c b/src/expr/exthdr.c
index 1b813b1e47c4d..280fe73f48041 100644
--- a/src/expr/exthdr.c
+++ b/src/expr/exthdr.c
@@ -235,6 +235,19 @@ static inline int str2exthdr_type(const char *str)
 	return -1;
 }
 
+static void
+nftnl_expr_exthdr_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_exthdr *exthdr = nftnl_expr_data(e);
+
+	e->byteorder = NFTNL_BYTEORDER_NETWORK;
+
+	if (e->flags & (1 << NFTNL_EXPR_EXTHDR_DREG))
+                nftnl_reg_byteorder_set(ctx, exthdr->dreg, e->byteorder);
+	if (e->flags & (1 << NFTNL_EXPR_EXTHDR_SREG))
+		nftnl_reg_byteorder_resolve(ctx, exthdr->sreg, e->byteorder);
+}
+
 static int
 nftnl_expr_exthdr_snprintf(char *buf, size_t len,
 			   uint32_t flags, const struct nftnl_expr *e)
@@ -262,5 +275,6 @@ struct expr_ops expr_ops_exthdr = {
 	.get		= nftnl_expr_exthdr_get,
 	.parse		= nftnl_expr_exthdr_parse,
 	.build		= nftnl_expr_exthdr_build,
+	.byteorder	= nftnl_expr_exthdr_byteorder,
 	.snprintf	= nftnl_expr_exthdr_snprintf,
 };
diff --git a/src/expr/fib.c b/src/expr/fib.c
index aaff52acabdbd..75194bff95f41 100644
--- a/src/expr/fib.c
+++ b/src/expr/fib.c
@@ -128,6 +128,23 @@ nftnl_expr_fib_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return ret;
 }
 
+static void
+nftnl_expr_fib_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_fib *fib = nftnl_expr_data(e);
+
+	switch (fib->result) {
+	case NFT_FIB_RESULT_OIFNAME:
+		e->byteorder = NFTNL_BYTEORDER_NETWORK;
+		break;
+	default:
+		e->byteorder = NFTNL_BYTEORDER_HOST;
+	}
+
+	if (e->flags & (1 << NFTNL_EXPR_FIB_DREG))
+                nftnl_reg_byteorder_set(ctx, fib->dreg, e->byteorder);
+}
+
 static const char *fib_type[NFT_FIB_RESULT_MAX + 1] = {
 	[NFT_FIB_RESULT_OIF] = "oif",
 	[NFT_FIB_RESULT_OIFNAME] = "oifname",
@@ -198,5 +215,6 @@ struct expr_ops expr_ops_fib = {
 	.get		= nftnl_expr_fib_get,
 	.parse		= nftnl_expr_fib_parse,
 	.build		= nftnl_expr_fib_build,
+	.byteorder	= nftnl_expr_fib_byteorder,
 	.snprintf	= nftnl_expr_fib_snprintf,
 };
diff --git a/src/expr/fwd.c b/src/expr/fwd.c
index 82e5a418bfae5..6875abfa80d19 100644
--- a/src/expr/fwd.c
+++ b/src/expr/fwd.c
@@ -125,6 +125,19 @@ static int nftnl_expr_fwd_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return ret;
 }
 
+static void
+nftnl_expr_fwd_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_fwd *fwd = nftnl_expr_data(e);
+
+	if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV))
+		nftnl_reg_byteorder_resolve(ctx, fwd->sreg_dev,
+					    NFTNL_BYTEORDER_HOST);
+	if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_ADDR))
+		nftnl_reg_byteorder_resolve(ctx, fwd->sreg_addr,
+					    NFTNL_BYTEORDER_NETWORK);
+}
+
 static int nftnl_expr_fwd_snprintf(char *buf, size_t remain,
 				   uint32_t flags, const struct nftnl_expr *e)
 {
@@ -158,5 +171,6 @@ struct expr_ops expr_ops_fwd = {
 	.get		= nftnl_expr_fwd_get,
 	.parse		= nftnl_expr_fwd_parse,
 	.build		= nftnl_expr_fwd_build,
+	.byteorder	= nftnl_expr_fwd_byteorder,
 	.snprintf	= nftnl_expr_fwd_snprintf,
 };
diff --git a/src/expr/immediate.c b/src/expr/immediate.c
index 94b043c0fc8ab..fb291c7606bab 100644
--- a/src/expr/immediate.c
+++ b/src/expr/immediate.c
@@ -183,6 +183,14 @@ nftnl_expr_immediate_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return ret;
 }
 
+static void
+nftnl_expr_immediate_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_immediate *imm = nftnl_expr_data(e);
+
+	nftnl_reg_byteorder_unknown(ctx, imm->dreg, e);
+}
+
 static int
 nftnl_expr_immediate_snprintf(char *buf, size_t remain,
 			      uint32_t flags, const struct nftnl_expr *e)
@@ -195,17 +203,19 @@ nftnl_expr_immediate_snprintf(char *buf, size_t remain,
 
 	if (e->flags & (1 << NFTNL_EXPR_IMM_DATA)) {
 		ret = nftnl_data_reg_snprintf(buf + offset, remain, &imm->data,
-					      flags, DATA_VALUE);
+					      flags, DATA_VALUE, e->byteorder);
 		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	} else if (e->flags & (1 << NFTNL_EXPR_IMM_VERDICT)) {
 		ret = nftnl_data_reg_snprintf(buf + offset, remain, &imm->data,
-					      flags, DATA_VERDICT);
+					      flags, DATA_VERDICT,
+					      NFTNL_BYTEORDER_UNKNOWN);
 		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	} else if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN)) {
 		ret = nftnl_data_reg_snprintf(buf + offset, remain, &imm->data,
-					      flags, DATA_CHAIN);
+					      flags, DATA_CHAIN,
+					      NFTNL_BYTEORDER_UNKNOWN);
 		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 	}
 
@@ -229,5 +239,6 @@ struct expr_ops expr_ops_immediate = {
 	.get		= nftnl_expr_immediate_get,
 	.parse		= nftnl_expr_immediate_parse,
 	.build		= nftnl_expr_immediate_build,
+	.byteorder	= nftnl_expr_immediate_byteorder,
 	.snprintf	= nftnl_expr_immediate_snprintf,
 };
diff --git a/src/expr/masq.c b/src/expr/masq.c
index 684708c758390..a964e3ae1a938 100644
--- a/src/expr/masq.c
+++ b/src/expr/masq.c
@@ -131,6 +131,21 @@ nftnl_expr_masq_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return 0;
 }
 
+static void
+nftnl_expr_masq_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_masq *masq = nftnl_expr_data(e);
+
+	if (e->flags & (1 << NFTNL_EXPR_MASQ_REG_PROTO_MIN))
+		nftnl_reg_byteorder_resolve(ctx, masq->sreg_proto_min,
+					    NFTNL_BYTEORDER_NETWORK);
+	if (e->flags & (1 << NFTNL_EXPR_MASQ_REG_PROTO_MAX))
+		nftnl_reg_byteorder_resolve(ctx, masq->sreg_proto_max,
+					    NFTNL_BYTEORDER_NETWORK);
+
+	e->byteorder = NFTNL_BYTEORDER_NETWORK;
+}
+
 static int nftnl_expr_masq_snprintf(char *buf, size_t remain,
 				    uint32_t flags, const struct nftnl_expr *e)
 {
@@ -163,5 +178,6 @@ struct expr_ops expr_ops_masq = {
 	.get		= nftnl_expr_masq_get,
 	.parse		= nftnl_expr_masq_parse,
 	.build		= nftnl_expr_masq_build,
+	.byteorder	= nftnl_expr_masq_byteorder,
 	.snprintf	= nftnl_expr_masq_snprintf,
 };
diff --git a/src/expr/meta.c b/src/expr/meta.c
index 34fbb9bb63c03..deb14e5cb054d 100644
--- a/src/expr/meta.c
+++ b/src/expr/meta.c
@@ -191,6 +191,33 @@ static inline int str2meta_key(const char *str)
 	return -1;
 }
 
+static void nftnl_expr_meta_byteorder(struct nftnl_byteorder_ctx *ctx,
+				      struct nftnl_expr *e)
+{
+	struct nftnl_expr_meta *meta = nftnl_expr_data(e);
+
+
+	switch (meta->key) {
+	case NFT_META_PROTOCOL:
+	case NFT_META_IIFNAME:
+	case NFT_META_OIFNAME:
+	case NFT_META_BRI_IIFNAME:
+	case NFT_META_BRI_OIFNAME:
+	case NFT_META_PRANDOM:
+	case NFT_META_BRI_IIFVPROTO:
+	case NFT_META_SDIFNAME:
+		e->byteorder = NFTNL_BYTEORDER_NETWORK;
+		break;
+	default:
+		e->byteorder = NFTNL_BYTEORDER_HOST;
+	}
+
+	if (e->flags & (1 << NFTNL_EXPR_META_SREG))
+		nftnl_reg_byteorder_resolve(ctx, meta->sreg, e->byteorder);
+	if (e->flags & (1 << NFTNL_EXPR_META_DREG))
+		nftnl_reg_byteorder_set(ctx, meta->dreg, e->byteorder);
+}
+
 static int
 nftnl_expr_meta_snprintf(char *buf, size_t len,
 			 uint32_t flags, const struct nftnl_expr *e)
@@ -216,5 +243,6 @@ struct expr_ops expr_ops_meta = {
 	.get		= nftnl_expr_meta_get,
 	.parse		= nftnl_expr_meta_parse,
 	.build		= nftnl_expr_meta_build,
+	.byteorder	= nftnl_expr_meta_byteorder,
 	.snprintf	= nftnl_expr_meta_snprintf,
 };
diff --git a/src/expr/nat.c b/src/expr/nat.c
index 0a9cdd7f65f8f..785ceb20a92bf 100644
--- a/src/expr/nat.c
+++ b/src/expr/nat.c
@@ -220,6 +220,27 @@ static inline int nftnl_str2nat(const char *nat)
 	}
 }
 
+static void
+nftnl_expr_nat_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_nat *nat = nftnl_expr_data(e);
+
+	if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN))
+		nftnl_reg_byteorder_resolve(ctx, nat->sreg_addr_min,
+					    NFTNL_BYTEORDER_NETWORK);
+	if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX))
+		nftnl_reg_byteorder_resolve(ctx, nat->sreg_addr_max,
+					    NFTNL_BYTEORDER_NETWORK);
+	if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN))
+		nftnl_reg_byteorder_resolve(ctx, nat->sreg_proto_min,
+					    NFTNL_BYTEORDER_NETWORK);
+	if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX))
+		nftnl_reg_byteorder_resolve(ctx, nat->sreg_proto_max,
+					    NFTNL_BYTEORDER_NETWORK);
+
+	e->byteorder = NFTNL_BYTEORDER_NETWORK;
+}
+
 static int
 nftnl_expr_nat_snprintf(char *buf, size_t remain,
 			uint32_t flags, const struct nftnl_expr *e)
@@ -274,5 +295,6 @@ struct expr_ops expr_ops_nat = {
 	.get		= nftnl_expr_nat_get,
 	.parse		= nftnl_expr_nat_parse,
 	.build		= nftnl_expr_nat_build,
+	.byteorder	= nftnl_expr_nat_byteorder,
 	.snprintf	= nftnl_expr_nat_snprintf,
 };
diff --git a/src/expr/numgen.c b/src/expr/numgen.c
index 159dfeca3618b..dfbeeaf1b172a 100644
--- a/src/expr/numgen.c
+++ b/src/expr/numgen.c
@@ -142,6 +142,17 @@ nftnl_expr_ng_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return ret;
 }
 
+static void
+nftnl_expr_ng_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_ng *ng = nftnl_expr_data(e);
+
+	e->byteorder = NFTNL_BYTEORDER_HOST;
+
+	if (e->flags & (1 << NFTNL_EXPR_NG_DREG))
+		nftnl_reg_byteorder_set(ctx, ng->dreg, e->byteorder);
+}
+
 static int
 nftnl_expr_ng_snprintf(char *buf, size_t remain,
 		       uint32_t flags, const struct nftnl_expr *e)
@@ -180,5 +191,6 @@ struct expr_ops expr_ops_ng = {
 	.get		= nftnl_expr_ng_get,
 	.parse		= nftnl_expr_ng_parse,
 	.build		= nftnl_expr_ng_build,
+	.byteorder	= nftnl_expr_ng_byteorder,
 	.snprintf	= nftnl_expr_ng_snprintf,
 };
diff --git a/src/expr/osf.c b/src/expr/osf.c
index 215a681a97aae..b2e4294877c05 100644
--- a/src/expr/osf.c
+++ b/src/expr/osf.c
@@ -124,6 +124,17 @@ nftnl_expr_osf_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return 0;
 }
 
+static void
+nftnl_expr_osf_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_osf *osf = nftnl_expr_data(e);
+
+	e->byteorder = NFTNL_BYTEORDER_NETWORK;
+
+	if (e->flags & (1 << NFTNL_EXPR_OSF_DREG))
+                nftnl_reg_byteorder_set(ctx, osf->dreg, e->byteorder);
+}
+
 static int
 nftnl_expr_osf_snprintf(char *buf, size_t len,
 			uint32_t flags, const struct nftnl_expr *e)
@@ -147,5 +158,6 @@ struct expr_ops expr_ops_osf = {
 	.get		= nftnl_expr_osf_get,
 	.parse		= nftnl_expr_osf_parse,
 	.build		= nftnl_expr_osf_build,
+	.byteorder	= nftnl_expr_osf_byteorder,
 	.snprintf	= nftnl_expr_osf_snprintf,
 };
diff --git a/src/expr/payload.c b/src/expr/payload.c
index 82747ec8994f7..84764e837a965 100644
--- a/src/expr/payload.c
+++ b/src/expr/payload.c
@@ -232,6 +232,19 @@ static inline int nftnl_str2base(const char *base)
 	}
 }
 
+static void
+nftnl_expr_payload_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_payload *payload = nftnl_expr_data(e);
+
+	e->byteorder = NFTNL_BYTEORDER_NETWORK;
+
+	if (payload->sreg)
+		nftnl_reg_byteorder_resolve(ctx, payload->sreg, e->byteorder);
+	else
+                nftnl_reg_byteorder_set(ctx, payload->dreg, e->byteorder);
+}
+
 static int
 nftnl_expr_payload_snprintf(char *buf, size_t len,
 			    uint32_t flags, const struct nftnl_expr *e)
@@ -259,5 +272,6 @@ struct expr_ops expr_ops_payload = {
 	.get		= nftnl_expr_payload_get,
 	.parse		= nftnl_expr_payload_parse,
 	.build		= nftnl_expr_payload_build,
+	.byteorder	= nftnl_expr_payload_byteorder,
 	.snprintf	= nftnl_expr_payload_snprintf,
 };
diff --git a/src/expr/queue.c b/src/expr/queue.c
index 8f70977f7de85..1a65c8ad6484a 100644
--- a/src/expr/queue.c
+++ b/src/expr/queue.c
@@ -143,6 +143,17 @@ nftnl_expr_queue_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return 0;
 }
 
+static void
+nftnl_expr_queue_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_queue *queue = nftnl_expr_data(e);
+
+	e->byteorder = NFTNL_BYTEORDER_HOST;
+
+	if (e->flags & (1 << NFTNL_EXPR_QUEUE_SREG_QNUM))
+                nftnl_reg_byteorder_resolve(ctx, queue->sreg_qnum, e->byteorder);
+}
+
 static int
 nftnl_expr_queue_snprintf(char *buf, size_t remain,
 			  uint32_t flags, const struct nftnl_expr *e)
@@ -193,5 +204,6 @@ struct expr_ops expr_ops_queue = {
 	.get		= nftnl_expr_queue_get,
 	.parse		= nftnl_expr_queue_parse,
 	.build		= nftnl_expr_queue_build,
+	.byteorder	= nftnl_expr_queue_byteorder,
 	.snprintf	= nftnl_expr_queue_snprintf,
 };
diff --git a/src/expr/range.c b/src/expr/range.c
index f76843a8afd0c..ab4e2e70d8d01 100644
--- a/src/expr/range.c
+++ b/src/expr/range.c
@@ -184,6 +184,12 @@ static inline int nftnl_str2range(const char *op)
 	}
 }
 
+static void nftnl_expr_range_byteorder(struct nftnl_byteorder_ctx *ctx,
+				       struct nftnl_expr *e)
+{
+	e->byteorder = NFTNL_BYTEORDER_NETWORK;
+}
+
 static int nftnl_expr_range_snprintf(char *buf, size_t remain,
 				     uint32_t flags, const struct nftnl_expr *e)
 {
@@ -195,11 +201,11 @@ static int nftnl_expr_range_snprintf(char *buf, size_t remain,
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = nftnl_data_reg_snprintf(buf + offset, remain, &range->data_from,
-				      0, DATA_VALUE);
+				      0, DATA_VALUE, e->byteorder);
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = nftnl_data_reg_snprintf(buf + offset, remain, &range->data_to,
-				      0, DATA_VALUE);
+				      0, DATA_VALUE, e->byteorder);
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	return offset;
@@ -213,5 +219,6 @@ struct expr_ops expr_ops_range = {
 	.get		= nftnl_expr_range_get,
 	.parse		= nftnl_expr_range_parse,
 	.build		= nftnl_expr_range_build,
+	.byteorder	= nftnl_expr_range_byteorder,
 	.snprintf	= nftnl_expr_range_snprintf,
 };
diff --git a/src/expr/redir.c b/src/expr/redir.c
index 4f56cb4302b30..3c1ebc13909e5 100644
--- a/src/expr/redir.c
+++ b/src/expr/redir.c
@@ -131,6 +131,21 @@ nftnl_expr_redir_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return 0;
 }
 
+static void
+nftnl_expr_redir_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_redir *redir = nftnl_expr_data(e);
+
+	if (e->flags & (1 << NFTNL_EXPR_REDIR_REG_PROTO_MIN))
+		nftnl_reg_byteorder_resolve(ctx, redir->sreg_proto_min,
+					    NFTNL_BYTEORDER_NETWORK);
+	if (e->flags & (1 << NFTNL_EXPR_REDIR_REG_PROTO_MAX))
+		nftnl_reg_byteorder_resolve(ctx, redir->sreg_proto_max,
+					    NFTNL_BYTEORDER_NETWORK);
+
+	e->byteorder = NFTNL_BYTEORDER_NETWORK;
+}
+
 static int
 nftnl_expr_redir_snprintf(char *buf, size_t remain,
 			  uint32_t flags, const struct nftnl_expr *e)
@@ -167,5 +182,6 @@ struct expr_ops expr_ops_redir = {
 	.get		= nftnl_expr_redir_get,
 	.parse		= nftnl_expr_redir_parse,
 	.build		= nftnl_expr_redir_build,
+	.byteorder	= nftnl_expr_redir_byteorder,
 	.snprintf	= nftnl_expr_redir_snprintf,
 };
diff --git a/src/expr/rt.c b/src/expr/rt.c
index 1ad9b2ad4043f..bd8b2a91948ee 100644
--- a/src/expr/rt.c
+++ b/src/expr/rt.c
@@ -112,6 +112,24 @@ nftnl_expr_rt_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return 0;
 }
 
+static void nftnl_expr_rt_byteorder(struct nftnl_byteorder_ctx *ctx,
+				    struct nftnl_expr *e)
+{
+	struct nftnl_expr_rt *rt = nftnl_expr_data(e);
+
+	switch (rt->key) {
+	case NFT_RT_NEXTHOP4:
+	case NFT_RT_NEXTHOP6:
+		e->byteorder = NFTNL_BYTEORDER_NETWORK;
+		break;
+	default:
+		e->byteorder = NFTNL_BYTEORDER_HOST;
+	}
+
+	if (e->flags & (1 << NFTNL_EXPR_RT_DREG))
+		nftnl_reg_byteorder_set(ctx, rt->dreg, e->byteorder);
+}
+
 static const char *rt_key2str_array[NFT_RT_MAX + 1] = {
 	[NFT_RT_CLASSID]	= "classid",
 	[NFT_RT_NEXTHOP4]	= "nexthop4",
@@ -162,5 +180,6 @@ struct expr_ops expr_ops_rt = {
 	.get		= nftnl_expr_rt_get,
 	.parse		= nftnl_expr_rt_parse,
 	.build		= nftnl_expr_rt_build,
+	.byteorder	= nftnl_expr_rt_byteorder,
 	.snprintf	= nftnl_expr_rt_snprintf,
 };
diff --git a/src/expr/socket.c b/src/expr/socket.c
index 02d86f8ac57c0..dae9ea22bd24f 100644
--- a/src/expr/socket.c
+++ b/src/expr/socket.c
@@ -126,6 +126,17 @@ nftnl_expr_socket_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return 0;
 }
 
+static void
+nftnl_expr_socket_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_socket *socket = nftnl_expr_data(e);
+
+	e->byteorder = NFTNL_BYTEORDER_HOST;
+
+	if (e->flags & (1 << NFTNL_EXPR_SOCKET_DREG))
+                nftnl_reg_byteorder_set(ctx, socket->dreg, e->byteorder);
+}
+
 static const char *socket_key2str_array[NFT_SOCKET_MAX + 1] = {
 	[NFT_SOCKET_TRANSPARENT] = "transparent",
 	[NFT_SOCKET_MARK] = "mark",
@@ -165,5 +176,6 @@ struct expr_ops expr_ops_socket = {
 	.get		= nftnl_expr_socket_get,
 	.parse		= nftnl_expr_socket_parse,
 	.build		= nftnl_expr_socket_build,
+	.byteorder	= nftnl_expr_socket_byteorder,
 	.snprintf	= nftnl_expr_socket_snprintf,
 };
diff --git a/src/expr/tproxy.c b/src/expr/tproxy.c
index d3ee8f89b6db3..ef3e20569c1cf 100644
--- a/src/expr/tproxy.c
+++ b/src/expr/tproxy.c
@@ -134,6 +134,19 @@ nftnl_expr_tproxy_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
 				 htonl(tproxy->sreg_port));
 }
 
+static void nftnl_expr_tproxy_byteorder(struct nftnl_byteorder_ctx *ctx,
+				        struct nftnl_expr *e)
+{
+	struct nftnl_expr_tproxy *t = nftnl_expr_data(e);
+
+	e->byteorder = NFTNL_BYTEORDER_NETWORK;
+
+	if (e->flags & (1 << NFTNL_EXPR_TPROXY_REG_ADDR))
+		nftnl_reg_byteorder_resolve(ctx, t->sreg_addr, e->byteorder);
+	if (e->flags & (1 << NFTNL_EXPR_TPROXY_REG_PORT))
+		nftnl_reg_byteorder_resolve(ctx, t->sreg_port, e->byteorder);
+}
+
 static int
 nftnl_expr_tproxy_snprintf(char *buf, size_t remain,
 			uint32_t flags, const struct nftnl_expr *e)
@@ -170,5 +183,6 @@ struct expr_ops expr_ops_tproxy = {
 	.get		= nftnl_expr_tproxy_get,
 	.parse		= nftnl_expr_tproxy_parse,
 	.build		= nftnl_expr_tproxy_build,
+	.byteorder	= nftnl_expr_tproxy_byteorder,
 	.snprintf	= nftnl_expr_tproxy_snprintf,
 };
diff --git a/src/expr/tunnel.c b/src/expr/tunnel.c
index 1460fd26b0fbc..94a6c9bb4add2 100644
--- a/src/expr/tunnel.c
+++ b/src/expr/tunnel.c
@@ -111,6 +111,17 @@ nftnl_expr_tunnel_parse(struct nftnl_expr *e, struct nlattr *attr)
 	return 0;
 }
 
+static void
+nftnl_expr_tunnel_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_tunnel *tunnel = nftnl_expr_data(e);
+
+	e->byteorder = NFTNL_BYTEORDER_HOST;
+
+	if (e->flags & (1 << NFTNL_EXPR_TUNNEL_DREG))
+                nftnl_reg_byteorder_set(ctx, tunnel->dreg, e->byteorder);
+}
+
 static const char *tunnel_key2str_array[NFT_TUNNEL_MAX + 1] = {
 	[NFT_TUNNEL_PATH]	= "path",
 	[NFT_TUNNEL_ID]		= "id",
@@ -145,5 +156,6 @@ struct expr_ops expr_ops_tunnel = {
 	.get		= nftnl_expr_tunnel_get,
 	.parse		= nftnl_expr_tunnel_parse,
 	.build		= nftnl_expr_tunnel_build,
+	.byteorder	= nftnl_expr_tunnel_byteorder,
 	.snprintf	= nftnl_expr_tunnel_snprintf,
 };
diff --git a/src/expr/xfrm.c b/src/expr/xfrm.c
index c81d14d638dcd..3134b076f042e 100644
--- a/src/expr/xfrm.c
+++ b/src/expr/xfrm.c
@@ -171,6 +171,23 @@ static const char *xfrmdir2str(uint8_t dir)
 	return xfrmdir2str_array[dir];
 }
 
+static void
+nftnl_expr_xfrm_byteorder(struct nftnl_byteorder_ctx *ctx, struct nftnl_expr *e)
+{
+	struct nftnl_expr_xfrm *x = nftnl_expr_data(e);
+
+	switch (x->key) {
+	case NFT_XFRM_KEY_REQID:
+		e->byteorder = NFTNL_BYTEORDER_HOST;
+		break;
+	default:
+		e->byteorder = NFTNL_BYTEORDER_NETWORK;
+	}
+
+	if (e->flags & (1 << NFTNL_EXPR_XFRM_DREG))
+                nftnl_reg_byteorder_set(ctx, x->dreg, e->byteorder);
+}
+
 static int
 nftnl_expr_xfrm_snprintf(char *buf, size_t remain,
 			 uint32_t flags, const struct nftnl_expr *e)
@@ -196,5 +213,6 @@ struct expr_ops expr_ops_xfrm = {
 	.get		= nftnl_expr_xfrm_get,
 	.parse		= nftnl_expr_xfrm_parse,
 	.build		= nftnl_expr_xfrm_build,
+	.byteorder	= nftnl_expr_xfrm_byteorder,
 	.snprintf	= nftnl_expr_xfrm_snprintf,
 };
diff --git a/src/rule.c b/src/rule.c
index 0bb1c2a0583c1..9f1caa6feb57e 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -549,6 +549,7 @@ static int nftnl_rule_snprintf_default(char *buf, size_t remain,
 				       const struct nftnl_rule *r,
 				       uint32_t type, uint32_t flags)
 {
+	struct nftnl_byteorder_ctx ctx = {};
 	struct nftnl_expr *expr;
 	int ret, offset = 0, i;
 	const char *sep = "";
@@ -603,6 +604,12 @@ static int nftnl_rule_snprintf_default(char *buf, size_t remain,
 	ret = snprintf(buf + offset, remain, "\n");
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
+	list_for_each_entry(expr, &r->expr_list, head) {
+		if (!expr->ops->byteorder)
+			continue;
+		expr->ops->byteorder(&ctx, expr);
+	}
+
 	list_for_each_entry(expr, &r->expr_list, head) {
 		ret = snprintf(buf + offset, remain, "  [ %s ", expr->ops->name);
 		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
diff --git a/src/set_elem.c b/src/set_elem.c
index 12eadce1f8e0c..9b18f4def6c47 100644
--- a/src/set_elem.c
+++ b/src/set_elem.c
@@ -708,7 +708,8 @@ int nftnl_set_elem_snprintf_default(char *buf, size_t remain,
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key,
-				      DATA_F_NOPFX, DATA_VALUE);
+				      DATA_F_NOPFX, DATA_VALUE,
+				      NFTNL_BYTEORDER_UNKNOWN);
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	if (e->flags & (1 << NFTNL_SET_ELEM_KEY_END)) {
@@ -716,7 +717,8 @@ int nftnl_set_elem_snprintf_default(char *buf, size_t remain,
 		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 		ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key_end,
-					      DATA_F_NOPFX, DATA_VALUE);
+					      DATA_F_NOPFX, DATA_VALUE,
+					      NFTNL_BYTEORDER_UNKNOWN);
 		SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 	}
 
@@ -727,7 +729,8 @@ int nftnl_set_elem_snprintf_default(char *buf, size_t remain,
 		dregtype = DATA_VERDICT;
 
 	ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->data,
-				      DATA_F_NOPFX, dregtype);
+				      DATA_F_NOPFX, dregtype,
+				      NFTNL_BYTEORDER_UNKNOWN);
 	SNPRINTF_BUFFER_SIZE(ret, remain, offset);
 
 	ret = snprintf(buf + offset, remain, "%u [end]", e->set_elem_flags);
-- 
2.33.0




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux