[PATCH nft 1/2] src: interpret the event type from the evaluation step

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

 



Postpone the event type interpretation to the evaluation step.
This patch also fixes the combination of event and object types,
which was broken. The export code needed to be adjusted too.

The new and destroy are not tokens that can be recognized by
the scanner anymore, so this also implicitly restores 'ct state'.

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
@Patrick: After giving a closer look to Arturo's monitor code, it seems
to me that we really need an evaluation phase to support event and object
type combinations. Note this removes the 'new' and 'destroy' tokens from
the scanner, which is causing us problems. This reduces the size of the
monitor code in the parser by ~75 LOC.

 include/rule.h |   36 ++++++++++++++++++++--
 src/evaluate.c |   71 ++++++++++++++++++++++++++++++++++++++++++-
 src/parser.y   |   92 ++++++++++----------------------------------------------
 src/rule.c     |   51 +++++++++++++++++++++++++++----
 src/scanner.l  |    3 --
 5 files changed, 165 insertions(+), 88 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index a1d5890..936177b 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -252,6 +252,8 @@ enum cmd_ops {
  * @CMD_OBJ_TABLE:	table
  * @CMD_OBJ_RULESET:	ruleset
  * @CMD_OBJ_EXPR:	expression
+ * @CMD_OBJ_MONITOR:	monitor
+ * @CMD_OBJ_EXPORT:	export
  */
 enum cmd_obj {
 	CMD_OBJ_INVALID,
@@ -263,8 +265,38 @@ enum cmd_obj {
 	CMD_OBJ_TABLE,
 	CMD_OBJ_RULESET,
 	CMD_OBJ_EXPR,
+	CMD_OBJ_MONITOR,
+	CMD_OBJ_EXPORT,
 };
 
+struct export {
+	uint32_t	format;
+};
+
+struct export *export_alloc(uint32_t format);
+void export_free(struct export *e);
+
+enum {
+	CMD_MONITOR_OBJ_ANY,
+	CMD_MONITOR_OBJ_TABLES,
+	CMD_MONITOR_OBJ_CHAINS,
+	CMD_MONITOR_OBJ_RULES,
+	CMD_MONITOR_OBJ_SETS,
+	CMD_MONITOR_OBJ_ELEMS,
+	CMD_MONITOR_OBJ_MAX
+};
+
+struct monitor {
+	struct location	location;
+	uint32_t	format;
+	uint32_t	flags;
+	uint32_t	type;
+	const char	*event;
+};
+
+struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event);
+void monitor_free(struct monitor *m);
+
 /**
  * struct cmd - command statement
  *
@@ -292,10 +324,10 @@ struct cmd {
 		struct rule	*rule;
 		struct chain	*chain;
 		struct table	*table;
+		struct monitor	*monitor;
+		struct export	*export;
 	};
 	const void		*arg;
-	uint32_t		format;
-	uint32_t		monitor_flags;
 };
 
 extern struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
diff --git a/src/evaluate.c b/src/evaluate.c
index 284ee72..0004008 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -58,6 +58,8 @@ static int __fmtstring(4, 5) __stmt_binary_error(struct eval_ctx *ctx,
 	__stmt_binary_error(ctx, &(s1)->location, &(s2)->location, fmt, ## args)
 #define chain_error(ctx, s1, fmt, args...) \
 	__stmt_binary_error(ctx, &(s1)->location, NULL, fmt, ## args)
+#define monitor_error(ctx, s1, fmt, args...) \
+	__stmt_binary_error(ctx, &(s1)->location, NULL, fmt, ## args)
 
 static int __fmtstring(3, 4) set_error(struct eval_ctx *ctx,
 				       const struct set *set,
@@ -1433,6 +1435,72 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
 	}
 }
 
+enum {
+	CMD_MONITOR_EVENT_ANY,
+	CMD_MONITOR_EVENT_NEW,
+	CMD_MONITOR_EVENT_DEL,
+	CMD_MONITOR_EVENT_MAX
+};
+
+static uint32_t monitor_flags[CMD_MONITOR_EVENT_MAX][CMD_MONITOR_OBJ_MAX] = {
+	[CMD_MONITOR_EVENT_ANY] = {
+		[CMD_MONITOR_OBJ_ANY]		= 0xffffffff,
+		[CMD_MONITOR_OBJ_TABLES]	= (1 << NFT_MSG_NEWTABLE) |
+						  (1 << NFT_MSG_DELTABLE),
+		[CMD_MONITOR_OBJ_CHAINS]	= (1 << NFT_MSG_NEWCHAIN) |
+						  (1 << NFT_MSG_DELCHAIN),
+		[CMD_MONITOR_OBJ_RULES]		= (1 << NFT_MSG_NEWRULE) |
+						  (1 << NFT_MSG_DELRULE),
+		[CMD_MONITOR_OBJ_SETS]		= (1 << NFT_MSG_NEWSET) |
+						  (1 << NFT_MSG_DELSET),
+		[CMD_MONITOR_OBJ_ELEMS]		= (1 << NFT_MSG_NEWSETELEM) |
+						  (1 << NFT_MSG_DELSETELEM),
+	},
+	[CMD_MONITOR_EVENT_NEW] = {
+		[CMD_MONITOR_OBJ_ANY]		= (1 << NFT_MSG_NEWTABLE) |
+						  (1 << NFT_MSG_NEWCHAIN) |
+						  (1 << NFT_MSG_NEWRULE)  |
+						  (1 << NFT_MSG_NEWSET)   |
+						  (1 << NFT_MSG_NEWSETELEM),
+		[CMD_MONITOR_OBJ_TABLES]	= (1 << NFT_MSG_NEWTABLE),
+		[CMD_MONITOR_OBJ_CHAINS]	= (1 << NFT_MSG_NEWCHAIN),
+		[CMD_MONITOR_OBJ_RULES]		= (1 << NFT_MSG_NEWRULE),
+		[CMD_MONITOR_OBJ_SETS]		= (1 << NFT_MSG_NEWSET),
+		[CMD_MONITOR_OBJ_ELEMS]		= (1 << NFT_MSG_NEWSETELEM),
+	},
+	[CMD_MONITOR_EVENT_DEL] = {
+		[CMD_MONITOR_OBJ_ANY]		= (1 << NFT_MSG_DELTABLE) |
+						  (1 << NFT_MSG_DELCHAIN) |
+						  (1 << NFT_MSG_DELRULE)  |
+						  (1 << NFT_MSG_DELSET)   |
+						  (1 << NFT_MSG_DELSETELEM),
+		[CMD_MONITOR_OBJ_TABLES]	= (1 << NFT_MSG_DELTABLE),
+		[CMD_MONITOR_OBJ_CHAINS]	= (1 << NFT_MSG_DELCHAIN),
+		[CMD_MONITOR_OBJ_RULES]		= (1 << NFT_MSG_DELRULE),
+		[CMD_MONITOR_OBJ_SETS]		= (1 << NFT_MSG_DELSET),
+		[CMD_MONITOR_OBJ_ELEMS]		= (1 << NFT_MSG_DELSETELEM),
+	},
+};
+
+static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd)
+{
+	uint32_t event;
+
+	if (cmd->monitor->event == NULL)
+		event = CMD_MONITOR_EVENT_ANY;
+	else if (strcmp(cmd->monitor->event, "new") == 0)
+		event = CMD_MONITOR_EVENT_NEW;
+	else if (strcmp(cmd->monitor->event, "destroy") == 0)
+		event = CMD_MONITOR_EVENT_DEL;
+	else {
+		return monitor_error(ctx, cmd->monitor, "invalid event %s",
+				     cmd->monitor->event);
+	}
+
+	cmd->monitor->flags = monitor_flags[event][cmd->monitor->type];
+	return 0;
+}
+
 int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
 {
 #ifdef DEBUG
@@ -1455,9 +1523,10 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_FLUSH:
 	case CMD_RENAME:
 	case CMD_EXPORT:
-	case CMD_MONITOR:
 	case CMD_DESCRIBE:
 		return 0;
+	case CMD_MONITOR:
+		return cmd_evaluate_monitor(ctx, cmd);
 	default:
 		BUG("invalid command operation %u\n", cmd->op);
 	};
diff --git a/src/parser.y b/src/parser.y
index 4a8df7b..d3e1bc0 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -195,9 +195,6 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token GOTO			"goto"
 %token RETURN			"return"
 
-%token NEW			"new"
-%token DESTROY			"destroy"
-
 %token CONSTANT			"constant"
 %token INTERVAL			"interval"
 %token ELEMENTS			"elements"
@@ -522,7 +519,9 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %type <val>			ct_key
 
 %type <val>			export_format
-%type <val>			monitor_event	monitor_object		monitor_format
+%type <string>			monitor_event
+%destructor { xfree($$); }	monitor_event
+%type <val>			monitor_object	monitor_format
 
 %%
 
@@ -788,89 +787,30 @@ rename_cmd		:	CHAIN		chain_spec	identifier
 export_cmd		:	export_format
 			{
 				struct handle h = { .family = NFPROTO_UNSPEC };
-				$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_RULESET, &h, &@$, NULL);
-				$$->format = $1;
+				struct export *export = export_alloc($1);
+				$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export);
 			}
 			;
 
 monitor_cmd		:	monitor_event	monitor_object	monitor_format
 			{
 				struct handle h = { .family = NFPROTO_UNSPEC };
-				$$ = cmd_alloc(CMD_MONITOR, CMD_OBJ_RULESET, &h, &@$, NULL);
-				$$->monitor_flags = $1 & $2;
-				$$->format = $3;
+				struct monitor *m = monitor_alloc($3, $2, $1);
+				m->location = @1;
+				$$ = cmd_alloc(CMD_MONITOR, CMD_OBJ_MONITOR, &h, &@$, m);
 			}
 			;
 
-monitor_event		:	/* empty */
-			{
-				$$ = (1 << NFT_MSG_NEWRULE)	|
-				     (1 << NFT_MSG_DELRULE)	|
-				     (1 << NFT_MSG_NEWSET)	|
-				     (1 << NFT_MSG_DELSET)	|
-				     (1 << NFT_MSG_NEWSETELEM)	|
-				     (1 << NFT_MSG_DELSETELEM)	|
-				     (1 << NFT_MSG_NEWCHAIN)	|
-				     (1 << NFT_MSG_DELCHAIN)	|
-				     (1 << NFT_MSG_NEWTABLE)	|
-				     (1 << NFT_MSG_DELTABLE);
-			}
-			|	NEW
-			{
-				$$ = (1 << NFT_MSG_NEWTABLE)	|
-				     (1 << NFT_MSG_NEWCHAIN)	|
-				     (1 << NFT_MSG_NEWRULE)	|
-				     (1 << NFT_MSG_NEWSET)	|
-				     (1 << NFT_MSG_NEWSETELEM);
-			}
-			|	DESTROY
-			{
-				$$ = (1 << NFT_MSG_DELTABLE)	|
-				     (1 << NFT_MSG_DELCHAIN)	|
-				     (1 << NFT_MSG_DELRULE)	|
-				     (1 << NFT_MSG_DELSET)	|
-				     (1 << NFT_MSG_DELSETELEM);
-			}
+monitor_event		:	/* empty */	{ $$ = NULL; }
+			|       STRING		{ $$ = $1; }
 			;
 
-monitor_object		:	/* empty */
-			{
-				$$ = (1 << NFT_MSG_NEWRULE)	|
-				     (1 << NFT_MSG_DELRULE)	|
-				     (1 << NFT_MSG_NEWSET)	|
-				     (1 << NFT_MSG_DELSET)	|
-				     (1 << NFT_MSG_NEWSETELEM)	|
-				     (1 << NFT_MSG_DELSETELEM)	|
-				     (1 << NFT_MSG_NEWCHAIN)	|
-				     (1 << NFT_MSG_DELCHAIN)	|
-				     (1 << NFT_MSG_NEWTABLE)	|
-				     (1 << NFT_MSG_DELTABLE);
-			}
-			|	TABLES
-			{
-				$$ = (1 << NFT_MSG_NEWTABLE) |
-				     (1 << NFT_MSG_DELTABLE);
-			}
-			|	CHAINS
-			{
-				$$ = (1 << NFT_MSG_NEWCHAIN) |
-				     (1 << NFT_MSG_DELCHAIN);
-			}
-			|	SETS
-			{
-				$$ = (1 << NFT_MSG_NEWSET) |
-				     (1 << NFT_MSG_DELSET);
-			}
-			|	RULES
-			{
-				$$ = (1 << NFT_MSG_NEWRULE) |
-				     (1 << NFT_MSG_DELRULE);
-			}
-			|	ELEMENTS
-			{
-				$$ = (1 << NFT_MSG_NEWSETELEM) |
-				     (1 << NFT_MSG_DELSETELEM);
-			}
+monitor_object		:	/* empty */	{ $$ = CMD_MONITOR_OBJ_ANY; }
+			| 	TABLES		{ $$ = CMD_MONITOR_OBJ_TABLES; }
+			| 	CHAINS		{ $$ = CMD_MONITOR_OBJ_CHAINS; }
+			| 	SETS		{ $$ = CMD_MONITOR_OBJ_SETS; }
+			|	RULES		{ $$ = CMD_MONITOR_OBJ_RULES; }
+			|	ELEMENTS	{ $$ = CMD_MONITOR_OBJ_ELEMS; }
 			;
 
 monitor_format		:	/* empty */	{ $$ = NFT_OUTPUT_DEFAULT; }
diff --git a/src/rule.c b/src/rule.c
index 43355ee..a79a420 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -556,6 +556,39 @@ struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
 	return cmd;
 }
 
