All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] conntrack: -A command implementation
@ 2022-06-29 17:09 Mikhail Sennikovsky
  2022-06-29 17:09 ` [PATCH v2 1/3] conntrack: generalize command parsing Mikhail Sennikovsky
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Mikhail Sennikovsky @ 2022-06-29 17:09 UTC (permalink / raw)
  To: netfilter-devel, pablo, mikhail.sennikovsky; +Cc: Mikhail Sennikovsky

Hi Pablo & all,

As discussed, here is an updated patch set for the -A command
support.
As you requested it introduces a separate CT_ADD command now.
In order to do that cleanly and error-safe I had to do two
preparation steps, which are included as two separate commits
with detailed description on each.

Comments/suggestions are very welcome.

Regards,
Mikhail

Mikhail Sennikovsky (3):
  conntrack: generalize command parsing
  conntrack: use C99 initializer syntax for opts map
  conntrack: introduce new -A command

 extensions/libct_proto_dccp.c     |  33 +++----
 extensions/libct_proto_gre.c      |  33 +++----
 extensions/libct_proto_icmp.c     |  33 +++----
 extensions/libct_proto_icmpv6.c   |  33 +++----
 extensions/libct_proto_sctp.c     |  33 +++----
 extensions/libct_proto_tcp.c      |  33 +++----
 extensions/libct_proto_udp.c      |  33 +++----
 extensions/libct_proto_udplite.c  |  33 +++----
 include/conntrack.h               |  68 +++++++++++++-
 src/conntrack.c                   | 150 ++++++++++--------------------
 tests/conntrack/testsuite/08stdin |  47 +++++++++-
 tests/conntrack/testsuite/10add   |  42 +++++++++
 12 files changed, 338 insertions(+), 233 deletions(-)
 create mode 100644 tests/conntrack/testsuite/10add

-- 
2.25.1


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

* [PATCH v2 1/3] conntrack: generalize command parsing
  2022-06-29 17:09 [PATCH v2 0/3] conntrack: -A command implementation Mikhail Sennikovsky
@ 2022-06-29 17:09 ` Mikhail Sennikovsky
  2022-06-29 17:09 ` [PATCH v2 2/3] conntrack: use C99 initializer syntax for opts map Mikhail Sennikovsky
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Mikhail Sennikovsky @ 2022-06-29 17:09 UTC (permalink / raw)
  To: netfilter-devel, pablo, mikhail.sennikovsky; +Cc: Mikhail Sennikovsky

Currently the -U command has a special case handling
in the do_parse because it does not have EXP_ counterpart.
Generalizing it would simplify adding support for new commands
w/o EXP_ counterpart.

As a preparation step for adding the new "-A" command support,
make the -U command be handled the same way as the rest.

Signed-off-by: Mikhail Sennikovsky <mikhail.sennikovskii@ionos.com>
---
 src/conntrack.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/src/conntrack.c b/src/conntrack.c
index d49ac1a..6c999f4 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -446,6 +446,7 @@ static const int cmd2type[][2] = {
 	['h']	= { CT_HELP,	CT_HELP },
 	['C']	= { CT_COUNT,	EXP_COUNT },
 	['S']	= { CT_STATS,	EXP_STATS },
+	['U']	= { CT_UPDATE,	0 },
 };
 
 static const int opt2type[] = {
@@ -2995,15 +2996,6 @@ static void do_parse(struct ct_cmd *ct_cmd, int argc, char *argv[])
 		case 'h':
 		case 'C':
 		case 'S':
-			type = check_type(argc, argv);
-			if (type == CT_TABLE_DYING ||
-			    type == CT_TABLE_UNCONFIRMED) {
-				exit_error(PARAMETER_PROBLEM,
-					   "Can't do that command with "
-					   "tables `dying' and `unconfirmed'");
-			}
-			add_command(&command, cmd2type[c][type]);
-			break;
 		case 'U':
 			type = check_type(argc, argv);
 			if (type == CT_TABLE_DYING ||
@@ -3011,11 +3003,16 @@ static void do_parse(struct ct_cmd *ct_cmd, int argc, char *argv[])
 				exit_error(PARAMETER_PROBLEM,
 					   "Can't do that command with "
 					   "tables `dying' and `unconfirmed'");
-			} else if (type == CT_TABLE_CONNTRACK)
-				add_command(&command, CT_UPDATE);
-			else
+			}
+			if (cmd2type[c][type])
+				add_command(&command, cmd2type[c][type]);
+			else {
 				exit_error(PARAMETER_PROBLEM,
-					   "Can't update expectations");
+					   "Can't %s %s",
+					   get_long_opt(c),
+					   type == CT_TABLE_CONNTRACK ?
+					           "ct" : "expectations");
+			}
 			break;
 		/* options */
 		case 's':
-- 
2.25.1


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

* [PATCH v2 2/3] conntrack: use C99 initializer syntax for opts map
  2022-06-29 17:09 [PATCH v2 0/3] conntrack: -A command implementation Mikhail Sennikovsky
  2022-06-29 17:09 ` [PATCH v2 1/3] conntrack: generalize command parsing Mikhail Sennikovsky
@ 2022-06-29 17:09 ` Mikhail Sennikovsky
  2022-06-29 17:09 ` [PATCH v2 3/3] conntrack: introduce new -A command Mikhail Sennikovsky
  2022-07-08 11:19 ` [PATCH v2 0/3] conntrack: -A command implementation Pablo Neira Ayuso
  3 siblings, 0 replies; 5+ messages in thread
From: Mikhail Sennikovsky @ 2022-06-29 17:09 UTC (permalink / raw)
  To: netfilter-devel, pablo, mikhail.sennikovsky; +Cc: Mikhail Sennikovsky

The old way of the commands_v_options initialization made it more
difficult and error-prone to add a map for a new command, because one
would have to calculate a proper "index" for the initializer and fill
the gap with zeros.

As a preparation step for adding the new "-A" command support,
switch to C99 initializer syntax for commands_v_options.

Signed-off-by: Mikhail Sennikovsky <mikhail.sennikovskii@ionos.com>
---
 extensions/libct_proto_dccp.c    |  32 +++++-----
 extensions/libct_proto_gre.c     |  32 +++++-----
 extensions/libct_proto_icmp.c    |  32 +++++-----
 extensions/libct_proto_icmpv6.c  |  32 +++++-----
 extensions/libct_proto_sctp.c    |  32 +++++-----
 extensions/libct_proto_tcp.c     |  32 +++++-----
 extensions/libct_proto_udp.c     |  32 +++++-----
 extensions/libct_proto_udplite.c |  32 +++++-----
 include/conntrack.h              |  65 +++++++++++++++++++-
 src/conntrack.c                  | 102 ++++++-------------------------
 10 files changed, 212 insertions(+), 211 deletions(-)

