import UBI nftables-1.1.1-6.el10_1
This commit is contained in:
parent
2cbde3b3db
commit
5d448803a1
@ -1,4 +1,4 @@
|
||||
From b3c1312b5815b004614d79eae2ad731c6883ce6f Mon Sep 17 00:00:00 2001
|
||||
From 75c95b2f59fb09c6375ca1e10277af9d0641e71d Mon Sep 17 00:00:00 2001
|
||||
From: Florian Westphal <fw@strlen.de>
|
||||
Date: Wed, 22 Jan 2025 10:18:04 +0100
|
||||
Subject: [PATCH] evaluate: allow to re-use existing metered set
|
||||
@ -41,7 +41,7 @@ Signed-off-by: Eric Garver <egarver@redhat.com>
|
||||
create mode 100755 tests/shell/testcases/sets/meter_set_reuse
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 593a0140e92a..c9cbaa6ae648 100644
|
||||
index 593a014..c9cbaa6 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -3338,7 +3338,7 @@ static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
|
||||
@ -114,7 +114,7 @@ index 593a0140e92a..c9cbaa6ae648 100644
|
||||
if (stmt_evaluate(ctx, stmt->meter.stmt) < 0)
|
||||
diff --git a/tests/shell/testcases/sets/dumps/meter_set_reuse.json-nft b/tests/shell/testcases/sets/dumps/meter_set_reuse.json-nft
|
||||
new file mode 100644
|
||||
index 000000000000..ab4ac06184d0
|
||||
index 0000000..ab4ac06
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/sets/dumps/meter_set_reuse.json-nft
|
||||
@@ -0,0 +1,105 @@
|
||||
@ -225,7 +225,7 @@ index 000000000000..ab4ac06184d0
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/sets/dumps/meter_set_reuse.nft b/tests/shell/testcases/sets/dumps/meter_set_reuse.nft
|
||||
new file mode 100644
|
||||
index 000000000000..f911acaffb85
|
||||
index 0000000..f911aca
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/sets/dumps/meter_set_reuse.nft
|
||||
@@ -0,0 +1,11 @@
|
||||
@ -242,7 +242,7 @@ index 000000000000..f911acaffb85
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/sets/meter_set_reuse b/tests/shell/testcases/sets/meter_set_reuse
|
||||
new file mode 100755
|
||||
index 000000000000..94eccc1a7b82
|
||||
index 0000000..94eccc1
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/sets/meter_set_reuse
|
||||
@@ -0,0 +1,20 @@
|
||||
@ -266,6 +266,3 @@ index 000000000000..94eccc1a7b82
|
||||
+
|
||||
+# This re-add should work.
|
||||
+addrule
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
||||
807
0015-src-split-monitor-trace-code-into-new-trace.c.patch
Normal file
807
0015-src-split-monitor-trace-code-into-new-trace.c.patch
Normal file
@ -0,0 +1,807 @@
|
||||
From bb46381b2d378729d709480806c9522aaa32deeb Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 15 Jul 2025 22:50:32 +0200
|
||||
Subject: [PATCH] src: split monitor trace code into new trace.c
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-102994
|
||||
Upstream Status: nftables commit 8e03d59b5aa46b960454b4fd30541cee77125f77
|
||||
|
||||
commit 8e03d59b5aa46b960454b4fd30541cee77125f77
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Jul 7 11:47:13 2025 +0200
|
||||
|
||||
src: split monitor trace code into new trace.c
|
||||
|
||||
Preparation patch to avoid putting more trace functionality into
|
||||
netlink.c.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
Makefile.am | 1 +
|
||||
include/netlink.h | 5 -
|
||||
include/trace.h | 8 ++
|
||||
src/monitor.c | 2 +-
|
||||
src/netlink.c | 332 -------------------------------------------
|
||||
src/trace.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
6 files changed, 363 insertions(+), 338 deletions(-)
|
||||
create mode 100644 include/trace.h
|
||||
create mode 100644 src/trace.c
|
||||
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index fb64105..ba09e7f 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -220,6 +220,7 @@ src_libnftables_la_SOURCES = \
|
||||
src/misspell.c \
|
||||
src/mnl.c \
|
||||
src/monitor.c \
|
||||
+ src/trace.c \
|
||||
src/netlink.c \
|
||||
src/netlink_delinearize.c \
|
||||
src/netlink_linearize.c \
|
||||
diff --git a/include/netlink.h b/include/netlink.h
|
||||
index e9667a2..609f213 100644
|
||||
--- a/include/netlink.h
|
||||
+++ b/include/netlink.h
|
||||
@@ -227,11 +227,6 @@ struct ruleset_parse {
|
||||
struct cmd *cmd;
|
||||
};
|
||||
|
||||
-struct nftnl_parse_ctx;
|
||||
-
|
||||
-int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
|
||||
- struct netlink_mon_handler *monh);
|
||||
-
|
||||
enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype);
|
||||
|
||||
void netlink_linearize_init(struct netlink_linearize_ctx *lctx,
|
||||
diff --git a/include/trace.h b/include/trace.h
|
||||
new file mode 100644
|
||||
index 0000000..ebebb47
|
||||
--- /dev/null
|
||||
+++ b/include/trace.h
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef NFTABLES_TRACE_H
|
||||
+#define NFTABLES_TRACE_H
|
||||
+#include <linux/netlink.h>
|
||||
+
|
||||
+struct netlink_mon_handler;
|
||||
+int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
|
||||
+ struct netlink_mon_handler *monh);
|
||||
+#endif /* NFTABLES_TRACE_H */
|
||||
diff --git a/src/monitor.c b/src/monitor.c
|
||||
index a787db8..01325c9 100644
|
||||
--- a/src/monitor.c
|
||||
+++ b/src/monitor.c
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <libnftnl/table.h>
|
||||
-#include <libnftnl/trace.h>
|
||||
#include <libnftnl/chain.h>
|
||||
#include <libnftnl/expr.h>
|
||||
#include <libnftnl/object.h>
|
||||
@@ -32,6 +31,7 @@
|
||||
#include <nftables.h>
|
||||
#include <netlink.h>
|
||||
#include <mnl.h>
|
||||
+#include <trace.h>
|
||||
#include <expression.h>
|
||||
#include <statement.h>
|
||||
#include <gmputil.h>
|
||||
diff --git a/src/netlink.c b/src/netlink.c
|
||||
index 25ee341..2ced863 100644
|
||||
--- a/src/netlink.c
|
||||
+++ b/src/netlink.c
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <libnftnl/table.h>
|
||||
-#include <libnftnl/trace.h>
|
||||
#include <libnftnl/chain.h>
|
||||
#include <libnftnl/expr.h>
|
||||
#include <libnftnl/object.h>
|
||||
@@ -41,7 +40,6 @@
|
||||
#include <gmputil.h>
|
||||
#include <utils.h>
|
||||
#include <erec.h>
|
||||
-#include <iface.h>
|
||||
|
||||
#define nft_mon_print(monh, ...) nft_print(&monh->ctx->nft->output, __VA_ARGS__)
|
||||
|
||||
@@ -1859,333 +1857,3 @@ int netlink_list_flowtables(struct netlink_ctx *ctx, const struct handle *h)
|
||||
nftnl_flowtable_list_free(flowtable_cache);
|
||||
return err;
|
||||
}
|
||||
-
|
||||
-static void trace_print_hdr(const struct nftnl_trace *nlt,
|
||||
- struct output_ctx *octx)
|
||||
-{
|
||||
- nft_print(octx, "trace id %08x %s ",
|
||||
- nftnl_trace_get_u32(nlt, NFTNL_TRACE_ID),
|
||||
- family2str(nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY)));
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_TABLE))
|
||||
- nft_print(octx, "%s ",
|
||||
- nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE));
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CHAIN))
|
||||
- nft_print(octx, "%s ",
|
||||
- nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN));
|
||||
-}
|
||||
-
|
||||
-static void trace_print_expr(const struct nftnl_trace *nlt, unsigned int attr,
|
||||
- struct expr *lhs, struct output_ctx *octx)
|
||||
-{
|
||||
- struct expr *rhs, *rel;
|
||||
- const void *data;
|
||||
- uint32_t len;
|
||||
-
|
||||
- data = nftnl_trace_get_data(nlt, attr, &len);
|
||||
- rhs = constant_expr_alloc(&netlink_location,
|
||||
- lhs->dtype, lhs->byteorder,
|
||||
- len * BITS_PER_BYTE, data);
|
||||
- rel = relational_expr_alloc(&netlink_location, OP_EQ, lhs, rhs);
|
||||
-
|
||||
- expr_print(rel, octx);
|
||||
- nft_print(octx, " ");
|
||||
- expr_free(rel);
|
||||
-}
|
||||
-
|
||||
-static void trace_print_verdict(const struct nftnl_trace *nlt,
|
||||
- struct output_ctx *octx)
|
||||
-{
|
||||
- struct expr *chain_expr = NULL;
|
||||
- const char *chain = NULL;
|
||||
- unsigned int verdict;
|
||||
- struct expr *expr;
|
||||
-
|
||||
- verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_VERDICT);
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) {
|
||||
- chain = xstrdup(nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET));
|
||||
- chain_expr = constant_expr_alloc(&netlink_location,
|
||||
- &string_type,
|
||||
- BYTEORDER_HOST_ENDIAN,
|
||||
- strlen(chain) * BITS_PER_BYTE,
|
||||
- chain);
|
||||
- }
|
||||
- expr = verdict_expr_alloc(&netlink_location, verdict, chain_expr);
|
||||
-
|
||||
- nft_print(octx, "verdict ");
|
||||
- expr_print(expr, octx);
|
||||
- expr_free(expr);
|
||||
-}
|
||||
-
|
||||
-static void trace_print_policy(const struct nftnl_trace *nlt,
|
||||
- struct output_ctx *octx)
|
||||
-{
|
||||
- unsigned int policy;
|
||||
- struct expr *expr;
|
||||
-
|
||||
- policy = nftnl_trace_get_u32(nlt, NFTNL_TRACE_POLICY);
|
||||
-
|
||||
- expr = verdict_expr_alloc(&netlink_location, policy, NULL);
|
||||
-
|
||||
- nft_print(octx, "policy ");
|
||||
- expr_print(expr, octx);
|
||||
- expr_free(expr);
|
||||
-}
|
||||
-
|
||||
-static struct rule *trace_lookup_rule(const struct nftnl_trace *nlt,
|
||||
- uint64_t rule_handle,
|
||||
- struct nft_cache *cache)
|
||||
-{
|
||||
- struct chain *chain;
|
||||
- struct table *table;
|
||||
- struct handle h;
|
||||
-
|
||||
- h.family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
|
||||
- h.table.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
|
||||
- h.chain.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN);
|
||||
-
|
||||
- if (!h.table.name)
|
||||
- return NULL;
|
||||
-
|
||||
- table = table_cache_find(&cache->table_cache, h.table.name, h.family);
|
||||
- if (!table)
|
||||
- return NULL;
|
||||
-
|
||||
- chain = chain_cache_find(table, h.chain.name);
|
||||
- if (!chain)
|
||||
- return NULL;
|
||||
-
|
||||
- return rule_lookup(chain, rule_handle);
|
||||
-}
|
||||
-
|
||||
-static void trace_print_rule(const struct nftnl_trace *nlt,
|
||||
- struct output_ctx *octx, struct nft_cache *cache)
|
||||
-{
|
||||
- uint64_t rule_handle;
|
||||
- struct rule *rule;
|
||||
-
|
||||
- rule_handle = nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE);
|
||||
- rule = trace_lookup_rule(nlt, rule_handle, cache);
|
||||
-
|
||||
- trace_print_hdr(nlt, octx);
|
||||
-
|
||||
- if (rule) {
|
||||
- nft_print(octx, "rule ");
|
||||
- rule_print(rule, octx);
|
||||
- } else {
|
||||
- nft_print(octx, "unknown rule handle %" PRIu64, rule_handle);
|
||||
- }
|
||||
-
|
||||
- nft_print(octx, " (");
|
||||
- trace_print_verdict(nlt, octx);
|
||||
- nft_print(octx, ")\n");
|
||||
-}
|
||||
-
|
||||
-static void trace_gen_stmts(struct list_head *stmts,
|
||||
- struct proto_ctx *ctx, struct payload_dep_ctx *pctx,
|
||||
- const struct nftnl_trace *nlt, unsigned int attr,
|
||||
- enum proto_bases base)
|
||||
-{
|
||||
- struct list_head unordered = LIST_HEAD_INIT(unordered);
|
||||
- struct list_head list;
|
||||
- struct expr *rel, *lhs, *rhs, *tmp, *nexpr;
|
||||
- struct stmt *stmt;
|
||||
- const struct proto_desc *desc;
|
||||
- const void *hdr;
|
||||
- uint32_t hlen;
|
||||
- unsigned int n;
|
||||
-
|
||||
- if (!nftnl_trace_is_set(nlt, attr))
|
||||
- return;
|
||||
- hdr = nftnl_trace_get_data(nlt, attr, &hlen);
|
||||
-
|
||||
- lhs = payload_expr_alloc(&netlink_location, NULL, 0);
|
||||
- payload_init_raw(lhs, base, 0, hlen * BITS_PER_BYTE);
|
||||
- rhs = constant_expr_alloc(&netlink_location,
|
||||
- &invalid_type, BYTEORDER_INVALID,
|
||||
- hlen * BITS_PER_BYTE, hdr);
|
||||
-
|
||||
-restart:
|
||||
- init_list_head(&list);
|
||||
- payload_expr_expand(&list, lhs, ctx);
|
||||
- expr_free(lhs);
|
||||
-
|
||||
- desc = NULL;
|
||||
- list_for_each_entry_safe(lhs, nexpr, &list, list) {
|
||||
- if (desc && desc != ctx->protocol[base].desc) {
|
||||
- /* Chained protocols */
|
||||
- lhs->payload.offset = 0;
|
||||
- if (ctx->protocol[base].desc == NULL)
|
||||
- break;
|
||||
- goto restart;
|
||||
- }
|
||||
-
|
||||
- tmp = constant_expr_splice(rhs, lhs->len);
|
||||
- expr_set_type(tmp, lhs->dtype, lhs->byteorder);
|
||||
- if (tmp->byteorder == BYTEORDER_HOST_ENDIAN)
|
||||
- mpz_switch_byteorder(tmp->value, tmp->len / BITS_PER_BYTE);
|
||||
-
|
||||
- /* Skip unknown and filtered expressions */
|
||||
- desc = lhs->payload.desc;
|
||||
- if (lhs->dtype == &invalid_type ||
|
||||
- lhs->payload.tmpl == &proto_unknown_template ||
|
||||
- desc->checksum_key == payload_hdr_field(lhs) ||
|
||||
- desc->format.filter & (1 << payload_hdr_field(lhs))) {
|
||||
- expr_free(lhs);
|
||||
- expr_free(tmp);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- rel = relational_expr_alloc(&lhs->location, OP_EQ, lhs, tmp);
|
||||
- stmt = expr_stmt_alloc(&rel->location, rel);
|
||||
- list_add_tail(&stmt->list, &unordered);
|
||||
-
|
||||
- desc = ctx->protocol[base].desc;
|
||||
- relational_expr_pctx_update(ctx, rel);
|
||||
- }
|
||||
-
|
||||
- expr_free(rhs);
|
||||
-
|
||||
- n = 0;
|
||||
-next:
|
||||
- list_for_each_entry(stmt, &unordered, list) {
|
||||
- enum proto_bases b = base;
|
||||
-
|
||||
- rel = stmt->expr;
|
||||
- lhs = rel->left;
|
||||
-
|
||||
- /* Move statements to result list in defined order */
|
||||
- desc = lhs->payload.desc;
|
||||
- if (desc->format.order[n] &&
|
||||
- desc->format.order[n] != payload_hdr_field(lhs))
|
||||
- continue;
|
||||
-
|
||||
- list_move_tail(&stmt->list, stmts);
|
||||
- n++;
|
||||
-
|
||||
- if (payload_is_stacked(desc, rel))
|
||||
- b--;
|
||||
-
|
||||
- /* Don't strip 'icmp type' from payload dump. */
|
||||
- if (pctx->icmp_type == 0)
|
||||
- payload_dependency_kill(pctx, lhs, ctx->family);
|
||||
- if (lhs->flags & EXPR_F_PROTOCOL)
|
||||
- payload_dependency_store(pctx, stmt, b);
|
||||
-
|
||||
- goto next;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static void trace_print_packet(const struct nftnl_trace *nlt,
|
||||
- struct output_ctx *octx)
|
||||
-{
|
||||
- struct list_head stmts = LIST_HEAD_INIT(stmts);
|
||||
- const struct proto_desc *ll_desc;
|
||||
- struct payload_dep_ctx pctx = {};
|
||||
- struct proto_ctx ctx;
|
||||
- uint16_t dev_type;
|
||||
- uint32_t nfproto;
|
||||
- struct stmt *stmt, *next;
|
||||
-
|
||||
- trace_print_hdr(nlt, octx);
|
||||
-
|
||||
- nft_print(octx, "packet: ");
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_IIF))
|
||||
- trace_print_expr(nlt, NFTNL_TRACE_IIF,
|
||||
- meta_expr_alloc(&netlink_location,
|
||||
- NFT_META_IIF), octx);
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_OIF))
|
||||
- trace_print_expr(nlt, NFTNL_TRACE_OIF,
|
||||
- meta_expr_alloc(&netlink_location,
|
||||
- NFT_META_OIF), octx);
|
||||
-
|
||||
- proto_ctx_init(&ctx, nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY), 0, false);
|
||||
- ll_desc = ctx.protocol[PROTO_BASE_LL_HDR].desc;
|
||||
- if ((ll_desc == &proto_inet || ll_desc == &proto_netdev) &&
|
||||
- nftnl_trace_is_set(nlt, NFTNL_TRACE_NFPROTO)) {
|
||||
- nfproto = nftnl_trace_get_u32(nlt, NFTNL_TRACE_NFPROTO);
|
||||
-
|
||||
- proto_ctx_update(&ctx, PROTO_BASE_LL_HDR, &netlink_location, NULL);
|
||||
- proto_ctx_update(&ctx, PROTO_BASE_NETWORK_HDR, &netlink_location,
|
||||
- proto_find_upper(ll_desc, nfproto));
|
||||
- }
|
||||
- if (ctx.protocol[PROTO_BASE_LL_HDR].desc == NULL &&
|
||||
- nftnl_trace_is_set(nlt, NFTNL_TRACE_IIFTYPE)) {
|
||||
- dev_type = nftnl_trace_get_u16(nlt, NFTNL_TRACE_IIFTYPE);
|
||||
- proto_ctx_update(&ctx, PROTO_BASE_LL_HDR, &netlink_location,
|
||||
- proto_dev_desc(dev_type));
|
||||
- }
|
||||
-
|
||||
- trace_gen_stmts(&stmts, &ctx, &pctx, nlt, NFTNL_TRACE_LL_HEADER,
|
||||
- PROTO_BASE_LL_HDR);
|
||||
- trace_gen_stmts(&stmts, &ctx, &pctx, nlt, NFTNL_TRACE_NETWORK_HEADER,
|
||||
- PROTO_BASE_NETWORK_HDR);
|
||||
- trace_gen_stmts(&stmts, &ctx, &pctx, nlt, NFTNL_TRACE_TRANSPORT_HEADER,
|
||||
- PROTO_BASE_TRANSPORT_HDR);
|
||||
-
|
||||
- list_for_each_entry_safe(stmt, next, &stmts, list) {
|
||||
- stmt_print(stmt, octx);
|
||||
- nft_print(octx, " ");
|
||||
- stmt_free(stmt);
|
||||
- }
|
||||
- nft_print(octx, "\n");
|
||||
-}
|
||||
-
|
||||
-int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
|
||||
- struct netlink_mon_handler *monh)
|
||||
-{
|
||||
- struct nftnl_trace *nlt;
|
||||
-
|
||||
- assert(type == NFT_MSG_TRACE);
|
||||
-
|
||||
- nlt = nftnl_trace_alloc();
|
||||
- if (!nlt)
|
||||
- memory_allocation_error();
|
||||
-
|
||||
- if (nftnl_trace_nlmsg_parse(nlh, nlt) < 0)
|
||||
- netlink_abi_error();
|
||||
-
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_LL_HEADER) ||
|
||||
- nftnl_trace_is_set(nlt, NFTNL_TRACE_NETWORK_HEADER))
|
||||
- trace_print_packet(nlt, &monh->ctx->nft->output);
|
||||
-
|
||||
- switch (nftnl_trace_get_u32(nlt, NFTNL_TRACE_TYPE)) {
|
||||
- case NFT_TRACETYPE_RULE:
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE))
|
||||
- trace_print_rule(nlt, &monh->ctx->nft->output,
|
||||
- &monh->ctx->nft->cache);
|
||||
- break;
|
||||
- case NFT_TRACETYPE_POLICY:
|
||||
- trace_print_hdr(nlt, &monh->ctx->nft->output);
|
||||
-
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_POLICY)) {
|
||||
- trace_print_policy(nlt, &monh->ctx->nft->output);
|
||||
- nft_mon_print(monh, " ");
|
||||
- }
|
||||
-
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_MARK))
|
||||
- trace_print_expr(nlt, NFTNL_TRACE_MARK,
|
||||
- meta_expr_alloc(&netlink_location,
|
||||
- NFT_META_MARK),
|
||||
- &monh->ctx->nft->output);
|
||||
- nft_mon_print(monh, "\n");
|
||||
- break;
|
||||
- case NFT_TRACETYPE_RETURN:
|
||||
- trace_print_hdr(nlt, &monh->ctx->nft->output);
|
||||
-
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_VERDICT)) {
|
||||
- trace_print_verdict(nlt, &monh->ctx->nft->output);
|
||||
- nft_mon_print(monh, " ");
|
||||
- }
|
||||
-
|
||||
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_MARK))
|
||||
- trace_print_expr(nlt, NFTNL_TRACE_MARK,
|
||||
- meta_expr_alloc(&netlink_location,
|
||||
- NFT_META_MARK),
|
||||
- &monh->ctx->nft->output);
|
||||
- nft_mon_print(monh, "\n");
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- nftnl_trace_free(nlt);
|
||||
- return MNL_CB_OK;
|
||||
-}
|
||||
diff --git a/src/trace.c b/src/trace.c
|
||||
new file mode 100644
|
||||
index 0000000..a7cc8ff
|
||||
--- /dev/null
|
||||
+++ b/src/trace.c
|
||||
@@ -0,0 +1,353 @@
|
||||
+#include <nft.h>
|
||||
+#include <trace.h>
|
||||
+
|
||||
+#include <libnftnl/trace.h>
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <netinet/in.h>
|
||||
+#include <arpa/inet.h>
|
||||
+#include <inttypes.h>
|
||||
+
|
||||
+#include <linux/netfilter/nfnetlink.h>
|
||||
+#include <linux/netfilter/nf_tables.h>
|
||||
+#include <linux/netfilter.h>
|
||||
+
|
||||
+#include <nftables.h>
|
||||
+#include <mnl.h>
|
||||
+#include <parser.h>
|
||||
+#include <netlink.h>
|
||||
+#include <expression.h>
|
||||
+#include <statement.h>
|
||||
+#include <utils.h>
|
||||
+
|
||||
+#define nft_mon_print(monh, ...) nft_print(&monh->ctx->nft->output, __VA_ARGS__)
|
||||
+
|
||||
+static void trace_print_hdr(const struct nftnl_trace *nlt,
|
||||
+ struct output_ctx *octx)
|
||||
+{
|
||||
+ nft_print(octx, "trace id %08x %s ",
|
||||
+ nftnl_trace_get_u32(nlt, NFTNL_TRACE_ID),
|
||||
+ family2str(nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY)));
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_TABLE))
|
||||
+ nft_print(octx, "%s ",
|
||||
+ nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE));
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CHAIN))
|
||||
+ nft_print(octx, "%s ",
|
||||
+ nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN));
|
||||
+}
|
||||
+
|
||||
+static void trace_print_expr(const struct nftnl_trace *nlt, unsigned int attr,
|
||||
+ struct expr *lhs, struct output_ctx *octx)
|
||||
+{
|
||||
+ struct expr *rhs, *rel;
|
||||
+ const void *data;
|
||||
+ uint32_t len;
|
||||
+
|
||||
+ data = nftnl_trace_get_data(nlt, attr, &len);
|
||||
+ rhs = constant_expr_alloc(&netlink_location,
|
||||
+ lhs->dtype, lhs->byteorder,
|
||||
+ len * BITS_PER_BYTE, data);
|
||||
+ rel = relational_expr_alloc(&netlink_location, OP_EQ, lhs, rhs);
|
||||
+
|
||||
+ expr_print(rel, octx);
|
||||
+ nft_print(octx, " ");
|
||||
+ expr_free(rel);
|
||||
+}
|
||||
+
|
||||
+static void trace_print_verdict(const struct nftnl_trace *nlt,
|
||||
+ struct output_ctx *octx)
|
||||
+{
|
||||
+ struct expr *chain_expr = NULL;
|
||||
+ const char *chain = NULL;
|
||||
+ unsigned int verdict;
|
||||
+ struct expr *expr;
|
||||
+
|
||||
+ verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_VERDICT);
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) {
|
||||
+ chain = xstrdup(nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET));
|
||||
+ chain_expr = constant_expr_alloc(&netlink_location,
|
||||
+ &string_type,
|
||||
+ BYTEORDER_HOST_ENDIAN,
|
||||
+ strlen(chain) * BITS_PER_BYTE,
|
||||
+ chain);
|
||||
+ }
|
||||
+ expr = verdict_expr_alloc(&netlink_location, verdict, chain_expr);
|
||||
+
|
||||
+ nft_print(octx, "verdict ");
|
||||
+ expr_print(expr, octx);
|
||||
+ expr_free(expr);
|
||||
+}
|
||||
+
|
||||
+static void trace_print_policy(const struct nftnl_trace *nlt,
|
||||
+ struct output_ctx *octx)
|
||||
+{
|
||||
+ unsigned int policy;
|
||||
+ struct expr *expr;
|
||||
+
|
||||
+ policy = nftnl_trace_get_u32(nlt, NFTNL_TRACE_POLICY);
|
||||
+
|
||||
+ expr = verdict_expr_alloc(&netlink_location, policy, NULL);
|
||||
+
|
||||
+ nft_print(octx, "policy ");
|
||||
+ expr_print(expr, octx);
|
||||
+ expr_free(expr);
|
||||
+}
|
||||
+
|
||||
+static struct rule *trace_lookup_rule(const struct nftnl_trace *nlt,
|
||||
+ uint64_t rule_handle,
|
||||
+ struct nft_cache *cache)
|
||||
+{
|
||||
+ struct chain *chain;
|
||||
+ struct table *table;
|
||||
+ struct handle h;
|
||||
+
|
||||
+ h.family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
|
||||
+ h.table.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
|
||||
+ h.chain.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN);
|
||||
+
|
||||
+ if (!h.table.name)
|
||||
+ return NULL;
|
||||
+
|
||||
+ table = table_cache_find(&cache->table_cache, h.table.name, h.family);
|
||||
+ if (!table)
|
||||
+ return NULL;
|
||||
+
|
||||
+ chain = chain_cache_find(table, h.chain.name);
|
||||
+ if (!chain)
|
||||
+ return NULL;
|
||||
+
|
||||
+ return rule_lookup(chain, rule_handle);
|
||||
+}
|
||||
+
|
||||
+static void trace_print_rule(const struct nftnl_trace *nlt,
|
||||
+ struct output_ctx *octx, struct nft_cache *cache)
|
||||
+{
|
||||
+ uint64_t rule_handle;
|
||||
+ struct rule *rule;
|
||||
+
|
||||
+ rule_handle = nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE);
|
||||
+ rule = trace_lookup_rule(nlt, rule_handle, cache);
|
||||
+
|
||||
+ trace_print_hdr(nlt, octx);
|
||||
+
|
||||
+ if (rule) {
|
||||
+ nft_print(octx, "rule ");
|
||||
+ rule_print(rule, octx);
|
||||
+ } else {
|
||||
+ nft_print(octx, "unknown rule handle %" PRIu64, rule_handle);
|
||||
+ }
|
||||
+
|
||||
+ nft_print(octx, " (");
|
||||
+ trace_print_verdict(nlt, octx);
|
||||
+ nft_print(octx, ")\n");
|
||||
+}
|
||||
+
|
||||
+static void trace_gen_stmts(struct list_head *stmts,
|
||||
+ struct proto_ctx *ctx, struct payload_dep_ctx *pctx,
|
||||
+ const struct nftnl_trace *nlt, unsigned int attr,
|
||||
+ enum proto_bases base)
|
||||
+{
|
||||
+ struct list_head unordered = LIST_HEAD_INIT(unordered);
|
||||
+ struct list_head list;
|
||||
+ struct expr *rel, *lhs, *rhs, *tmp, *nexpr;
|
||||
+ struct stmt *stmt;
|
||||
+ const struct proto_desc *desc;
|
||||
+ const void *hdr;
|
||||
+ uint32_t hlen;
|
||||
+ unsigned int n;
|
||||
+
|
||||
+ if (!nftnl_trace_is_set(nlt, attr))
|
||||
+ return;
|
||||
+ hdr = nftnl_trace_get_data(nlt, attr, &hlen);
|
||||
+
|
||||
+ lhs = payload_expr_alloc(&netlink_location, NULL, 0);
|
||||
+ payload_init_raw(lhs, base, 0, hlen * BITS_PER_BYTE);
|
||||
+ rhs = constant_expr_alloc(&netlink_location,
|
||||
+ &invalid_type, BYTEORDER_INVALID,
|
||||
+ hlen * BITS_PER_BYTE, hdr);
|
||||
+
|
||||
+restart:
|
||||
+ init_list_head(&list);
|
||||
+ payload_expr_expand(&list, lhs, ctx);
|
||||
+ expr_free(lhs);
|
||||
+
|
||||
+ desc = NULL;
|
||||
+ list_for_each_entry_safe(lhs, nexpr, &list, list) {
|
||||
+ if (desc && desc != ctx->protocol[base].desc) {
|
||||
+ /* Chained protocols */
|
||||
+ lhs->payload.offset = 0;
|
||||
+ if (ctx->protocol[base].desc == NULL)
|
||||
+ break;
|
||||
+ goto restart;
|
||||
+ }
|
||||
+
|
||||
+ tmp = constant_expr_splice(rhs, lhs->len);
|
||||
+ expr_set_type(tmp, lhs->dtype, lhs->byteorder);
|
||||
+ if (tmp->byteorder == BYTEORDER_HOST_ENDIAN)
|
||||
+ mpz_switch_byteorder(tmp->value, tmp->len / BITS_PER_BYTE);
|
||||
+
|
||||
+ /* Skip unknown and filtered expressions */
|
||||
+ desc = lhs->payload.desc;
|
||||
+ if (lhs->dtype == &invalid_type ||
|
||||
+ lhs->payload.tmpl == &proto_unknown_template ||
|
||||
+ desc->checksum_key == payload_hdr_field(lhs) ||
|
||||
+ desc->format.filter & (1 << payload_hdr_field(lhs))) {
|
||||
+ expr_free(lhs);
|
||||
+ expr_free(tmp);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ rel = relational_expr_alloc(&lhs->location, OP_EQ, lhs, tmp);
|
||||
+ stmt = expr_stmt_alloc(&rel->location, rel);
|
||||
+ list_add_tail(&stmt->list, &unordered);
|
||||
+
|
||||
+ desc = ctx->protocol[base].desc;
|
||||
+ relational_expr_pctx_update(ctx, rel);
|
||||
+ }
|
||||
+
|
||||
+ expr_free(rhs);
|
||||
+
|
||||
+ n = 0;
|
||||
+next:
|
||||
+ list_for_each_entry(stmt, &unordered, list) {
|
||||
+ enum proto_bases b = base;
|
||||
+
|
||||
+ rel = stmt->expr;
|
||||
+ lhs = rel->left;
|
||||
+
|
||||
+ /* Move statements to result list in defined order */
|
||||
+ desc = lhs->payload.desc;
|
||||
+ if (desc->format.order[n] &&
|
||||
+ desc->format.order[n] != payload_hdr_field(lhs))
|
||||
+ continue;
|
||||
+
|
||||
+ list_move_tail(&stmt->list, stmts);
|
||||
+ n++;
|
||||
+
|
||||
+ if (payload_is_stacked(desc, rel))
|
||||
+ b--;
|
||||
+
|
||||
+ /* Don't strip 'icmp type' from payload dump. */
|
||||
+ if (pctx->icmp_type == 0)
|
||||
+ payload_dependency_kill(pctx, lhs, ctx->family);
|
||||
+ if (lhs->flags & EXPR_F_PROTOCOL)
|
||||
+ payload_dependency_store(pctx, stmt, b);
|
||||
+
|
||||
+ goto next;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void trace_print_packet(const struct nftnl_trace *nlt,
|
||||
+ struct output_ctx *octx)
|
||||
+{
|
||||
+ struct list_head stmts = LIST_HEAD_INIT(stmts);
|
||||
+ const struct proto_desc *ll_desc;
|
||||
+ struct payload_dep_ctx pctx = {};
|
||||
+ struct proto_ctx ctx;
|
||||
+ uint16_t dev_type;
|
||||
+ uint32_t nfproto;
|
||||
+ struct stmt *stmt, *next;
|
||||
+
|
||||
+ trace_print_hdr(nlt, octx);
|
||||
+
|
||||
+ nft_print(octx, "packet: ");
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_IIF))
|
||||
+ trace_print_expr(nlt, NFTNL_TRACE_IIF,
|
||||
+ meta_expr_alloc(&netlink_location,
|
||||
+ NFT_META_IIF), octx);
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_OIF))
|
||||
+ trace_print_expr(nlt, NFTNL_TRACE_OIF,
|
||||
+ meta_expr_alloc(&netlink_location,
|
||||
+ NFT_META_OIF), octx);
|
||||
+
|
||||
+ proto_ctx_init(&ctx, nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY), 0, false);
|
||||
+ ll_desc = ctx.protocol[PROTO_BASE_LL_HDR].desc;
|
||||
+ if ((ll_desc == &proto_inet || ll_desc == &proto_netdev) &&
|
||||
+ nftnl_trace_is_set(nlt, NFTNL_TRACE_NFPROTO)) {
|
||||
+ nfproto = nftnl_trace_get_u32(nlt, NFTNL_TRACE_NFPROTO);
|
||||
+
|
||||
+ proto_ctx_update(&ctx, PROTO_BASE_LL_HDR, &netlink_location, NULL);
|
||||
+ proto_ctx_update(&ctx, PROTO_BASE_NETWORK_HDR, &netlink_location,
|
||||
+ proto_find_upper(ll_desc, nfproto));
|
||||
+ }
|
||||
+ if (ctx.protocol[PROTO_BASE_LL_HDR].desc == NULL &&
|
||||
+ nftnl_trace_is_set(nlt, NFTNL_TRACE_IIFTYPE)) {
|
||||
+ dev_type = nftnl_trace_get_u16(nlt, NFTNL_TRACE_IIFTYPE);
|
||||
+ proto_ctx_update(&ctx, PROTO_BASE_LL_HDR, &netlink_location,
|
||||
+ proto_dev_desc(dev_type));
|
||||
+ }
|
||||
+
|
||||
+ trace_gen_stmts(&stmts, &ctx, &pctx, nlt, NFTNL_TRACE_LL_HEADER,
|
||||
+ PROTO_BASE_LL_HDR);
|
||||
+ trace_gen_stmts(&stmts, &ctx, &pctx, nlt, NFTNL_TRACE_NETWORK_HEADER,
|
||||
+ PROTO_BASE_NETWORK_HDR);
|
||||
+ trace_gen_stmts(&stmts, &ctx, &pctx, nlt, NFTNL_TRACE_TRANSPORT_HEADER,
|
||||
+ PROTO_BASE_TRANSPORT_HDR);
|
||||
+
|
||||
+ list_for_each_entry_safe(stmt, next, &stmts, list) {
|
||||
+ stmt_print(stmt, octx);
|
||||
+ nft_print(octx, " ");
|
||||
+ stmt_free(stmt);
|
||||
+ }
|
||||
+ nft_print(octx, "\n");
|
||||
+}
|
||||
+
|
||||
+int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
|
||||
+ struct netlink_mon_handler *monh)
|
||||
+{
|
||||
+ struct nftnl_trace *nlt;
|
||||
+
|
||||
+ assert(type == NFT_MSG_TRACE);
|
||||
+
|
||||
+ nlt = nftnl_trace_alloc();
|
||||
+ if (!nlt)
|
||||
+ memory_allocation_error();
|
||||
+
|
||||
+ if (nftnl_trace_nlmsg_parse(nlh, nlt) < 0)
|
||||
+ netlink_abi_error();
|
||||
+
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_LL_HEADER) ||
|
||||
+ nftnl_trace_is_set(nlt, NFTNL_TRACE_NETWORK_HEADER))
|
||||
+ trace_print_packet(nlt, &monh->ctx->nft->output);
|
||||
+
|
||||
+ switch (nftnl_trace_get_u32(nlt, NFTNL_TRACE_TYPE)) {
|
||||
+ case NFT_TRACETYPE_RULE:
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE))
|
||||
+ trace_print_rule(nlt, &monh->ctx->nft->output,
|
||||
+ &monh->ctx->nft->cache);
|
||||
+ break;
|
||||
+ case NFT_TRACETYPE_POLICY:
|
||||
+ trace_print_hdr(nlt, &monh->ctx->nft->output);
|
||||
+
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_POLICY)) {
|
||||
+ trace_print_policy(nlt, &monh->ctx->nft->output);
|
||||
+ nft_mon_print(monh, " ");
|
||||
+ }
|
||||
+
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_MARK))
|
||||
+ trace_print_expr(nlt, NFTNL_TRACE_MARK,
|
||||
+ meta_expr_alloc(&netlink_location,
|
||||
+ NFT_META_MARK),
|
||||
+ &monh->ctx->nft->output);
|
||||
+ nft_mon_print(monh, "\n");
|
||||
+ break;
|
||||
+ case NFT_TRACETYPE_RETURN:
|
||||
+ trace_print_hdr(nlt, &monh->ctx->nft->output);
|
||||
+
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_VERDICT)) {
|
||||
+ trace_print_verdict(nlt, &monh->ctx->nft->output);
|
||||
+ nft_mon_print(monh, " ");
|
||||
+ }
|
||||
+
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_MARK))
|
||||
+ trace_print_expr(nlt, NFTNL_TRACE_MARK,
|
||||
+ meta_expr_alloc(&netlink_location,
|
||||
+ NFT_META_MARK),
|
||||
+ &monh->ctx->nft->output);
|
||||
+ nft_mon_print(monh, "\n");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ nftnl_trace_free(nlt);
|
||||
+ return MNL_CB_OK;
|
||||
+}
|
||||
268
0016-src-add-conntrack-information-to-trace-monitor-mode.patch
Normal file
268
0016-src-add-conntrack-information-to-trace-monitor-mode.patch
Normal file
@ -0,0 +1,268 @@
|
||||
From 0d28ee52a20e8441f66dc11b690fb595f63db6a3 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 15 Jul 2025 22:50:32 +0200
|
||||
Subject: [PATCH] src: add conntrack information to trace monitor mode
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-102994
|
||||
Upstream Status: nftables commit cfd768615235bb89650f15498c70d19813502825
|
||||
|
||||
commit cfd768615235bb89650f15498c70d19813502825
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Jul 7 22:38:13 2025 +0200
|
||||
|
||||
src: add conntrack information to trace monitor mode
|
||||
|
||||
Upcoming kernel change provides the packets conntrack state in the
|
||||
trace message data.
|
||||
|
||||
This allows to see if packet is seen as original or reply, the conntrack
|
||||
state (new, establieshed, related) and the status bits which show if e.g.
|
||||
NAT was applied. Alsoi include conntrack ID so users can use conntrack
|
||||
tool to query the kernel for more information via ctnetlink.
|
||||
|
||||
This improves debugging when e.g. packets do not pick up the expected
|
||||
NAT mapping, which could e.g. also happen because of expectations
|
||||
following the NAT binding of the owning conntrack entry.
|
||||
|
||||
Example output ("conntrack: " lines are new):
|
||||
|
||||
trace id 32 t PRE_RAW packet: iif "enp0s3" ether saddr [..]
|
||||
trace id 32 t PRE_RAW rule tcp flags syn meta nftrace set 1 (verdict continue)
|
||||
trace id 32 t PRE_RAW policy accept
|
||||
trace id 32 t PRE_MANGLE conntrack: ct direction original ct state new ct id 2641368242
|
||||
trace id 32 t PRE_MANGLE packet: iif "enp0s3" ether saddr [..]
|
||||
trace id 32 t ct_new_pre rule jump rpfilter (verdict jump rpfilter)
|
||||
trace id 32 t PRE_MANGLE policy accept
|
||||
trace id 32 t INPUT conntrack: ct direction original ct state new ct status dnat-done ct id 2641368242
|
||||
trace id 32 t INPUT packet: iif "enp0s3" [..]
|
||||
trace id 32 t public_in rule tcp dport 443 accept (verdict accept)
|
||||
|
||||
v3: remove clash bit again, kernel won't expose it anymore.
|
||||
v2: add more status bits: helper, clash, offload, hw-offload.
|
||||
add flag explanation to documentation.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
doc/data-types.txt | 30 ++---
|
||||
include/linux/netfilter/nf_conntrack_common.h | 16 +++
|
||||
src/ct.c | 7 ++
|
||||
src/trace.c | 109 ++++++++++++++++++
|
||||
4 files changed, 147 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/doc/data-types.txt b/doc/data-types.txt
|
||||
index 6c0e2f9..abbb7fd 100644
|
||||
--- a/doc/data-types.txt
|
||||
+++ b/doc/data-types.txt
|
||||
@@ -378,21 +378,21 @@ For each of the types above, keywords are available for convenience:
|
||||
.conntrack status (ct_status)
|
||||
[options="header"]
|
||||
|==================
|
||||
-|Keyword| Value
|
||||
-|expected|
|
||||
-1
|
||||
-|seen-reply|
|
||||
-2
|
||||
-|assured|
|
||||
-4
|
||||
-|confirmed|
|
||||
-8
|
||||
-|snat|
|
||||
-16
|
||||
-|dnat|
|
||||
-32
|
||||
-|dying|
|
||||
-512
|
||||
+|Keyword| Value | Description
|
||||
+|expected|1| Expected connection; conntrack helper set it up
|
||||
+|seen-reply|2| Conntrack has seen packets in both directions
|
||||
+|assured| 4 |Conntrack entry will not be removed if hash table is full
|
||||
+|confirmed | 8 | Initial packet processed
|
||||
+|snat| 16 | Original source address differs from reply destination
|
||||
+|dnat| 32 | Original destination differs from reply source
|
||||
+|seq-adjust| 64 | tcp sequence number rewrite due to conntrack helper or synproxy
|
||||
+|snat-done| 128 | tried to find matching snat/masquerade rule
|
||||
+|dnat-done| 256 | tried to find matching dnat/redirect rule
|
||||
+|dying| 512 | Connection about to be deleted
|
||||
+|fixed-timeout | 1024 | entry expires even if traffic is active
|
||||
+|helper | 8192 | connection is monitored by conntrack helper
|
||||
+|offload | 16384 | connection is offloaded to a flow table
|
||||
+|hw-offload | 32768 | connection is offloaded to hardware
|
||||
|================
|
||||
|
||||
.conntrack event bits (ct_event)
|
||||
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
|
||||
index 768ff25..22bbb6c 100644
|
||||
--- a/include/linux/netfilter/nf_conntrack_common.h
|
||||
+++ b/include/linux/netfilter/nf_conntrack_common.h
|
||||
@@ -77,6 +77,22 @@ enum ip_conntrack_status {
|
||||
/* Connection has fixed timeout. */
|
||||
IPS_FIXED_TIMEOUT_BIT = 10,
|
||||
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
|
||||
+
|
||||
+ /* Conntrack is a fake untracked entry. Obsolete and not used anymore */
|
||||
+ IPS_UNTRACKED_BIT = 12,
|
||||
+ IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
|
||||
+
|
||||
+ /* Conntrack got a helper explicitly attached (ruleset, ctnetlink). */
|
||||
+ IPS_HELPER_BIT = 13,
|
||||
+ IPS_HELPER = (1 << IPS_HELPER_BIT),
|
||||
+
|
||||
+ /* Conntrack has been offloaded to flow table. */
|
||||
+ IPS_OFFLOAD_BIT = 14,
|
||||
+ IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT),
|
||||
+
|
||||
+ /* Conntrack has been offloaded to hardware. */
|
||||
+ IPS_HW_OFFLOAD_BIT = 15,
|
||||
+ IPS_HW_OFFLOAD = (1 << IPS_HW_OFFLOAD_BIT),
|
||||
};
|
||||
|
||||
/* Connection tracking event types */
|
||||
diff --git a/src/ct.c b/src/ct.c
|
||||
index 6793464..cd97d82 100644
|
||||
--- a/src/ct.c
|
||||
+++ b/src/ct.c
|
||||
@@ -98,7 +98,14 @@ static const struct symbol_table ct_status_tbl = {
|
||||
SYMBOL("confirmed", IPS_CONFIRMED),
|
||||
SYMBOL("snat", IPS_SRC_NAT),
|
||||
SYMBOL("dnat", IPS_DST_NAT),
|
||||
+ SYMBOL("seq-adjust", IPS_SEQ_ADJUST),
|
||||
+ SYMBOL("snat-done", IPS_SRC_NAT_DONE),
|
||||
+ SYMBOL("dnat-done", IPS_DST_NAT_DONE),
|
||||
SYMBOL("dying", IPS_DYING),
|
||||
+ SYMBOL("fixed-timeout", IPS_FIXED_TIMEOUT),
|
||||
+ SYMBOL("helper", IPS_HELPER_BIT),
|
||||
+ SYMBOL("offload", IPS_OFFLOAD_BIT),
|
||||
+ SYMBOL("hw-offload", IPS_HW_OFFLOAD_BIT),
|
||||
SYMBOL_LIST_END
|
||||
},
|
||||
};
|
||||
diff --git a/src/trace.c b/src/trace.c
|
||||
index a7cc8ff..b270951 100644
|
||||
--- a/src/trace.c
|
||||
+++ b/src/trace.c
|
||||
@@ -237,6 +237,114 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
+static struct expr *trace_alloc_list(const struct datatype *dtype,
|
||||
+ enum byteorder byteorder,
|
||||
+ unsigned int len, const void *data)
|
||||
+{
|
||||
+ struct expr *list_expr;
|
||||
+ unsigned int i;
|
||||
+ mpz_t value;
|
||||
+ uint32_t v;
|
||||
+
|
||||
+ if (len != sizeof(v))
|
||||
+ return constant_expr_alloc(&netlink_location,
|
||||
+ dtype, byteorder,
|
||||
+ len * BITS_PER_BYTE, data);
|
||||
+
|
||||
+ list_expr = list_expr_alloc(&netlink_location);
|
||||
+
|
||||
+ mpz_init2(value, 32);
|
||||
+ mpz_import_data(value, data, byteorder, len);
|
||||
+ v = mpz_get_uint32(value);
|
||||
+ if (v == 0) {
|
||||
+ mpz_clear(value);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 32; i++) {
|
||||
+ uint32_t bitv = v & (1 << i);
|
||||
+
|
||||
+ if (bitv == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ compound_expr_add(list_expr,
|
||||
+ constant_expr_alloc(&netlink_location,
|
||||
+ dtype, byteorder,
|
||||
+ len * BITS_PER_BYTE,
|
||||
+ &bitv));
|
||||
+ }
|
||||
+
|
||||
+ mpz_clear(value);
|
||||
+ return list_expr;
|
||||
+}
|
||||
+
|
||||
+static void trace_print_ct_expr(const struct nftnl_trace *nlt, unsigned int attr,
|
||||
+ enum nft_ct_keys key, struct output_ctx *octx)
|
||||
+{
|
||||
+ struct expr *lhs, *rhs, *rel;
|
||||
+ const void *data;
|
||||
+ uint32_t len;
|
||||
+
|
||||
+ data = nftnl_trace_get_data(nlt, attr, &len);
|
||||
+ lhs = ct_expr_alloc(&netlink_location, key, -1);
|
||||
+
|
||||
+ switch (key) {
|
||||
+ case NFT_CT_STATUS:
|
||||
+ rhs = trace_alloc_list(lhs->dtype, lhs->byteorder, len, data);
|
||||
+ if (!rhs) {
|
||||
+ expr_free(lhs);
|
||||
+ return;
|
||||
+ }
|
||||
+ rel = binop_expr_alloc(&netlink_location, OP_IMPLICIT, lhs, rhs);
|
||||
+ break;
|
||||
+ case NFT_CT_DIRECTION:
|
||||
+ case NFT_CT_STATE:
|
||||
+ case NFT_CT_ID:
|
||||
+ /* fallthrough */
|
||||
+ default:
|
||||
+ rhs = constant_expr_alloc(&netlink_location,
|
||||
+ lhs->dtype, lhs->byteorder,
|
||||
+ len * BITS_PER_BYTE, data);
|
||||
+ rel = relational_expr_alloc(&netlink_location, OP_IMPLICIT, lhs, rhs);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ expr_print(rel, octx);
|
||||
+ nft_print(octx, " ");
|
||||
+ expr_free(rel);
|
||||
+}
|
||||
+
|
||||
+static void trace_print_ct(const struct nftnl_trace *nlt,
|
||||
+ struct output_ctx *octx)
|
||||
+{
|
||||
+ bool ct = nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_STATE);
|
||||
+
|
||||
+ if (!ct)
|
||||
+ return;
|
||||
+
|
||||
+ trace_print_hdr(nlt, octx);
|
||||
+
|
||||
+ nft_print(octx, "conntrack: ");
|
||||
+
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_DIRECTION))
|
||||
+ trace_print_ct_expr(nlt, NFTNL_TRACE_CT_DIRECTION,
|
||||
+ NFT_CT_DIRECTION, octx);
|
||||
+
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_STATE))
|
||||
+ trace_print_ct_expr(nlt, NFTNL_TRACE_CT_STATE,
|
||||
+ NFT_CT_STATE, octx);
|
||||
+
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_STATUS))
|
||||
+ trace_print_ct_expr(nlt, NFTNL_TRACE_CT_STATUS,
|
||||
+ NFT_CT_STATUS, octx);
|
||||
+
|
||||
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CT_ID))
|
||||
+ trace_print_ct_expr(nlt, NFTNL_TRACE_CT_ID,
|
||||
+ NFT_CT_ID, octx);
|
||||
+
|
||||
+ nft_print(octx, "\n");
|
||||
+}
|
||||
+
|
||||
static void trace_print_packet(const struct nftnl_trace *nlt,
|
||||
struct output_ctx *octx)
|
||||
{
|
||||
@@ -248,6 +356,7 @@ static void trace_print_packet(const struct nftnl_trace *nlt,
|
||||
uint32_t nfproto;
|
||||
struct stmt *stmt, *next;
|
||||
|
||||
+ trace_print_ct(nlt, octx);
|
||||
trace_print_hdr(nlt, octx);
|
||||
|
||||
nft_print(octx, "packet: ");
|
||||
@ -0,0 +1,38 @@
|
||||
From 5ed024ecfaf596ec0298f8ad75c5695f9889464c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 9 Sep 2025 16:27:52 +0200
|
||||
Subject: [PATCH] trace: Fix for memleak in trace_alloc_list() error path
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-111205
|
||||
Upstream Status: nftables commit fdbb0ec57b5c891c1de17f367b693ab787ea9c2d
|
||||
|
||||
commit fdbb0ec57b5c891c1de17f367b693ab787ea9c2d
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue Aug 26 12:57:37 2025 +0200
|
||||
|
||||
trace: Fix for memleak in trace_alloc_list() error path
|
||||
|
||||
The allocated 'list_expr' may leak.
|
||||
|
||||
Fixes: cfd768615235b ("src: add conntrack information to trace monitor mode")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
src/trace.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/trace.c b/src/trace.c
|
||||
index b270951..47f4c21 100644
|
||||
--- a/src/trace.c
|
||||
+++ b/src/trace.c
|
||||
@@ -258,6 +258,7 @@ static struct expr *trace_alloc_list(const struct datatype *dtype,
|
||||
v = mpz_get_uint32(value);
|
||||
if (v == 0) {
|
||||
mpz_clear(value);
|
||||
+ expr_free(list_expr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
78
0018-doc-nft.8-Minor-NAT-STATEMENTS-section-review.patch
Normal file
78
0018-doc-nft.8-Minor-NAT-STATEMENTS-section-review.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 3bb2e6c3d03fa60724ab72b96d1e97fa02d7eed9 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 9 Sep 2025 16:53:21 +0200
|
||||
Subject: [PATCH] doc: nft.8: Minor NAT STATEMENTS section review
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-106743
|
||||
Upstream Status: nftables commit 9e1cbf667da2b9c30b41ff887de212b2c38b2eb7
|
||||
|
||||
commit 9e1cbf667da2b9c30b41ff887de212b2c38b2eb7
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Thu Jul 31 12:40:11 2025 +0200
|
||||
|
||||
doc: nft.8: Minor NAT STATEMENTS section review
|
||||
|
||||
Synopsis insinuates an IP address argument is mandatory in snat/dnat
|
||||
statements although specifying ports alone is perfectly fine. Adjust it
|
||||
accordingly and add a paragraph briefly describing the behaviour.
|
||||
|
||||
While at it, update the redirect statement description with more
|
||||
relevant examples, the current one is wrong: To *only* alter the
|
||||
destination port, dnat statement must be used, not redirect.
|
||||
|
||||
Fixes: 6908a677ba04c ("nft.8: Enhance NAT documentation")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
doc/statements.txt | 17 +++++++++++------
|
||||
1 file changed, 11 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/doc/statements.txt b/doc/statements.txt
|
||||
index 74af1d1..7fe9ed3 100644
|
||||
--- a/doc/statements.txt
|
||||
+++ b/doc/statements.txt
|
||||
@@ -399,11 +399,12 @@ NAT STATEMENTS
|
||||
~~~~~~~~~~~~~~
|
||||
[verse]
|
||||
____
|
||||
-*snat* [[*ip* | *ip6*] [ *prefix* ] *to*] 'ADDR_SPEC' [*:*'PORT_SPEC'] ['FLAGS']
|
||||
-*dnat* [[*ip* | *ip6*] [ *prefix* ] *to*] 'ADDR_SPEC' [*:*'PORT_SPEC'] ['FLAGS']
|
||||
+*snat* [[*ip* | *ip6*] [ *prefix* ] *to*] 'TARGET_SPEC' ['FLAGS']
|
||||
+*dnat* [[*ip* | *ip6*] [ *prefix* ] *to*] 'TARGET_SPEC' ['FLAGS']
|
||||
*masquerade* [*to :*'PORT_SPEC'] ['FLAGS']
|
||||
*redirect* [*to :*'PORT_SPEC'] ['FLAGS']
|
||||
|
||||
+'TARGET_SPEC' := 'ADDR_SPEC' | ['ADDR_SPEC'] *:*'PORT_SPEC'
|
||||
'ADDR_SPEC' := 'address' | 'address' *-* 'address'
|
||||
'PORT_SPEC' := 'port' | 'port' *-* 'port'
|
||||
|
||||
@@ -413,11 +414,11 @@ ____
|
||||
|
||||
The nat statements are only valid from nat chain types. +
|
||||
|
||||
-The *snat* and *masquerade* statements specify that the source address of the
|
||||
+The *snat* and *masquerade* statements specify that the source address/port of the
|
||||
packet should be modified. While *snat* is only valid in the postrouting and
|
||||
input chains, *masquerade* makes sense only in postrouting. The dnat and
|
||||
redirect statements are only valid in the prerouting and output chains, they
|
||||
-specify that the destination address of the packet should be modified. You can
|
||||
+specify that the destination address/port of the packet should be modified. You can
|
||||
use non-base chains which are called from base chains of nat chain type too.
|
||||
All future packets in this connection will also be mangled, and rules should
|
||||
cease being examined.
|
||||
@@ -427,8 +428,12 @@ outgoing interface's IP address to translate to. It is particularly useful on
|
||||
gateways with dynamic (public) IP addresses.
|
||||
|
||||
The *redirect* statement is a special form of dnat which always translates the
|
||||
-destination address to the local host's one. It comes in handy if one only wants
|
||||
-to alter the destination port of incoming traffic on different interfaces.
|
||||
+destination address to the local host's one. It comes in handy to intercept
|
||||
+traffic passing a router and feeding it to a locally running daemon, e.g. when
|
||||
+building a transparent proxy or application-layer gateway.
|
||||
+
|
||||
+For 'TARGET_SPEC', one may specify addresses, ports, or both. If no address or
|
||||
+no port is specified, the respective packet header field remains unchanged.
|
||||
|
||||
When used in the inet family (available with kernel 5.2), the dnat and snat
|
||||
statements require the use of the ip and ip6 keyword in case an address is
|
||||
232
0019-table-Embed-creating-nft-version-into-userdata.patch
Normal file
232
0019-table-Embed-creating-nft-version-into-userdata.patch
Normal file
@ -0,0 +1,232 @@
|
||||
From 50afb84d7064806ad7acc8364455062fc0751528 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 9 Sep 2025 16:49:27 +0200
|
||||
Subject: [PATCH] table: Embed creating nft version into userdata
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-108851
|
||||
Upstream Status: nftables commit 64c07e38f0494093a399a68a31056f5866c4d705
|
||||
Conflicts: Context change due to missing --with-unitdir option.
|
||||
|
||||
commit 64c07e38f0494093a399a68a31056f5866c4d705
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Mon May 12 22:59:26 2025 +0200
|
||||
|
||||
table: Embed creating nft version into userdata
|
||||
|
||||
Upon listing a table which was created by a newer version of nftables,
|
||||
warn about the potentially incomplete content.
|
||||
|
||||
Suggested-by: Florian Westphal <fw@strlen.de>
|
||||
Cc: Dan Winship <danwinship@redhat.com>
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
Makefile.am | 3 +++
|
||||
configure.ac | 24 ++++++++++++++++++++++++
|
||||
include/rule.h | 1 +
|
||||
src/mnl.c | 21 +++++++++++++++------
|
||||
src/netlink.c | 33 +++++++++++++++++++++++++++++++++
|
||||
src/rule.c | 4 ++++
|
||||
6 files changed, 80 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index ba09e7f..c2a6908 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -33,6 +33,7 @@ sbin_PROGRAMS =
|
||||
check_PROGRAMS =
|
||||
dist_man_MANS =
|
||||
CLEANFILES =
|
||||
+DISTCLEANFILES =
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -105,6 +106,8 @@ noinst_HEADERS = \
|
||||
\
|
||||
$(NULL)
|
||||
|
||||
+DISTCLEANFILES += nftversion.h
|
||||
+
|
||||
###############################################################################
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 816e920..bac8319 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -114,6 +114,30 @@ AC_CHECK_DECLS([getprotobyname_r, getprotobynumber_r, getservbyport_r], [], [],
|
||||
#include <netdb.h>
|
||||
]])
|
||||
|
||||
+AC_ARG_WITH([stable-release], [AS_HELP_STRING([--with-stable-release],
|
||||
+ [Stable release number])],
|
||||
+ [], [with_stable_release=0])
|
||||
+AC_CONFIG_COMMANDS([stable_release],
|
||||
+ [STABLE_RELEASE=$stable_release],
|
||||
+ [stable_release=$with_stable_release])
|
||||
+AC_CONFIG_COMMANDS([nftversion.h], [
|
||||
+(
|
||||
+ echo "static char nftversion[[]] = {"
|
||||
+ echo " ${VERSION}," | tr '.' ','
|
||||
+ echo " ${STABLE_RELEASE}"
|
||||
+ echo "};"
|
||||
+ echo "static char nftbuildstamp[[]] = {"
|
||||
+ for ((i = 56; i >= 0; i-= 8)); do
|
||||
+ echo " ((uint64_t)MAKE_STAMP >> $i) & 0xff,"
|
||||
+ done
|
||||
+ echo "};"
|
||||
+) >nftversion.h
|
||||
+])
|
||||
+# Current date should be fetched exactly once per build,
|
||||
+# so have 'make' call date and pass the value to every 'gcc' call
|
||||
+AC_SUBST([MAKE_STAMP], ["\$(shell date +%s)"])
|
||||
+CFLAGS="${CFLAGS} -DMAKE_STAMP=\${MAKE_STAMP}"
|
||||
+
|
||||
AC_CONFIG_FILES([ \
|
||||
Makefile \
|
||||
libnftables.pc \
|
||||
diff --git a/include/rule.h b/include/rule.h
|
||||
index 238be23..1b52972 100644
|
||||
--- a/include/rule.h
|
||||
+++ b/include/rule.h
|
||||
@@ -170,6 +170,7 @@ struct table {
|
||||
uint32_t owner;
|
||||
const char *comment;
|
||||
bool has_xt_stmts;
|
||||
+ bool is_from_future;
|
||||
};
|
||||
|
||||
extern struct table *table_alloc(void);
|
||||
diff --git a/src/mnl.c b/src/mnl.c
|
||||
index 12a6345..e748ab6 100644
|
||||
--- a/src/mnl.c
|
||||
+++ b/src/mnl.c
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <nft.h>
|
||||
#include <iface.h>
|
||||
+#include <nftversion.h>
|
||||
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <libnftnl/common.h>
|
||||
@@ -1054,24 +1055,32 @@ int mnl_nft_table_add(struct netlink_ctx *ctx, struct cmd *cmd,
|
||||
if (nlt == NULL)
|
||||
memory_allocation_error();
|
||||
|
||||
+ udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
|
||||
+ if (!udbuf)
|
||||
+ memory_allocation_error();
|
||||
+
|
||||
nftnl_table_set_u32(nlt, NFTNL_TABLE_FAMILY, cmd->handle.family);
|
||||
if (cmd->table) {
|
||||
nftnl_table_set_u32(nlt, NFTNL_TABLE_FLAGS, cmd->table->flags);
|
||||
|
||||
if (cmd->table->comment) {
|
||||
- udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
|
||||
- if (!udbuf)
|
||||
- memory_allocation_error();
|
||||
if (!nftnl_udata_put_strz(udbuf, NFTNL_UDATA_TABLE_COMMENT, cmd->table->comment))
|
||||
memory_allocation_error();
|
||||
- nftnl_table_set_data(nlt, NFTNL_TABLE_USERDATA, nftnl_udata_buf_data(udbuf),
|
||||
- nftnl_udata_buf_len(udbuf));
|
||||
- nftnl_udata_buf_free(udbuf);
|
||||
}
|
||||
} else {
|
||||
nftnl_table_set_u32(nlt, NFTNL_TABLE_FLAGS, 0);
|
||||
}
|
||||
|
||||
+ if (!nftnl_udata_put(udbuf, NFTNL_UDATA_TABLE_NFTVER,
|
||||
+ sizeof(nftversion), nftversion) ||
|
||||
+ !nftnl_udata_put(udbuf, NFTNL_UDATA_TABLE_NFTBLD,
|
||||
+ sizeof(nftbuildstamp), nftbuildstamp))
|
||||
+ memory_allocation_error();
|
||||
+ nftnl_table_set_data(nlt, NFTNL_TABLE_USERDATA,
|
||||
+ nftnl_udata_buf_data(udbuf),
|
||||
+ nftnl_udata_buf_len(udbuf));
|
||||
+ nftnl_udata_buf_free(udbuf);
|
||||
+
|
||||
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
|
||||
NFT_MSG_NEWTABLE,
|
||||
cmd->handle.family,
|
||||
diff --git a/src/netlink.c b/src/netlink.c
|
||||
index 2ced863..7f9730d 100644
|
||||
--- a/src/netlink.c
|
||||
+++ b/src/netlink.c
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <nft.h>
|
||||
+#include <nftversion.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <libmnl/libmnl.h>
|
||||
@@ -728,6 +729,14 @@ static int table_parse_udata_cb(const struct nftnl_udata *attr, void *data)
|
||||
if (value[len - 1] != '\0')
|
||||
return -1;
|
||||
break;
|
||||
+ case NFTNL_UDATA_TABLE_NFTVER:
|
||||
+ if (len != sizeof(nftversion))
|
||||
+ return -1;
|
||||
+ break;
|
||||
+ case NFTNL_UDATA_TABLE_NFTBLD:
|
||||
+ if (len != sizeof(nftbuildstamp))
|
||||
+ return -1;
|
||||
+ break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -735,6 +744,29 @@ static int table_parse_udata_cb(const struct nftnl_udata *attr, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int version_cmp(const struct nftnl_udata **ud)
|
||||
+{
|
||||
+ const char *udbuf;
|
||||
+ size_t i;
|
||||
+
|
||||
+ /* netlink attribute lengths checked by table_parse_udata_cb() */
|
||||
+ if (ud[NFTNL_UDATA_TABLE_NFTVER]) {
|
||||
+ udbuf = nftnl_udata_get(ud[NFTNL_UDATA_TABLE_NFTVER]);
|
||||
+ for (i = 0; i < sizeof(nftversion); i++) {
|
||||
+ if (nftversion[i] != udbuf[i])
|
||||
+ return nftversion[i] - udbuf[i];
|
||||
+ }
|
||||
+ }
|
||||
+ if (ud[NFTNL_UDATA_TABLE_NFTBLD]) {
|
||||
+ udbuf = nftnl_udata_get(ud[NFTNL_UDATA_TABLE_NFTBLD]);
|
||||
+ for (i = 0; i < sizeof(nftbuildstamp); i++) {
|
||||
+ if (nftbuildstamp[i] != udbuf[i])
|
||||
+ return nftbuildstamp[i] - udbuf[i];
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
|
||||
const struct nftnl_table *nlt)
|
||||
{
|
||||
@@ -759,6 +791,7 @@ struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
|
||||
}
|
||||
if (ud[NFTNL_UDATA_TABLE_COMMENT])
|
||||
table->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_TABLE_COMMENT]));
|
||||
+ table->is_from_future = version_cmp(ud) < 0;
|
||||
}
|
||||
|
||||
return table;
|
||||
diff --git a/src/rule.c b/src/rule.c
|
||||
index 151ed53..e4d6f53 100644
|
||||
--- a/src/rule.c
|
||||
+++ b/src/rule.c
|
||||
@@ -1274,6 +1274,10 @@ static void table_print(const struct table *table, struct output_ctx *octx)
|
||||
fprintf(octx->error_fp,
|
||||
"# Warning: table %s %s is managed by iptables-nft, do not touch!\n",
|
||||
family, table->handle.table.name);
|
||||
+ if (table->is_from_future)
|
||||
+ fprintf(octx->error_fp,
|
||||
+ "# Warning: table %s %s was created by a newer version of nftables? Content may be incomplete!\n",
|
||||
+ family, table->handle.table.name);
|
||||
|
||||
nft_print(octx, "table %s %s {", family, table->handle.table.name);
|
||||
if (nft_output_handle(octx) || table->flags & TABLE_F_OWNER)
|
||||
52
0020-Makefile-Fix-for-make-CFLAGS.patch
Normal file
52
0020-Makefile-Fix-for-make-CFLAGS.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 575c0a20b143f5487a184c2c5c866dd8b14a69f5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 9 Sep 2025 16:50:13 +0200
|
||||
Subject: [PATCH] Makefile: Fix for 'make CFLAGS=...'
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-108851
|
||||
Upstream Status: nftables commit 229fa8b440b67debb12beca830e57a9ea25a2745
|
||||
|
||||
commit 229fa8b440b67debb12beca830e57a9ea25a2745
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue Sep 9 00:14:16 2025 +0200
|
||||
|
||||
Makefile: Fix for 'make CFLAGS=...'
|
||||
|
||||
Appending to CFLAGS from configure.ac like this was too naive, passing
|
||||
custom CFLAGS in make arguments overwrites it. Extend AM_CFLAGS instead.
|
||||
|
||||
Fixes: 64c07e38f0494 ("table: Embed creating nft version into userdata")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||||
---
|
||||
Makefile.am | 2 ++
|
||||
configure.ac | 1 -
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index c2a6908..58c6959 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -154,6 +154,8 @@ AM_CFLAGS = \
|
||||
\
|
||||
$(GCC_FVISIBILITY_HIDDEN) \
|
||||
\
|
||||
+ -DMAKE_STAMP=$(MAKE_STAMP) \
|
||||
+ \
|
||||
$(NULL)
|
||||
|
||||
AM_YFLAGS = -d -Wno-yacc
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index bac8319..c14aa67 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -136,7 +136,6 @@ AC_CONFIG_COMMANDS([nftversion.h], [
|
||||
# Current date should be fetched exactly once per build,
|
||||
# so have 'make' call date and pass the value to every 'gcc' call
|
||||
AC_SUBST([MAKE_STAMP], ["\$(shell date +%s)"])
|
||||
-CFLAGS="${CFLAGS} -DMAKE_STAMP=\${MAKE_STAMP}"
|
||||
|
||||
AC_CONFIG_FILES([ \
|
||||
Makefile \
|
||||
@ -1,6 +1,6 @@
|
||||
Name: nftables
|
||||
Version: 1.1.1
|
||||
Release: 4%{?dist}
|
||||
Release: 6%{?dist}
|
||||
# Upstream released a 0.100 version, then 0.4. Need Epoch to get back on track.
|
||||
Epoch: 1
|
||||
Summary: Netfilter Tables userspace utilities
|
||||
@ -30,6 +30,12 @@ Patch11: 0011-json-Support-typeof-in-set-and-map-types.patch
|
||||
Patch12: 0012-tests-py-Fix-for-storing-payload-into-missing-file.patch
|
||||
Patch13: 0013-monitor-Recognize-flowtable-add-del-events.patch
|
||||
Patch14: 0014-evaluate-allow-to-re-use-existing-metered-set.patch
|
||||
Patch15: 0015-src-split-monitor-trace-code-into-new-trace.c.patch
|
||||
Patch16: 0016-src-add-conntrack-information-to-trace-monitor-mode.patch
|
||||
Patch17: 0017-trace-Fix-for-memleak-in-trace_alloc_list-error-path.patch
|
||||
Patch18: 0018-doc-nft.8-Minor-NAT-STATEMENTS-section-review.patch
|
||||
Patch19: 0019-table-Embed-creating-nft-version-into-userdata.patch
|
||||
Patch20: 0020-Makefile-Fix-for-make-CFLAGS.patch
|
||||
|
||||
BuildRequires: autoconf
|
||||
BuildRequires: automake
|
||||
@ -144,6 +150,16 @@ cd py/
|
||||
%files -n python3-nftables -f %{pyproject_files}
|
||||
|
||||
%changelog
|
||||
* Wed Sep 10 2025 Phil Sutter <psutter@redhat.com> [1.1.1-6.el10]
|
||||
- Makefile: Fix for 'make CFLAGS=...' (Phil Sutter) [RHEL-108851]
|
||||
- table: Embed creating nft version into userdata (Phil Sutter) [RHEL-108851]
|
||||
- doc: nft.8: Minor NAT STATEMENTS section review (Phil Sutter) [RHEL-106743]
|
||||
- trace: Fix for memleak in trace_alloc_list() error path (Phil Sutter) [RHEL-111205]
|
||||
|
||||
* Wed Jul 16 2025 Phil Sutter <psutter@redhat.com> [1.1.1-5.el10]
|
||||
- src: add conntrack information to trace monitor mode (Phil Sutter) [RHEL-102994]
|
||||
- src: split monitor trace code into new trace.c (Phil Sutter) [RHEL-102994]
|
||||
|
||||
* Mon Mar 03 2025 Eric Garver <egarver@redhat.com> [1.1.1-4.el10]
|
||||
- evaluate: allow to re-use existing metered set [RHEL-75507]
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user