+struct export *export_alloc(uint32_t format)
+{
+	struct export *export;
+
+	export = xmalloc(sizeof(struct export));
+	export->format = format;
+
+	return export;
+}
+
+void export_free(struct export *e)
+{
+	xfree(e);
+}
+
+struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event)
+{
+	struct monitor *mon;
+
+	mon = xmalloc(sizeof(struct monitor));
+	mon->format = format;
+	mon->type = type;
+	mon->event = event;
+	mon->flags = 0;
+
+	return mon;
+}
+
+void monitor_free(struct monitor *m)
+{
+	xfree(m);
+}
+
 void cmd_free(struct cmd *cmd)
 {
 	handle_free(&cmd->handle);
@@ -579,6 +612,12 @@ void cmd_free(struct cmd *cmd)
 		case CMD_OBJ_EXPR:
 			expr_free(cmd->expr);
 			break;
+		case CMD_OBJ_MONITOR:
+			monitor_free(cmd->monitor);
+			break;
+		case CMD_OBJ_EXPORT:
+			export_free(cmd->export);
+			break;
 		default:
 			BUG("invalid command object type %u\n", cmd->obj);
 		}
@@ -726,7 +765,7 @@ static int do_command_export(struct netlink_ctx *ctx, struct cmd *cmd)
 	if (rs == NULL)
 		return -1;
 