diff --git a/extensions/libct_proto_dccp.c b/extensions/libct_proto_dccp.c
index e9da474..6103117 100644
--- a/extensions/libct_proto_dccp.c
+++ b/extensions/libct_proto_dccp.c
@@ -67,22 +67,22 @@ static const char *dccp_optflags[DCCP_OPT_MAX] = {
 static char dccp_commands_v_options[NUMBER_OF_CMD][DCCP_OPT_MAX] =
 /* Well, it's better than "Re: Sevilla vs Betis" */
 {
-	    	/* 1 2 3 4 5 6 7 8 9 10*/
-/*CT_LIST*/   	  {2,2,2,2,0,0,2,0,0,0},
-/*CT_CREATE*/	  {3,3,3,3,0,0,1,0,0,1},
-/*CT_UPDATE*/	  {2,2,2,2,0,0,2,0,0,0},
-/*CT_DELETE*/	  {2,2,2,2,0,0,2,0,0,0},
-/*CT_GET*/	  {3,3,3,3,0,0,2,0,0,0},
-/*CT_FLUSH*/	  {0,0,0,0,0,0,0,0,0,0},
-/*CT_EVENT*/	  {2,2,2,2,0,0,2,0,0,0},
-/*CT_VERSION*/	  {0,0,0,0,0,0,0,0,0,0},
-/*CT_HELP*/	  {0,0,0,0,0,0,0,0,0,0},
-/*EXP_LIST*/	  {0,0,0,0,0,0,0,0,0,0},
-/*EXP_CREATE*/	  {1,1,0,0,1,1,0,1,1,1},
-/*EXP_DELETE*/	  {1,1,1,1,0,0,0,0,0,0},
-/*EXP_GET*/	  {1,1,1,1,0,0,0,0,0,0},
-/*EXP_FLUSH*/	  {0,0,0,0,0,0,0,0,0,0},
-/*EXP_EVENT*/	  {0,0,0,0,0,0,0,0,0,0},
+				/* 1 2 3 4 5 6 7 8 9 10 */
+	[CT_LIST_BIT]		= {2,2,2,2,0,0,2,0,0,0},
+	[CT_CREATE_BIT]		= {3,3,3,3,0,0,1,0,0,1},
+	[CT_UPDATE_BIT]		= {2,2,2,2,0,0,2,0,0,0},
+	[CT_DELETE_BIT]		= {2,2,2,2,0,0,2,0,0,0},
+	[CT_GET_BIT]		= {3,3,3,3,0,0,2,0,0,0},
+	[CT_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0,0},
+	[CT_EVENT_BIT]		= {2,2,2,2,0,0,2,0,0,0},
+	[CT_VERSION_BIT]	= {0,0,0,0,0,0,0,0,0,0},
+	[CT_HELP_BIT]		= {0,0,0,0,0,0,0,0,0,0},
+	[EXP_LIST_BIT]		= {0,0,0,0,0,0,0,0,0,0},
+	[EXP_CREATE_BIT]	= {1,1,0,0,1,1,0,1,1,1},
+	[EXP_DELETE_BIT]	= {1,1,1,1,0,0,0,0,0,0},
+	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0,0,0},
+	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0,0},
+	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0,0,0},
 };
 
 static const char *dccp_states[DCCP_CONNTRACK_MAX] = {
diff --git a/extensions/libct_proto_gre.c b/extensions/libct_proto_gre.c
index a36d111..c619db3 100644
--- a/extensions/libct_proto_gre.c
+++ b/extensions/libct_proto_gre.c
@@ -66,22 +66,22 @@ static void help(void)
 
 static char gre_commands_v_options[NUMBER_OF_CMD][GRE_OPT_MAX] =
 {
-		/* 1 2 3 4 5 6 7 8 */
-/*CT_LIST*/	  {2,2,2,2,0,0,0,0},
-/*CT_CREATE*/	  {3,3,3,3,0,0,0,0},
-/*CT_UPDATE*/	  {2,2,2,2,0,0,0,0},
-/*CT_DELETE*/	  {2,2,2,2,0,0,0,0},
-/*CT_GET*/	  {3,3,3,3,0,0,0,0},
-/*CT_FLUSH*/	  {0,0,0,0,0,0,0,0},
-/*CT_EVENT*/	  {2,2,2,2,0,0,0,0},
-/*CT_VERSION*/	  {0,0,0,0,0,0,0,0},
-/*CT_HELP*/	  {0,0,0,0,0,0,0,0},
-/*EXP_LIST*/	  {0,0,0,0,0,0,0,0},
-/*EXP_CREATE*/	  {1,1,1,1,1,1,1,1},
-/*EXP_DELETE*/	  {1,1,1,1,0,0,0,0},
-/*EXP_GET*/	  {1,1,1,1,0,0,0,0},
-/*EXP_FLUSH*/	  {0,0,0,0,0,0,0,0},
-/*EXP_EVENT*/	  {0,0,0,0,0,0,0,0},
+				/* 1 2 3 4 5 6 7 8 */
+	[CT_LIST_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_CREATE_BIT]		= {3,3,3,3,0,0,0,0},
+	[CT_UPDATE_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_DELETE_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_GET_BIT]		= {3,3,3,3,0,0,0,0},
+	[CT_FLUSH_BIT]		= {0,0,0,0,0,0,0,0},
+	[CT_EVENT_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_VERSION_BIT]	= {0,0,0,0,0,0,0,0},
+	[CT_HELP_BIT]		= {0,0,0,0,0,0,0,0},
+	[EXP_LIST_BIT]		= {0,0,0,0,0,0,0,0},
+	[EXP_CREATE_BIT]	= {1,1,1,1,1,1,1,1},
+	[EXP_DELETE_BIT]	= {1,1,1,1,0,0,0,0},
+	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0},
+	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0},
+	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0},
 };
 
 static int parse_options(char c,
diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c
index ec52c39..304018f 100644
--- a/extensions/libct_proto_icmp.c
+++ b/extensions/libct_proto_icmp.c
@@ -40,22 +40,22 @@ static const char *icmp_optflags[ICMP_NUMBER_OF_OPT] = {
 static char icmp_commands_v_options[NUMBER_OF_CMD][ICMP_NUMBER_OF_OPT] =
 /* Well, it's better than "Re: Maradona vs Pele" */
 {
-		/* 1 2 3 */
-/*CT_LIST*/	  {2,2,2},
-/*CT_CREATE*/	  {1,1,2},
-/*CT_UPDATE*/	  {2,2,2},
-/*CT_DELETE*/	  {2,2,2},
-/*CT_GET*/	  {1,1,2},
-/*CT_FLUSH*/	  {0,0,0},
-/*CT_EVENT*/	  {2,2,2},
-/*CT_VERSION*/	  {0,0,0},
-/*CT_HELP*/	  {0,0,0},
-/*EXP_LIST*/	  {0,0,0},
-/*EXP_CREATE*/	  {0,0,0},
-/*EXP_DELETE*/	  {0,0,0},
-/*EXP_GET*/	  {0,0,0},
-/*EXP_FLUSH*/	  {0,0,0},
-/*EXP_EVENT*/	  {0,0,0},
+				/* 1 2 3 */
+	[CT_LIST_BIT]		= {2,2,2},
+	[CT_CREATE_BIT]		= {1,1,2},
+	[CT_UPDATE_BIT]		= {2,2,2},
+	[CT_DELETE_BIT]		= {2,2,2},
+	[CT_GET_BIT]		= {1,1,2},
+	[CT_FLUSH_BIT]		= {0,0,0},
+	[CT_EVENT_BIT]		= {2,2,2},
+	[CT_VERSION_BIT]	= {0,0,0},
+	[CT_HELP_BIT]		= {0,0,0},
+	[EXP_LIST_BIT]		= {0,0,0},
+	[EXP_CREATE_BIT]	= {0,0,0},
+	[EXP_DELETE_BIT]	= {0,0,0},
+	[EXP_GET_BIT]		= {0,0,0},
+	[EXP_FLUSH_BIT]		= {0,0,0},
+	[EXP_EVENT_BIT]		= {0,0,0},
 };
 
 static void help(void)
diff --git a/extensions/libct_proto_icmpv6.c b/extensions/libct_proto_icmpv6.c
index fe16a1d..114bcac 100644
--- a/extensions/libct_proto_icmpv6.c
+++ b/extensions/libct_proto_icmpv6.c
@@ -43,22 +43,22 @@ static const char *icmpv6_optflags[ICMPV6_NUMBER_OF_OPT] = {
 static char icmpv6_commands_v_options[NUMBER_OF_CMD][ICMPV6_NUMBER_OF_OPT] =
 /* Well, it's better than "Re: Maradona vs Pele" */
 {
-		/* 1 2 3 */
-/*CT_LIST*/	  {2,2,2},
-/*CT_CREATE*/	  {1,1,2},
-/*CT_UPDATE*/	  {2,2,2},
-/*CT_DELETE*/	  {2,2,2},
-/*CT_GET*/	  {1,1,2},
-/*CT_FLUSH*/	  {0,0,0},
-/*CT_EVENT*/	  {2,2,2},
-/*CT_VERSION*/	  {0,0,0},
-/*CT_HELP*/	  {0,0,0},
-/*EXP_LIST*/	  {0,0,0},
-/*EXP_CREATE*/	  {0,0,0},
-/*EXP_DELETE*/	  {0,0,0},
-/*EXP_GET*/	  {0,0,0},
-/*EXP_FLUSH*/	  {0,0,0},
-/*EXP_EVENT*/	  {0,0,0},
+				/* 1 2 3 */
+	[CT_LIST_BIT]		= {2,2,2},
+	[CT_CREATE_BIT]		= {1,1,2},
+	[CT_UPDATE_BIT]		= {2,2,2},
+	[CT_DELETE_BIT]		= {2,2,2},
+	[CT_GET_BIT]		= {1,1,2},
+	[CT_FLUSH_BIT]		= {0,0,0},
+	[CT_EVENT_BIT]		= {2,2,2},
+	[CT_VERSION_BIT]	= {0,0,0},
+	[CT_HELP_BIT]		= {0,0,0},
+	[EXP_LIST_BIT]		= {0,0,0},
+	[EXP_CREATE_BIT]	= {0,0,0},
+	[EXP_DELETE_BIT]	= {0,0,0},
+	[EXP_GET_BIT]		= {0,0,0},
+	[EXP_FLUSH_BIT]		= {0,0,0},
+	[EXP_EVENT_BIT]		= {0,0,0},
 };
 
 static void help(void)
diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c
index a58ccde..723a2cd 100644
--- a/extensions/libct_proto_sctp.c
+++ b/extensions/libct_proto_sctp.c
@@ -70,22 +70,22 @@ static const char *sctp_optflags[SCTP_OPT_MAX] = {
 static char sctp_commands_v_options[NUMBER_OF_CMD][SCTP_OPT_MAX] =
 /* Well, it's better than "Re: Sevilla vs Betis" */
 {
-	    	/* 1 2 3 4 5 6 7 8 9 10 11*/
-/*CT_LIST*/   	  {2,2,2,2,0,0,2,0,0,0,0},
-/*CT_CREATE*/	  {3,3,3,3,0,0,1,0,0,1,1},
-/*CT_UPDATE*/	  {2,2,2,2,0,0,2,0,0,2,2},
-/*CT_DELETE*/	  {2,2,2,2,0,0,2,0,0,0,0},
-/*CT_GET*/	  {3,3,3,3,0,0,2,0,0,2,2},
-/*CT_FLUSH*/	  {0,0,0,0,0,0,0,0,0,0,0},
-/*CT_EVENT*/	  {2,2,2,2,0,0,2,0,0,0,0},
-/*CT_VERSION*/	  {0,0,0,0,0,0,0,0,0,0,0},
-/*CT_HELP*/	  {0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_LIST*/	  {0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_CREATE*/	  {1,1,0,0,1,1,0,1,1,1,1},
-/*EXP_DELETE*/	  {1,1,1,1,0,0,0,0,0,0,0},
-/*EXP_GET*/	  {1,1,1,1,0,0,0,0,0,0,0},
-/*EXP_FLUSH*/	  {0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_EVENT*/	  {0,0,0,0,0,0,0,0,0,0,0},
+				/* 1 2 3 4 5 6 7 8 9 10 11 */
+	[CT_LIST_BIT]		= {2,2,2,2,0,0,2,0,0,0,0},
+	[CT_CREATE_BIT]		= {3,3,3,3,0,0,1,0,0,1,1},
+	[CT_UPDATE_BIT]		= {2,2,2,2,0,0,2,0,0,2,2},
+	[CT_DELETE_BIT]		= {2,2,2,2,0,0,2,0,0,0,0},
+	[CT_GET_BIT]		= {3,3,3,3,0,0,2,0,0,2,2},
+	[CT_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0,0,0},
+	[CT_EVENT_BIT]		= {2,2,2,2,0,0,2,0,0,0,0},
+	[CT_VERSION_BIT]	= {0,0,0,0,0,0,0,0,0,0,0},
+	[CT_HELP_BIT]		= {0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_LIST_BIT]		= {0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_CREATE_BIT]	= {1,1,0,0,1,1,0,1,1,1,1},
+	[EXP_DELETE_BIT]	= {1,1,1,1,0,0,0,0,0,0,0},
+	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0,0,0,0},
+	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0,0,0,0},
 };
 
 static const char *sctp_states[SCTP_CONNTRACK_MAX] = {
diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c
index 3da0dc6..7e4500c 100644
--- a/extensions/libct_proto_tcp.c
+++ b/extensions/libct_proto_tcp.c
@@ -54,22 +54,22 @@ static const char *tcp_optflags[TCP_NUMBER_OF_OPT] = {
 static char tcp_commands_v_options[NUMBER_OF_CMD][TCP_NUMBER_OF_OPT] =
 /* Well, it's better than "Re: Sevilla vs Betis" */
 {
-	    	/* 1 2 3 4 5 6 7 8 9 */
-/*CT_LIST*/   	  {2,2,2,2,0,0,2,0,0},
-/*CT_CREATE*/	  {3,3,3,3,0,0,1,0,0},
-/*CT_UPDATE*/	  {2,2,2,2,0,0,2,0,0},
-/*CT_DELETE*/	  {2,2,2,2,0,0,2,0,0},
-/*CT_GET*/	  {3,3,3,3,0,0,2,0,0},
-/*CT_FLUSH*/	  {0,0,0,0,0,0,0,0,0},
-/*CT_EVENT*/	  {2,2,2,2,0,0,2,0,0},
-/*CT_VERSION*/	  {0,0,0,0,0,0,0,0,0},
-/*CT_HELP*/	  {0,0,0,0,0,0,0,0,0},
-/*EXP_LIST*/	  {0,0,0,0,0,0,0,0,0},
-/*EXP_CREATE*/	  {1,1,0,0,1,1,0,1,1},
-/*EXP_DELETE*/	  {1,1,1,1,0,0,0,0,0},
-/*EXP_GET*/	  {1,1,1,1,0,0,0,0,0},
-/*EXP_FLUSH*/	  {0,0,0,0,0,0,0,0,0},
-/*EXP_EVENT*/	  {0,0,0,0,0,0,0,0,0},
+				/* 1 2 3 4 5 6 7 8 9 */
+	[CT_LIST_BIT]		= {2,2,2,2,0,0,2,0,0},
+	[CT_CREATE_BIT]		= {3,3,3,3,0,0,1,0,0},
+	[CT_UPDATE_BIT]		= {2,2,2,2,0,0,2,0,0},
+	[CT_DELETE_BIT]		= {2,2,2,2,0,0,2,0,0},
+	[CT_GET_BIT]		= {3,3,3,3,0,0,2,0,0},
+	[CT_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0},
+	[CT_EVENT_BIT]		= {2,2,2,2,0,0,2,0,0},
+	[CT_VERSION_BIT]	= {0,0,0,0,0,0,0,0,0},
+	[CT_HELP_BIT]		= {0,0,0,0,0,0,0,0,0},
+	[EXP_LIST_BIT]		= {0,0,0,0,0,0,0,0,0},
+	[EXP_CREATE_BIT]	= {1,1,0,0,1,1,0,1,1},
+	[EXP_DELETE_BIT]	= {1,1,1,1,0,0,0,0,0},
+	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0,0},
+	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0},
+	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0,0},
 };
 
 static const char *tcp_states[TCP_CONNTRACK_MAX] = {
diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c
index fe43548..fce489d 100644
--- a/extensions/libct_proto_udp.c
+++ b/extensions/libct_proto_udp.c
@@ -62,22 +62,22 @@ static void help(void)
 static char udp_commands_v_options[NUMBER_OF_CMD][UDP_NUMBER_OF_OPT] =
 /* Well, it's better than "Re: Galeano vs Vargas Llosa" */
 {
-		/* 1 2 3 4 5 6 7 8 */
-/*CT_LIST*/	  {2,2,2,2,0,0,0,0},
-/*CT_CREATE*/     {3,3,3,3,0,0,0,0},
-/*CT_UPDATE*/     {2,2,2,2,0,0,0,0},
-/*CT_DELETE*/     {2,2,2,2,0,0,0,0},
-/*CT_GET*/        {3,3,3,3,0,0,0,0},
-/*CT_FLUSH*/      {0,0,0,0,0,0,0,0},
-/*CT_EVENT*/      {2,2,2,2,0,0,0,0},
-/*CT_VERSION*/    {0,0,0,0,0,0,0,0},
-/*CT_HELP*/       {0,0,0,0,0,0,0,0},
-/*EXP_LIST*/      {0,0,0,0,0,0,0,0},
-/*EXP_CREATE*/    {1,1,0,0,1,1,1,1},
-/*EXP_DELETE*/    {1,1,1,1,0,0,0,0},
-/*EXP_GET*/       {1,1,1,1,0,0,0,0},
-/*EXP_FLUSH*/     {0,0,0,0,0,0,0,0},
-/*EXP_EVENT*/     {0,0,0,0,0,0,0,0},
+				/* 1 2 3 4 5 6 7 8 */
+	[CT_LIST_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_CREATE_BIT]		= {3,3,3,3,0,0,0,0},
+	[CT_UPDATE_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_DELETE_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_GET_BIT]		= {3,3,3,3,0,0,0,0},
+	[CT_FLUSH_BIT]		= {0,0,0,0,0,0,0,0},
+	[CT_EVENT_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_VERSION_BIT]	= {0,0,0,0,0,0,0,0},
+	[CT_HELP_BIT]		= {0,0,0,0,0,0,0,0},
+	[EXP_LIST_BIT]		= {0,0,0,0,0,0,0,0},
+	[EXP_CREATE_BIT]	= {1,1,0,0,1,1,1,1},
+	[EXP_DELETE_BIT]	= {1,1,1,1,0,0,0,0},
+	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0},
+	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0},
+	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0},
 };
 
 static int parse_options(char c,
diff --git a/extensions/libct_proto_udplite.c b/extensions/libct_proto_udplite.c
index 2bece38..8d42d1a 100644
--- a/extensions/libct_proto_udplite.c
+++ b/extensions/libct_proto_udplite.c
@@ -70,22 +70,22 @@ static void help(void)
 
 static char udplite_commands_v_options[NUMBER_OF_CMD][UDP_OPT_MAX] =
 {
-		/* 1 2 3 4 5 6 7 8 */
-/*CT_LIST*/	  {2,2,2,2,0,0,0,0},
-/*CT_CREATE*/	  {3,3,3,3,0,0,0,0},
-/*CT_UPDATE*/	  {2,2,2,2,0,0,0,0},
-/*CT_DELETE*/	  {2,2,2,2,0,0,0,0},
-/*CT_GET*/	  {3,3,3,3,0,0,0,0},
-/*CT_FLUSH*/	  {0,0,0,0,0,0,0,0},
-/*CT_EVENT*/	  {2,2,2,2,0,0,0,0},
-/*CT_VERSION*/	  {0,0,0,0,0,0,0,0},
-/*CT_HELP*/	  {0,0,0,0,0,0,0,0},
-/*EXP_LIST*/	  {0,0,0,0,0,0,0,0},
-/*EXP_CREATE*/	  {1,1,0,0,1,1,1,1},
-/*EXP_DELETE*/	  {1,1,1,1,0,0,0,0},
-/*EXP_GET*/	  {1,1,1,1,0,0,0,0},
-/*EXP_FLUSH*/	  {0,0,0,0,0,0,0,0},
-/*EXP_EVENT*/	  {0,0,0,0,0,0,0,0},
+				/* 1 2 3 4 5 6 7 8 */
+	[CT_LIST_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_CREATE_BIT]		= {3,3,3,3,0,0,0,0},
+	[CT_UPDATE_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_DELETE_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_GET_BIT]		= {3,3,3,3,0,0,0,0},
+	[CT_FLUSH_BIT]		= {0,0,0,0,0,0,0,0},
+	[CT_EVENT_BIT]		= {2,2,2,2,0,0,0,0},
+	[CT_VERSION_BIT]	= {0,0,0,0,0,0,0,0},
+	[CT_HELP_BIT]		= {0,0,0,0,0,0,0,0},
+	[EXP_LIST_BIT]		= {0,0,0,0,0,0,0,0},
+	[EXP_CREATE_BIT]	= {1,1,0,0,1,1,1,1},
+	[EXP_DELETE_BIT]	= {1,1,1,1,0,0,0,0},
+	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0},
+	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0},
+	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0},
 };
 
 static int parse_options(char c,
diff --git a/include/conntrack.h b/include/conntrack.h
index 1c1720e..bc17af0 100644
--- a/include/conntrack.h
+++ b/include/conntrack.h
@@ -11,7 +11,70 @@
 #include <linux/netfilter/nf_conntrack_common.h>
 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
 
-#define NUMBER_OF_CMD   19
+enum ct_command {
+	CT_NONE		= 0,
+
+	CT_LIST_BIT 	= 0,
+	CT_LIST 	= (1 << CT_LIST_BIT),
+
+	CT_CREATE_BIT	= 1,
+	CT_CREATE	= (1 << CT_CREATE_BIT),
+
+	CT_UPDATE_BIT	= 2,
+	CT_UPDATE	= (1 << CT_UPDATE_BIT),
+
+	CT_DELETE_BIT	= 3,
+	CT_DELETE	= (1 << CT_DELETE_BIT),
+
+	CT_GET_BIT	= 4,
+	CT_GET		= (1 << CT_GET_BIT),
+
+	CT_FLUSH_BIT	= 5,
+	CT_FLUSH	= (1 << CT_FLUSH_BIT),
+
+	CT_EVENT_BIT	= 6,
+	CT_EVENT	= (1 << CT_EVENT_BIT),
+
+	CT_VERSION_BIT	= 7,
+	CT_VERSION	= (1 << CT_VERSION_BIT),
+
+	CT_HELP_BIT	= 8,
+	CT_HELP		= (1 << CT_HELP_BIT),
+
+	EXP_LIST_BIT 	= 9,
+	EXP_LIST 	= (1 << EXP_LIST_BIT),
+
+	EXP_CREATE_BIT	= 10,
+	EXP_CREATE	= (1 << EXP_CREATE_BIT),
+
+	EXP_DELETE_BIT	= 11,
+	EXP_DELETE	= (1 << EXP_DELETE_BIT),
+
+	EXP_GET_BIT	= 12,
+	EXP_GET		= (1 << EXP_GET_BIT),
+
+	EXP_FLUSH_BIT	= 13,
+	EXP_FLUSH	= (1 << EXP_FLUSH_BIT),
+
+	EXP_EVENT_BIT	= 14,
+	EXP_EVENT	= (1 << EXP_EVENT_BIT),
+
+	CT_COUNT_BIT	= 15,
+	CT_COUNT	= (1 << CT_COUNT_BIT),
+
+	EXP_COUNT_BIT	= 16,
+	EXP_COUNT	= (1 << EXP_COUNT_BIT),
+
+	CT_STATS_BIT	= 17,
+	CT_STATS	= (1 << CT_STATS_BIT),
+
+	EXP_STATS_BIT	= 18,
+	EXP_STATS	= (1 << EXP_STATS_BIT),
+
+	_CT_BIT_MAX	= 19,
+};
+
+#define NUMBER_OF_CMD   _CT_BIT_MAX
 #define NUMBER_OF_OPT   29
 
 struct nf_conntrack;
diff --git a/src/conntrack.c b/src/conntrack.c
index 6c999f4..e96e42d 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -153,68 +153,6 @@ static void free_tmpl_objects(struct ct_tmpl *tmpl)
 		nfct_bitmask_destroy(tmpl->label_modify);
 }
 
-enum ct_command {
-	CT_NONE		= 0,
-
-	CT_LIST_BIT 	= 0,
-	CT_LIST 	= (1 << CT_LIST_BIT),
-
-	CT_CREATE_BIT	= 1,
-	CT_CREATE	= (1 << CT_CREATE_BIT),
-
-	CT_UPDATE_BIT	= 2,
-	CT_UPDATE	= (1 << CT_UPDATE_BIT),
-
-	CT_DELETE_BIT	= 3,
-	CT_DELETE	= (1 << CT_DELETE_BIT),
-
-	CT_GET_BIT	= 4,
-	CT_GET		= (1 << CT_GET_BIT),
-
-	CT_FLUSH_BIT	= 5,
-	CT_FLUSH	= (1 << CT_FLUSH_BIT),
-
-	CT_EVENT_BIT	= 6,
-	CT_EVENT	= (1 << CT_EVENT_BIT),
-
-	CT_VERSION_BIT	= 7,
-	CT_VERSION	= (1 << CT_VERSION_BIT),
-
-	CT_HELP_BIT	= 8,
-	CT_HELP		= (1 << CT_HELP_BIT),
-
-	EXP_LIST_BIT 	= 9,
-	EXP_LIST 	= (1 << EXP_LIST_BIT),
-
-	EXP_CREATE_BIT	= 10,
-	EXP_CREATE	= (1 << EXP_CREATE_BIT),
-
-	EXP_DELETE_BIT	= 11,
-	EXP_DELETE	= (1 << EXP_DELETE_BIT),
-
-	EXP_GET_BIT	= 12,
-	EXP_GET		= (1 << EXP_GET_BIT),
-
-	EXP_FLUSH_BIT	= 13,
-	EXP_FLUSH	= (1 << EXP_FLUSH_BIT),
-
-	EXP_EVENT_BIT	= 14,
-	EXP_EVENT	= (1 << EXP_EVENT_BIT),
-
-	CT_COUNT_BIT	= 15,
-	CT_COUNT	= (1 << CT_COUNT_BIT),
-
-	EXP_COUNT_BIT	= 16,
-	EXP_COUNT	= (1 << EXP_COUNT_BIT),
-
-	CT_STATS_BIT	= 17,
-	CT_STATS	= (1 << CT_STATS_BIT),
-
-	EXP_STATS_BIT	= 18,
-	EXP_STATS	= (1 << EXP_STATS_BIT),
-};
-/* If you add a new command, you have to update NUMBER_OF_CMD in conntrack.h */
-
 enum ct_options {
 	CT_OPT_ORIG_SRC_BIT	= 0,
 	CT_OPT_ORIG_SRC 	= (1 << CT_OPT_ORIG_SRC_BIT),
@@ -413,26 +351,26 @@ static const char *getopt_str = ":L::I::U::D::G::E::F::hVs:d:r:q:"
 static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
 /* Well, it's better than "Re: Linux vs FreeBSD" */
 {
-          /*   s d r q p t u z e [ ] { } a m i f n g o c b j w l < > ( ) */
-/*CT_LIST*/   {2,2,2,2,2,0,2,2,0,0,0,2,2,0,2,0,2,2,2,2,2,0,2,2,2,0,0,2,2},
-/*CT_CREATE*/ {3,3,3,3,1,1,2,0,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2,0,2,0,2,2},
-/*CT_UPDATE*/ {2,2,2,2,2,2,2,0,0,0,0,2,2,0,2,2,2,2,2,2,0,0,0,0,2,2,2,0,0},
-/*CT_DELETE*/ {2,2,2,2,2,2,2,0,0,0,0,2,2,0,2,2,2,2,2,2,0,0,0,2,2,0,0,2,2},
-/*CT_GET*/    {3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,2,0,0,0,0},
-/*CT_FLUSH*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0},
-/*CT_EVENT*/  {2,2,2,2,2,0,0,0,2,0,0,2,2,0,2,0,2,2,2,2,2,2,2,2,2,0,0,2,2},
-/*VERSION*/   {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*HELP*/      {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_LIST*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,0},
-/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_GET*/   {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0},
-/*CT_COUNT*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*CT_STATS*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+				/* s d r q p t u z e [ ] { } a m i f n g o c b j w l < > ( ) */
+	[CT_LIST_BIT]		= {2,2,2,2,2,0,2,2,0,0,0,2,2,0,2,0,2,2,2,2,2,0,2,2,2,0,0,2,2},
+	[CT_CREATE_BIT]		= {3,3,3,3,1,1,2,0,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2,0,2,0,2,2},
+	[CT_UPDATE_BIT]		= {2,2,2,2,2,2,2,0,0,0,0,2,2,0,2,2,2,2,2,2,0,0,0,0,2,2,2,0,0},
+	[CT_DELETE_BIT]		= {2,2,2,2,2,2,2,0,0,0,0,2,2,0,2,2,2,2,2,2,0,0,0,2,2,0,0,2,2},
+	[CT_GET_BIT]		= {3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,2,0,0,0,0},
+	[CT_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0},
+	[CT_EVENT_BIT]		= {2,2,2,2,2,0,0,0,2,0,0,2,2,0,2,0,2,2,2,2,2,2,2,2,2,0,0,2,2},
+	[CT_VERSION_BIT]	= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[CT_HELP_BIT]		= {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_LIST_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,0},
+	[EXP_CREATE_BIT]	= {1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_DELETE_BIT]	= {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_GET_BIT]		= {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0},
+	[CT_COUNT_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_COUNT_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[CT_STATS_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[EXP_STATS_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 };
 
 static const int cmd2type[][2] = {
-- 
2.25.1


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

* [PATCH v2 3/3] conntrack: introduce new -A command
  2022-06-29 17:09 [PATCH v2 0/3] conntrack: -A command implementation Mikhail Sennikovsky
  2022-06-29 17:09 ` [PATCH v2 1/3] conntrack: generalize command parsing Mikhail Sennikovsky
  2022-06-29 17:09 ` [PATCH v2 2/3] conntrack: use C99 initializer syntax for opts map Mikhail Sennikovsky
@ 2022-06-29 17:09 ` Mikhail Sennikovsky
  2022-07-08 11:19 ` [PATCH v2 0/3] conntrack: -A command implementation Pablo Neira Ayuso
  3 siblings, 0 replies; 5+ messages in thread
From: Mikhail Sennikovsky @ 2022-06-29 17:09 UTC (permalink / raw)
  To: netfilter-devel, pablo, mikhail.sennikovsky; +Cc: Mikhail Sennikovsky

The -A command works exactly the same way as -I except that it
does not fail if the ct entry already exists.
This command is useful for the batched ct loads to not abort if
some entries being applied exist.

The ct entry dump in the "save" format is now switched to use the
-A command as well for the generated output.
Also tests added to cover the -A command.

Signed-off-by: Mikhail Sennikovsky <mikhail.sennikovskii@ionos.com>
---
 extensions/libct_proto_dccp.c     |  1 +
 extensions/libct_proto_gre.c      |  1 +
 extensions/libct_proto_icmp.c     |  1 +
 extensions/libct_proto_icmpv6.c   |  1 +
 extensions/libct_proto_sctp.c     |  1 +
 extensions/libct_proto_tcp.c      |  1 +
 extensions/libct_proto_udp.c      |  1 +
 extensions/libct_proto_udplite.c  |  1 +
 include/conntrack.h               |  5 +++-
 src/conntrack.c                   | 25 ++++++++++------
 tests/conntrack/testsuite/08stdin | 47 ++++++++++++++++++++++++++++++-
 tests/conntrack/testsuite/10add   | 42 +++++++++++++++++++++++++++
 12 files changed, 117 insertions(+), 10 deletions(-)
 create mode 100644 tests/conntrack/testsuite/10add

diff --git a/extensions/libct_proto_dccp.c b/extensions/libct_proto_dccp.c
index 6103117..0204929 100644
--- a/extensions/libct_proto_dccp.c
+++ b/extensions/libct_proto_dccp.c
@@ -83,6 +83,7 @@ static char dccp_commands_v_options[NUMBER_OF_CMD][DCCP_OPT_MAX] =
 	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0,0,0},
 	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0,0},
 	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0,0,0},
+	[CT_ADD_BIT]		= {3,3,3,3,0,0,1,0,0,1},
 };
 
 static const char *dccp_states[DCCP_CONNTRACK_MAX] = {
diff --git a/extensions/libct_proto_gre.c b/extensions/libct_proto_gre.c
index c619db3..2f216b9 100644
--- a/extensions/libct_proto_gre.c
+++ b/extensions/libct_proto_gre.c
@@ -82,6 +82,7 @@ static char gre_commands_v_options[NUMBER_OF_CMD][GRE_OPT_MAX] =
 	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0},
 	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0},
 	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0},
+	[CT_ADD_BIT]		= {3,3,3,3,0,0,0,0},
 };
 
 static int parse_options(char c,
diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c
index 304018f..9f67cf4 100644
--- a/extensions/libct_proto_icmp.c
+++ b/extensions/libct_proto_icmp.c
@@ -56,6 +56,7 @@ static char icmp_commands_v_options[NUMBER_OF_CMD][ICMP_NUMBER_OF_OPT] =
 	[EXP_GET_BIT]		= {0,0,0},
 	[EXP_FLUSH_BIT]		= {0,0,0},
 	[EXP_EVENT_BIT]		= {0,0,0},
+	[CT_ADD_BIT]		= {1,1,2},
 };
 
 static void help(void)
diff --git a/extensions/libct_proto_icmpv6.c b/extensions/libct_proto_icmpv6.c
index 114bcac..216757e 100644
--- a/extensions/libct_proto_icmpv6.c
+++ b/extensions/libct_proto_icmpv6.c
@@ -59,6 +59,7 @@ static char icmpv6_commands_v_options[NUMBER_OF_CMD][ICMPV6_NUMBER_OF_OPT] =
 	[EXP_GET_BIT]		= {0,0,0},
 	[EXP_FLUSH_BIT]		= {0,0,0},
 	[EXP_EVENT_BIT]		= {0,0,0},
+	[CT_ADD_BIT]		= {1,1,2},
 };
 
 static void help(void)
diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c
index 723a2cd..8099b83 100644
--- a/extensions/libct_proto_sctp.c
+++ b/extensions/libct_proto_sctp.c
@@ -86,6 +86,7 @@ static char sctp_commands_v_options[NUMBER_OF_CMD][SCTP_OPT_MAX] =
 	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0,0,0,0},
 	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0,0,0},
 	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0,0,0,0},
+	[CT_ADD_BIT]		= {3,3,3,3,0,0,1,0,0,1,1},
 };
 
 static const char *sctp_states[SCTP_CONNTRACK_MAX] = {
diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c
index 7e4500c..27f5833 100644
--- a/extensions/libct_proto_tcp.c
+++ b/extensions/libct_proto_tcp.c
@@ -70,6 +70,7 @@ static char tcp_commands_v_options[NUMBER_OF_CMD][TCP_NUMBER_OF_OPT] =
 	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0,0},
 	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0,0},
 	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0,0},
+	[CT_ADD_BIT]		= {3,3,3,3,0,0,1,0,0},
 };
 
 static const char *tcp_states[TCP_CONNTRACK_MAX] = {
diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c
index fce489d..a78857f 100644
--- a/extensions/libct_proto_udp.c
+++ b/extensions/libct_proto_udp.c
@@ -78,6 +78,7 @@ static char udp_commands_v_options[NUMBER_OF_CMD][UDP_NUMBER_OF_OPT] =
 	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0},
 	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0},
 	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0},
+	[CT_ADD_BIT]		= {3,3,3,3,0,0,0,0},
 };
 
 static int parse_options(char c,
diff --git a/extensions/libct_proto_udplite.c b/extensions/libct_proto_udplite.c
index 8d42d1a..3df3142 100644
--- a/extensions/libct_proto_udplite.c
+++ b/extensions/libct_proto_udplite.c
@@ -86,6 +86,7 @@ static char udplite_commands_v_options[NUMBER_OF_CMD][UDP_OPT_MAX] =
 	[EXP_GET_BIT]		= {1,1,1,1,0,0,0,0},
 	[EXP_FLUSH_BIT]		= {0,0,0,0,0,0,0,0},
 	[EXP_EVENT_BIT]		= {0,0,0,0,0,0,0,0},
+	[CT_ADD_BIT]		= {3,3,3,3,0,0,0,0},
 };
 
 static int parse_options(char c,
diff --git a/include/conntrack.h b/include/conntrack.h
index bc17af0..6dad4a1 100644
--- a/include/conntrack.h
+++ b/include/conntrack.h
@@ -71,7 +71,10 @@ enum ct_command {
 	EXP_STATS_BIT	= 18,
 	EXP_STATS	= (1 << EXP_STATS_BIT),
 
-	_CT_BIT_MAX	= 19,
+	CT_ADD_BIT	= 19,
+	CT_ADD		= (1 << CT_ADD_BIT),
+
+	_CT_BIT_MAX	= 20,
 };
 
 #define NUMBER_OF_CMD   _CT_BIT_MAX
diff --git a/src/conntrack.c b/src/conntrack.c
index e96e42d..763e4d6 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -291,6 +291,7 @@ static const char *optflags[NUMBER_OF_OPT] = {
 static struct option original_opts[] = {
 	{"dump", 2, 0, 'L'},
 	{"create", 2, 0, 'I'},
+	{"add", 2, 0, 'A'},
 	{"delete", 2, 0, 'D'},
 	{"update", 2, 0, 'U'},
 	{"get", 2, 0, 'G'},
@@ -334,7 +335,7 @@ static struct option original_opts[] = {
 	{0, 0, 0, 0}
 };
 
-static const char *getopt_str = ":L::I::U::D::G::E::F::hVs:d:r:q:"
+static const char *getopt_str = ":L::I::U::D::G::E::F::A::hVs:d:r:q:"
 				"p:t:u:e:a:z[:]:{:}:m:i:f:o:n::"
 				"g::c:b:C::Sj::w:l:<:>::(:):";
 
@@ -371,6 +372,7 @@ static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
 	[EXP_COUNT_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 	[CT_STATS_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 	[EXP_STATS_BIT]		= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+	[CT_ADD_BIT]		= {3,3,3,3,1,1,2,0,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2,0,2,0,2,2},
 };
 
 static const int cmd2type[][2] = {
@@ -385,6 +387,7 @@ static const int cmd2type[][2] = {
 	['C']	= { CT_COUNT,	EXP_COUNT },
 	['S']	= { CT_STATS,	EXP_STATS },
 	['U']	= { CT_UPDATE,	0 },
+	['A']	= { CT_ADD,	0 },
 };
 
 static const int opt2type[] = {
@@ -488,6 +491,7 @@ static char exit_msg[NUMBER_OF_CMD][64] = {
 	[CT_EVENT_BIT]		= "%d flow events have been shown.\n",
 	[EXP_LIST_BIT]		= "%d expectations have been shown.\n",
 	[EXP_DELETE_BIT]	= "%d expectations have been shown.\n",
+	[CT_ADD_BIT]		= "%d flow entries have been added.\n",
 };
 
 static const char usage_commands[] =
@@ -745,7 +749,7 @@ static int ct_save_snprintf(char *buf, size_t len,
 
 	switch (type) {
 	case NFCT_T_NEW:
-		ret = snprintf(buf + offset, len, "-I ");
+		ret = snprintf(buf + offset, len, "-A ");
 		BUFFER_SIZE(ret, size, len, offset);
 		break;
 	case NFCT_T_UPDATE:
@@ -1054,11 +1058,11 @@ err2str(int err, enum ct_command command)
 	  { { CT_LIST, ENOTSUPP, "function not implemented" },
 	    { 0xFFFF, EINVAL, "invalid parameters" },
 	    { CT_CREATE, EEXIST, "Such conntrack exists, try -U to update" },
-	    { CT_CREATE|CT_GET|CT_DELETE, ENOENT, 
+	    { CT_CREATE|CT_GET|CT_DELETE|CT_ADD, ENOENT,
 		    "such conntrack doesn't exist" },
-	    { CT_CREATE|CT_GET, ENOMEM, "not enough memory" },
+	    { CT_CREATE|CT_GET|CT_ADD, ENOMEM, "not enough memory" },
 	    { CT_GET, EAFNOSUPPORT, "protocol not supported" },
-	    { CT_CREATE, ETIME, "conntrack has expired" },
+	    { CT_CREATE|CT_ADD, ETIME, "conntrack has expired" },
 	    { EXP_CREATE, ENOENT, "master conntrack not found" },
 	    { EXP_CREATE, EINVAL, "invalid parameters" },
 	    { ~0U, EPERM, "sorry, you must be root or get "
@@ -2881,7 +2885,8 @@ static int print_stats(const struct ct_cmd *cmd)
 	if (cmd->command && exit_msg[cmd->cmd][0]) {
 		fprintf(stderr, "%s v%s (conntrack-tools): ",PROGNAME,VERSION);
 		fprintf(stderr, exit_msg[cmd->cmd], counter);
-		if (counter == 0 && !(cmd->command & (CT_LIST | EXP_LIST)))
+		if (counter == 0 &&
+		    !(cmd->command & (CT_LIST | EXP_LIST | CT_ADD)))
 			return -1;
 	}
 
@@ -2935,6 +2940,7 @@ static void do_parse(struct ct_cmd *ct_cmd, int argc, char *argv[])
 		case 'C':
 		case 'S':
 		case 'U':
+		case 'A':
 			type = check_type(argc, argv);
 			if (type == CT_TABLE_DYING ||
 			    type == CT_TABLE_UNCONFIRMED) {
@@ -3286,6 +3292,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd,
 		break;
 
 	case CT_CREATE:
+	case CT_ADD:
 		if ((cmd->options & CT_OPT_ORIG) && !(cmd->options & CT_OPT_REPL))
 			nfct_setobjopt(cmd->tmpl.ct, NFCT_SOPT_SETUP_REPLY);
 		else if (!(cmd->options & CT_OPT_ORIG) && (cmd->options & CT_OPT_REPL))
@@ -3304,7 +3311,8 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd,
 				       NULL, cmd->tmpl.ct, NULL);
 		if (res >= 0)
 			counter++;
-
+		else if (errno == EEXIST && cmd->command == CT_ADD)
+			res = 0;
 		break;
 
 	case EXP_CREATE:
@@ -3810,7 +3818,8 @@ int main(int argc, char *argv[])
 		ct_parse_file(&cmd_list, argv[0], argv[2]);
 
 		list_for_each_entry(cmd, &cmd_list, list) {
-			if (!(cmd->command & (CT_CREATE | CT_UPDATE | CT_DELETE | CT_FLUSH)))
+			if (!(cmd->command &
+			      (CT_CREATE | CT_ADD | CT_UPDATE | CT_DELETE | CT_FLUSH)))
 				exit_error(PARAMETER_PROBLEM,
 					   "Cannot use command `%s' with --load-file",
 					   ct_unsupp_cmd_file(cmd));
diff --git a/tests/conntrack/testsuite/08stdin b/tests/conntrack/testsuite/08stdin
index 1d31176..158c4c3 100644
--- a/tests/conntrack/testsuite/08stdin
+++ b/tests/conntrack/testsuite/08stdin
@@ -77,4 +77,49 @@
 -D -w 123 ;
 -R - ; OK
 # validate it via standard command line way
--D -w 123 ; BAD
\ No newline at end of file
+-D -w 123 ; BAD
+# create with -A
+# create a conntrack
+-A -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ;
+# create from reply
+-A -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 --state LISTEN -u SEEN_REPLY -t 50 ;
+# create a v6 conntrack
+-A -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ;
+# creae icmp ping request entry
+-A -t 29 -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ;
+-R - ; OK
+# create again
+-I -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+-I -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+-I -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+-I -t 29 -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ; BAD
+# repeat, it should succeed
+-A -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ;
+# create from reply
+-A -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 --state LISTEN -u SEEN_REPLY -t 50 ;
+# create a v6 conntrack
+-A -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ;
+# creae icmp ping request entry
+-A -t 29 -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ;
+-R - ; OK
+# delete
+-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 ;
+# empty lines should be just ignored
+;
+;
+# delete reverse
+-D -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 ;
+# empty lines with spaces or tabs should be ignored as well
+ ;
+	;
+		;
+  ;
+	    ;
+	    	    	;
+# delete v6 conntrack
+-D -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p tcp --sport 10 --dport 20 ;
+# delete icmp ping request entry
+-D -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ;
+;
+;
+-R - ; OK
diff --git a/tests/conntrack/testsuite/10add b/tests/conntrack/testsuite/10add
new file mode 100644
index 0000000..4f9f3b9
--- /dev/null
+++ b/tests/conntrack/testsuite/10add
@@ -0,0 +1,42 @@
+#missing destination
+-A -s 1.1.1.1 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+#missing source
+-A -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+#missing protocol
+-A -s 1.1.1.1 -d 2.2.2.2 --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+#missing source port
+-A -s 1.1.1.1 -d 2.2.2.2 -p tcp --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+#missing destination port
+-A -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+#missing timeout
+-A -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY ; BAD
+# create a conntrack
+-A -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# create again
+-A -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# delete
+-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 ; OK
+# delete again
+-D -s 1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 ; BAD
+# create from reply
+-A -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# create again from reply
+-A -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# delete reverse
+-D -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 ; OK
+# delete reverse again
+-D -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 ; BAD
+# create a v6 conntrack
+-A -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# create again a v6 conntrack
+-A -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
+# delete v6 conntrack
+-D -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p tcp --sport 10 --dport 20 ; OK
+# mismatched address family
+-A -s 2001:DB8::1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
+# creae icmp ping request entry
+-A -t 29 -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ; OK
+# creae again icmp ping request entry
+-A -t 29 -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ; OK
+# delete icmp ping request entry
+-D -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ; OK
-- 
2.25.1


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

* Re: [PATCH v2 0/3] conntrack: -A command implementation
  2022-06-29 17:09 [PATCH v2 0/3] conntrack: -A command implementation Mikhail Sennikovsky
                   ` (2 preceding siblings ...)
  2022-06-29 17:09 ` [PATCH v2 3/3] conntrack: introduce new -A command Mikhail Sennikovsky
@ 2022-07-08 11:19 ` Pablo Neira Ayuso
  3 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2022-07-08 11:19 UTC (permalink / raw)
  To: Mikhail Sennikovsky; +Cc: netfilter-devel, mikhail.sennikovsky

On Wed, Jun 29, 2022 at 07:09:38PM +0200, Mikhail Sennikovsky wrote:
> Hi Pablo & all,
> 
> As discussed, here is an updated patch set for the -A command
> support.
> As you requested it introduces a separate CT_ADD command now.
> In order to do that cleanly and error-safe I had to do two
> preparation steps, which are included as two separate commits
> with detailed description on each.

Series applied, thanks

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

end of thread, other threads:[~2022-07-08 11:19 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-29 17:09 [PATCH v2 0/3] conntrack: -A command implementation Mikhail Sennikovsky
2022-06-29 17:09 ` [PATCH v2 1/3] conntrack: generalize command parsing Mikhail Sennikovsky
2022-06-29 17:09 ` [PATCH v2 2/3] conntrack: use C99 initializer syntax for opts map Mikhail Sennikovsky
2022-06-29 17:09 ` [PATCH v2 3/3] conntrack: introduce new -A command Mikhail Sennikovsky
2022-07-08 11:19 ` [PATCH v2 0/3] conntrack: -A command implementation Pablo Neira Ayuso

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.