All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] conntrack-tools: support conntrack dump status filtering
@ 2021-08-02  9:12 Florian Westphal
  2021-08-02  9:12 ` [PATCH lnf-conntrack 1/4] include: sync uapi header with nf-next Florian Westphal
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Florian Westphal @ 2021-08-02  9:12 UTC (permalink / raw)
  To: netfilter-devel

These changes to libnetfilter-conntrack and conntrack-tools allow to
dump  the connection tracking table while suppressing entries that
lack the given status bits.

This allows for example to limit the dump rquest to only contain
entries that did not yet see a reply.

First patch syncs the embedded uapi header with that of nf-next,
second patch adds the status dump filter glue to libnetfilter-conntrack.

Patch 3 is the main change.
Patch 4 adds support for the simpler 'UNREPLIED' keyword, this seems
easier to use than to ask for '!SEEN_REPLY'.



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

* [PATCH lnf-conntrack 1/4] include: sync uapi header with nf-next
  2021-08-02  9:12 [PATCH] conntrack-tools: support conntrack dump status filtering Florian Westphal
@ 2021-08-02  9:12 ` Florian Westphal
  2021-08-02  9:12 ` [PATCH lnf-conntrack 2/4] src: add support for status dump filter Florian Westphal
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2021-08-02  9:12 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 .../linux_nfnetlink_conntrack.h               | 24 +++++++++++++++----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
index 0e9af6c1ebd7..6c8de4eb7472 100644
--- a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
+++ b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
@@ -58,6 +58,8 @@ enum ctattr_type {
 	CTA_LABELS,
 	CTA_LABELS_MASK,
 	CTA_SYNPROXY,
+	CTA_FILTER,
+	CTA_STATUS_MASK,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
@@ -121,6 +123,7 @@ enum ctattr_protoinfo_dccp {
 	CTA_PROTOINFO_DCCP_STATE,
 	CTA_PROTOINFO_DCCP_ROLE,
 	CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
+	CTA_PROTOINFO_DCCP_PAD,
 	__CTA_PROTOINFO_DCCP_MAX,
 };
 #define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1)
@@ -140,6 +143,7 @@ enum ctattr_counters {
 	CTA_COUNTERS_BYTES,		/* 64bit counters */
 	CTA_COUNTERS32_PACKETS,		/* old 32bit counters, unused */
 	CTA_COUNTERS32_BYTES,		/* old 32bit counters, unused */
+	CTA_COUNTERS_PAD,
 	__CTA_COUNTERS_MAX
 };
 #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
@@ -148,6 +152,7 @@ enum ctattr_tstamp {
 	CTA_TIMESTAMP_UNSPEC,
 	CTA_TIMESTAMP_START,
 	CTA_TIMESTAMP_STOP,
+	CTA_TIMESTAMP_PAD,
 	__CTA_TIMESTAMP_MAX
 };
 #define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1)
@@ -242,13 +247,13 @@ enum ctattr_secctx {
 
 enum ctattr_stats_cpu {
 	CTA_STATS_UNSPEC,
-	CTA_STATS_SEARCHED,
+	CTA_STATS_SEARCHED,	/* no longer used */
 	CTA_STATS_FOUND,
-	CTA_STATS_NEW,
+	CTA_STATS_NEW,		/* no longer used */
 	CTA_STATS_INVALID,
-	CTA_STATS_IGNORE,
-	CTA_STATS_DELETE,
-	CTA_STATS_DELETE_LIST,
+	CTA_STATS_IGNORE,	/* no longer used */
+	CTA_STATS_DELETE,	/* no longer used */
+	CTA_STATS_DELETE_LIST,	/* no longer used */
 	CTA_STATS_INSERT,
 	CTA_STATS_INSERT_FAILED,
 	CTA_STATS_DROP,
@@ -263,6 +268,7 @@ enum ctattr_stats_cpu {
 enum ctattr_stats_global {
 	CTA_STATS_GLOBAL_UNSPEC,
 	CTA_STATS_GLOBAL_ENTRIES,
+	CTA_STATS_GLOBAL_MAX_ENTRIES,
 	__CTA_STATS_GLOBAL_MAX,
 };
 #define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1)
@@ -276,6 +282,14 @@ enum ctattr_expect_stats {
 };
 #define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1)
 
+enum ctattr_filter {
+	CTA_FILTER_UNSPEC,
+	CTA_FILTER_ORIG_FLAGS,
+	CTA_FILTER_REPLY_FLAGS,
+	__CTA_FILTER_MAX
+};
+#define CTA_FILTER_MAX (__CTA_FILTER_MAX - 1)
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.31.1


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

* [PATCH lnf-conntrack 2/4] src: add support for status dump filter
  2021-08-02  9:12 [PATCH] conntrack-tools: support conntrack dump status filtering Florian Westphal
  2021-08-02  9:12 ` [PATCH lnf-conntrack 1/4] include: sync uapi header with nf-next Florian Westphal
@ 2021-08-02  9:12 ` Florian Westphal
  2021-08-02  9:12 ` [PATCH conntrack-tools 3/4] conntrack: enable kernel-based status filtering with -L -u STATUS Florian Westphal
  2021-08-02  9:12 ` [PATCH conntrack-tools 4/4] conntrack: add shorthand mnemonic for UNREPLIED Florian Westphal
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2021-08-02  9:12 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

This tells kernel to suppress conntrack entries that do not match
the status bits/bitmask filter.

This is useful to e.g. only list entries that are not assured
(value 0, mask == ASSUED) or entries that only saw one-way traffic
(value 0, mask == SEEN_REPLY).

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/internal/object.h                       |  1 +
 .../libnetfilter_conntrack.h                    |  5 +++--
 src/conntrack/filter_dump.c                     | 17 +++++++++++++++++
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/include/internal/object.h b/include/internal/object.h
index 3f6904f16d8b..75ffdbe97229 100644
--- a/include/internal/object.h
+++ b/include/internal/object.h
@@ -287,6 +287,7 @@ struct nfct_filter {
 
 struct nfct_filter_dump {
 	struct nfct_filter_dump_mark	mark;
+	struct nfct_filter_dump_mark	status;
 	uint8_t				l3num;
 	uint32_t			set;
 };
diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
index f02d827761a8..6233434cfeb8 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
@@ -137,11 +137,11 @@ enum nf_conntrack_attr {
 	ATTR_HELPER_INFO,			/* variable length */
 	ATTR_CONNLABELS,			/* variable length */
 	ATTR_CONNLABELS_MASK,			/* variable length */
-	ATTR_ORIG_ZONE,				/* u16 bits */
+	ATTR_ORIG_ZONE = 68,			/* u16 bits */
 	ATTR_REPL_ZONE,				/* u16 bits */
 	ATTR_SNAT_IPV6,				/* u128 bits */
 	ATTR_DNAT_IPV6,				/* u128 bits */
-	ATTR_SYNPROXY_ISN,			/* u32 bits */
+	ATTR_SYNPROXY_ISN = 72,			/* u32 bits */
 	ATTR_SYNPROXY_ITS,			/* u32 bits */
 	ATTR_SYNPROXY_TSOFF,			/* u32 bits */
 	ATTR_MAX
@@ -546,6 +546,7 @@ struct nfct_filter_dump_mark {
 enum nfct_filter_dump_attr {
 	NFCT_FILTER_DUMP_MARK = 0,	/* struct nfct_filter_dump_mark */
 	NFCT_FILTER_DUMP_L3NUM,		/* uint8_t */
+	NFCT_FILTER_DUMP_STATUS,	/* struct nfct_filter_dump_mark */
 	NFCT_FILTER_DUMP_MAX
 };
 
diff --git a/src/conntrack/filter_dump.c b/src/conntrack/filter_dump.c
index 158b4cb1155d..3894d0638a72 100644
--- a/src/conntrack/filter_dump.c
+++ b/src/conntrack/filter_dump.c
@@ -19,6 +19,16 @@ set_filter_dump_attr_mark(struct nfct_filter_dump *filter_dump,
 	filter_dump->mark.mask = this->mask;
 }
 
+static void
+set_filter_dump_attr_status(struct nfct_filter_dump *filter_dump,
+			    const void *value)
+{
+	const struct nfct_filter_dump_mark *this = value;
+
+	filter_dump->status.val = this->val;
+	filter_dump->status.mask = this->mask;
+}
+
 static void
 set_filter_dump_attr_family(struct nfct_filter_dump *filter_dump,
 			    const void *value)
@@ -29,6 +39,7 @@ set_filter_dump_attr_family(struct nfct_filter_dump *filter_dump,
 const set_filter_dump_attr set_filter_dump_attr_array[NFCT_FILTER_DUMP_MAX] = {
 	[NFCT_FILTER_DUMP_MARK]		= set_filter_dump_attr_mark,
 	[NFCT_FILTER_DUMP_L3NUM]	= set_filter_dump_attr_family,
+	[NFCT_FILTER_DUMP_STATUS]	= set_filter_dump_attr_status,
 };
 
 void __build_filter_dump(struct nfnlhdr *req, size_t size,
@@ -44,4 +55,10 @@ void __build_filter_dump(struct nfnlhdr *req, size_t size,
 		struct nfgenmsg *nfg = NLMSG_DATA(&req->nlh);
 		nfg->nfgen_family = filter_dump->l3num;
 	}
+	if (filter_dump->set & (1 << NFCT_FILTER_DUMP_STATUS)) {
+		nfnl_addattr32(&req->nlh, size, CTA_STATUS,
+				htonl(filter_dump->status.val));
+		nfnl_addattr32(&req->nlh, size, CTA_STATUS_MASK,
+				htonl(filter_dump->status.mask));
+	}
 }
-- 
2.31.1


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

* [PATCH conntrack-tools 3/4] conntrack: enable kernel-based status filtering with -L -u STATUS
  2021-08-02  9:12 [PATCH] conntrack-tools: support conntrack dump status filtering Florian Westphal
  2021-08-02  9:12 ` [PATCH lnf-conntrack 1/4] include: sync uapi header with nf-next Florian Westphal
  2021-08-02  9:12 ` [PATCH lnf-conntrack 2/4] src: add support for status dump filter Florian Westphal
@ 2021-08-02  9:12 ` Florian Westphal
  2021-08-02  9:12 ` [PATCH conntrack-tools 4/4] conntrack: add shorthand mnemonic for UNREPLIED Florian Westphal
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2021-08-02  9:12 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

This change is backwards compatible:

Old kernels do not recognize CTA_STATUS_MASK attribute and will
ignore it (no filtering in kernel).

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 src/conntrack.c | 59 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 4 deletions(-)

diff --git a/src/conntrack.c b/src/conntrack.c
index 987a52140633..cc564a2b4b1b 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -92,6 +92,10 @@ struct ct_tmpl {
 	struct nfct_filter_dump_mark filter_mark_kernel;
 	bool filter_mark_kernel_set;
 
+	/* Allow to filter by status from kernel-space. */
+	struct nfct_filter_dump_mark filter_status_kernel;
+	bool filter_status_kernel_set;
+
 	/* Allows filtering by ctlabels */
 	struct nfct_bitmask *label;
 
@@ -1146,7 +1150,7 @@ static struct parse_parameter {
 };
 
 static int
-do_parse_parameter(const char *str, size_t str_length, unsigned int *value, 
+do_parse_parameter(const char *str, size_t str_length, unsigned int *value,
 		   int parse_type)
 {
 	size_t i;
@@ -1171,7 +1175,7 @@ do_parse_parameter(const char *str, size_t str_length, unsigned int *value,
 			ret = 1;
 			break;
 		}
-	
+
 	return ret;
 }
 
@@ -1192,6 +1196,41 @@ parse_parameter(const char *arg, unsigned int *status, int parse_type)
 		exit_error(PARAMETER_PROBLEM, "Bad parameter `%s'", arg);
 }
 
+static void
+parse_parameter_mask(const char *arg, unsigned int *status, unsigned int *mask, int parse_type)
+{
+	unsigned int *value;
+	const char *comma;
+	bool negated;
+
+	while ((comma = strchr(arg, ',')) != NULL) {
+		if (comma == arg)
+			exit_error(PARAMETER_PROBLEM,"Bad parameter `%s'", arg);
+
+		negated = *arg == '!';
+		if (negated)
+			arg++;
+		if (comma == arg)
+			exit_error(PARAMETER_PROBLEM,"Bad parameter `%s'", arg);
+
+		value = negated ? mask : status;
+
+		if (!do_parse_parameter(arg, comma-arg, value, parse_type))
+			exit_error(PARAMETER_PROBLEM,"Bad parameter `%s'", arg);
+		arg = comma+1;
+	}
+
+	negated = *arg == '!';
+	if (negated)
+		arg++;
+	value = negated ? mask : status;
+
+	if (strlen(arg) == 0
+	    || !do_parse_parameter(arg, strlen(arg),
+		    value, parse_type))
+		exit_error(PARAMETER_PROBLEM, "Bad parameter `%s'", arg);
+}
+
 static void
 parse_u32_mask(const char *arg, struct u32_mask *m)
 {
@@ -2914,8 +2953,16 @@ static void do_parse(struct ct_cmd *ct_cmd, int argc, char *argv[])
 			break;
 		case 'u':
 			options |= CT_OPT_STATUS;
-			parse_parameter(optarg, &status, PARSE_STATUS);
+			parse_parameter_mask(optarg, &status,
+					    &tmpl->filter_status_kernel.mask,
+					    PARSE_STATUS);
 			nfct_set_attr_u32(tmpl->ct, ATTR_STATUS, status);
+			if (tmpl->filter_status_kernel.mask == 0)
+				tmpl->filter_status_kernel.mask = status;
+
+			tmpl->mark.value = status;
+			tmpl->filter_status_kernel.val = tmpl->mark.value;
+			tmpl->filter_status_kernel_set = true;
 			break;
 		case 'e':
 			options |= CT_OPT_EVENT_MASK;
@@ -3171,7 +3218,11 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 		nfct_filter_dump_set_attr_u8(filter_dump,
 					     NFCT_FILTER_DUMP_L3NUM,
 					     cmd->family);
-
+		if (cmd->tmpl.filter_status_kernel_set) {
+			nfct_filter_dump_set_attr(filter_dump,
+						  NFCT_FILTER_DUMP_STATUS,
+						  &cmd->tmpl.filter_status_kernel);
+		}
 		if (cmd->options & CT_OPT_ZERO)
 			res = nfct_query(cth, NFCT_Q_DUMP_FILTER_RESET,
 					filter_dump);
-- 
2.31.1


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

* [PATCH conntrack-tools 4/4] conntrack: add shorthand mnemonic for UNREPLIED
  2021-08-02  9:12 [PATCH] conntrack-tools: support conntrack dump status filtering Florian Westphal
                   ` (2 preceding siblings ...)
  2021-08-02  9:12 ` [PATCH conntrack-tools 3/4] conntrack: enable kernel-based status filtering with -L -u STATUS Florian Westphal
@ 2021-08-02  9:12 ` Florian Westphal
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2021-08-02  9:12 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

conntrack tool prints [UNREPLIED] if a conntrack entry lacks the
SEEN_REPLY bit.  Accept this as '-u' argument too.

If requested, mask is set to SEEN_REPLY and value remains 0 (bit not set).

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 src/conntrack.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/conntrack.c b/src/conntrack.c
index cc564a2b4b1b..ef7f604c9e97 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -1199,6 +1199,7 @@ parse_parameter(const char *arg, unsigned int *status, int parse_type)
 static void
 parse_parameter_mask(const char *arg, unsigned int *status, unsigned int *mask, int parse_type)
 {
+	static const char unreplied[] = "UNREPLIED";
 	unsigned int *value;
 	const char *comma;
 	bool negated;
@@ -1215,6 +1216,12 @@ parse_parameter_mask(const char *arg, unsigned int *status, unsigned int *mask,
 
 		value = negated ? mask : status;
 
+		if (!negated && strncmp(arg, unreplied, strlen(unreplied)) == 0) {
+			*mask |= IPS_SEEN_REPLY;
+			arg = comma+1;
+			continue;
+		}
+
 		if (!do_parse_parameter(arg, comma-arg, value, parse_type))
 			exit_error(PARAMETER_PROBLEM,"Bad parameter `%s'", arg);
 		arg = comma+1;
@@ -1225,6 +1232,11 @@ parse_parameter_mask(const char *arg, unsigned int *status, unsigned int *mask,
 		arg++;
 	value = negated ? mask : status;
 
+	if (!negated && strncmp(arg, unreplied, strlen(unreplied)) == 0) {
+		*mask |= IPS_SEEN_REPLY;
+		return;
+	}
+
 	if (strlen(arg) == 0
 	    || !do_parse_parameter(arg, strlen(arg),
 		    value, parse_type))
-- 
2.31.1


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

end of thread, other threads:[~2021-08-02  9:12 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-02  9:12 [PATCH] conntrack-tools: support conntrack dump status filtering Florian Westphal
2021-08-02  9:12 ` [PATCH lnf-conntrack 1/4] include: sync uapi header with nf-next Florian Westphal
2021-08-02  9:12 ` [PATCH lnf-conntrack 2/4] src: add support for status dump filter Florian Westphal
2021-08-02  9:12 ` [PATCH conntrack-tools 3/4] conntrack: enable kernel-based status filtering with -L -u STATUS Florian Westphal
2021-08-02  9:12 ` [PATCH conntrack-tools 4/4] conntrack: add shorthand mnemonic for UNREPLIED Florian Westphal

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