-	nft_ruleset_fprintf(stdout, rs, cmd->format, 0);
+	nft_ruleset_fprintf(stdout, rs, cmd->export->format, 0);
 	fprintf(stdout, "\n");
 
 	nft_ruleset_free(rs);
@@ -929,9 +968,9 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
 	 *  - new rules in default format
 	 *  - new elements
 	 */
-	if (((cmd->monitor_flags & (1 << NFT_MSG_NEWRULE)) &&
-	    (cmd->format == NFT_OUTPUT_DEFAULT)) ||
-	    (cmd->monitor_flags & (1 << NFT_MSG_NEWSETELEM)))
+	if (((cmd->monitor->flags & (1 << NFT_MSG_NEWRULE)) &&
+	    (cmd->monitor->format == NFT_OUTPUT_DEFAULT)) ||
+	    (cmd->monitor->flags & (1 << NFT_MSG_NEWSETELEM)))
 		monhandler.cache_needed = true;
 	else
 		monhandler.cache_needed = false;
@@ -963,8 +1002,8 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
 		}
 	}
 
-	monhandler.monitor_flags = cmd->monitor_flags;
-	monhandler.format = cmd->format;
+	monhandler.monitor_flags = cmd->monitor->flags;
+	monhandler.format = cmd->monitor->format;
 	monhandler.ctx = ctx;
 	monhandler.loc = &cmd->location;
 
diff --git a/src/scanner.l b/src/scanner.l
index 35c9446..a00c1ca 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -261,9 +261,6 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 "export"		{ return EXPORT; }
 "monitor"		{ return MONITOR; }
 
-"new"			{ return NEW; }
-"destroy"		{ return DESTROY; }
-
 "position"		{ return POSITION; }
 "comment"		{ return COMMENT; }
 
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux