diff mbox

src: Add command "replace" for rules

Message ID 1445947087-25861-1-git-send-email-carlosfg@riseup.net
State Accepted
Delegated to: Pablo Neira
Headers show

Commit Message

Carlos Falgueras García Oct. 27, 2015, 11:58 a.m. UTC
Modify the parser and add necessary functions to provide the command "nft
replace rule <ruleid_spec> <new_rule>"

Example of use:
	# nft list ruleset -a
	table ip filter {
		chain output {
			ip daddr 8.8.8.7 counter packets 0 bytes 0 # handle 3
		}
	}
	# nft replace rule filter output handle 3 ip daddr 8.8.8.8 counter
	# nft list ruleset -a
	table ip filter {
		chain output {
			ip daddr 8.8.8.8 counter packets 0 bytes 0 # handle 3
		}
	}

Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
---
 include/mnl.h      |  2 ++
 include/netlink.h  |  4 ++++
 include/rule.h     |  2 ++
 src/evaluate.c     |  1 +
 src/mnl.c          | 16 ++++++++++++++++
 src/netlink.c      | 18 ++++++++++++++++++
 src/parser_bison.y | 12 ++++++++++--
 src/rule.c         | 14 ++++++++++++++
 src/scanner.l      |  1 +
 9 files changed, 68 insertions(+), 2 deletions(-)

Comments

Pablo Neira Ayuso Nov. 6, 2015, 1:42 p.m. UTC | #1
On Tue, Oct 27, 2015 at 12:58:07PM +0100, Carlos Falgueras García wrote:
> Modify the parser and add necessary functions to provide the command "nft
> replace rule <ruleid_spec> <new_rule>"
> 
> Example of use:
> 	# nft list ruleset -a
> 	table ip filter {
> 		chain output {
> 			ip daddr 8.8.8.7 counter packets 0 bytes 0 # handle 3
> 		}
> 	}
> 	# nft replace rule filter output handle 3 ip daddr 8.8.8.8 counter
> 	# nft list ruleset -a
> 	table ip filter {
> 		chain output {
> 			ip daddr 8.8.8.8 counter packets 0 bytes 0 # handle 3
> 		}
> 	}

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

Patch

diff --git a/include/mnl.h b/include/mnl.h
index 9c14e1a..f74dfee 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -26,6 +26,8 @@  int mnl_nft_rule_batch_add(struct nftnl_rule *nlr, unsigned int flags,
 			   uint32_t seqnum);
 int mnl_nft_rule_batch_del(struct nftnl_rule *nlr, unsigned int flags,
 			   uint32_t seqnum);
+int mnl_nft_rule_batch_replace(struct nftnl_rule *nlr, unsigned int flags,
+			       uint32_t seqnum);
 
 int mnl_nft_rule_add(struct mnl_socket *nf_sock, struct nftnl_rule *r,
 		     unsigned int flags);
diff --git a/include/netlink.h b/include/netlink.h
index 7bf7ea0..8444742 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -98,6 +98,10 @@  extern int netlink_add_rule_batch(struct netlink_ctx *ctx,
 extern int netlink_del_rule_batch(struct netlink_ctx *ctx,
 				  const struct handle *h,
 				  const struct location *loc);
+extern int netlink_replace_rule_batch(struct netlink_ctx *ctx,
+				      const struct handle *h,
+				      const struct rule *rule,
+				      const struct location *loc);
 
 extern int netlink_add_chain(struct netlink_ctx *ctx, const struct handle *h,
 			     const struct location *loc,
diff --git a/include/rule.h b/include/rule.h
index 30b4597..a86f600 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -237,6 +237,7 @@  extern void set_print_plain(const struct set *s);
  *
  * @CMD_INVALID:	invalid
  * @CMD_ADD:		add object (non-exclusive)
+ * @CMD_REPLACE,	replace object
  * @CMD_CREATE:		create object (exclusive)
  * @CMD_INSERT:		insert object
  * @CMD_DELETE:		delete object
@@ -250,6 +251,7 @@  extern void set_print_plain(const struct set *s);
 enum cmd_ops {
 	CMD_INVALID,
 	CMD_ADD,
+	CMD_REPLACE,
 	CMD_CREATE,
 	CMD_INSERT,
 	CMD_DELETE,
diff --git a/src/evaluate.c b/src/evaluate.c
index 4f9299e..4c34d1b 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2229,6 +2229,7 @@  int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
 	ctx->cmd = cmd;
 	switch (cmd->op) {
 	case CMD_ADD:
+	case CMD_REPLACE:
 	case CMD_CREATE:
 	case CMD_INSERT:
 		return cmd_evaluate_add(ctx, cmd);
diff --git a/src/mnl.c b/src/mnl.c
index e4253e5..52875f4 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -301,6 +301,22 @@  int mnl_nft_rule_batch_add(struct nftnl_rule *nlr, unsigned int flags,
 	return 0;
 }
 
+int mnl_nft_rule_batch_replace(struct nftnl_rule *nlr, unsigned int flags,
+			       uint32_t seqnum)
+{
+	struct nlmsghdr *nlh;
+
+	nlh = nftnl_rule_nlmsg_build_hdr(nftnl_batch_buffer(batch),
+			NFT_MSG_NEWRULE,
+			nftnl_rule_get_u32(nlr, NFTNL_RULE_FAMILY),
+			NLM_F_REPLACE | flags, seqnum);
+
+	nftnl_rule_nlmsg_build_payload(nlh, nlr);
+	mnl_nft_batch_continue();
+
+	return 0;
+}
+
 int mnl_nft_rule_batch_del(struct nftnl_rule *nlr, unsigned int flags,
 			   uint32_t seqnum)
 {
diff --git a/src/netlink.c b/src/netlink.c
index 4d1e977..ad86084 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -382,6 +382,24 @@  int netlink_add_rule_batch(struct netlink_ctx *ctx,
 	return err;
 }
 
+int netlink_replace_rule_batch(struct netlink_ctx *ctx, const struct handle *h,
+			       const struct rule *rule,
+			       const struct location *loc)
+{
+	struct nftnl_rule *nlr;
+	int err;
+
+	nlr = alloc_nftnl_rule(&rule->handle);
+	netlink_linearize_rule(ctx, nlr, rule);
+	err = mnl_nft_rule_batch_replace(nlr, 0, ctx->seqnum);
+	nftnl_rule_free(nlr);
+
+	if (err < 0)
+		netlink_io_error(ctx, loc, "Could not replace rule to batch: %s",
+				 strerror(errno));
+	return err;
+}
+
 int netlink_add_rule_list(struct netlink_ctx *ctx, const struct handle *h,
 			  struct list_head *rule_list)
 {
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 98480b6..49988f6 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -184,6 +184,7 @@  static void location_update(struct location *loc, struct location *rhs, int n)
 
 %token ADD			"add"
 %token UPDATE			"update"
+%token REPLACE			"replace"
 %token CREATE			"create"
 %token INSERT			"insert"
 %token DELETE			"delete"
@@ -413,8 +414,8 @@  static void location_update(struct location *loc, struct location *rhs, int n)
 %type <cmd>			line
 %destructor { cmd_free($$); }	line
 
-%type <cmd>			base_cmd add_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd
-%destructor { cmd_free($$); }	base_cmd add_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd
+%type <cmd>			base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd
+%destructor { cmd_free($$); }	base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd
 
 %type <handle>			table_spec chain_spec chain_identifier ruleid_spec ruleset_spec
 %destructor { handle_free(&$$); } table_spec chain_spec chain_identifier ruleid_spec ruleset_spec
@@ -649,6 +650,7 @@  line			:	common_block			{ $$ = NULL; }
 
 base_cmd		:	/* empty */	add_cmd		{ $$ = $1; }
 	  		|	ADD		add_cmd		{ $$ = $2; }
+	  		|	REPLACE		replace_cmd	{ $$ = $2; }
 			|	CREATE		create_cmd	{ $$ = $2; }
 			|	INSERT		insert_cmd	{ $$ = $2; }
 			|	DELETE		delete_cmd	{ $$ = $2; }
@@ -711,6 +713,12 @@  add_cmd			:	TABLE		table_spec
 			}
 			;
 
+replace_cmd		:	RULE		ruleid_spec	rule
+			{
+				$$ = cmd_alloc(CMD_REPLACE, CMD_OBJ_RULE, &$2, &@$, $3);
+			}
+			;
+
 create_cmd		:	TABLE		table_spec
 			{
 				$$ = cmd_alloc(CMD_CREATE, CMD_OBJ_TABLE, &$2, &@$, NULL);
diff --git a/src/rule.c b/src/rule.c
index 0a81469..c154062 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -935,6 +935,18 @@  static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl)
 	return 0;
 }
 
+static int do_command_replace(struct netlink_ctx *ctx, struct cmd *cmd)
+{
+	switch (cmd->obj) {
+	case CMD_OBJ_RULE:
+		return netlink_replace_rule_batch(ctx, &cmd->handle, cmd->rule,
+						  &cmd->location);
+	default:
+		BUG("invalid command object type %u\n", cmd->obj);
+	}
+	return 0;
+}
+
 static int do_command_insert(struct netlink_ctx *ctx, struct cmd *cmd)
 {
 	switch (cmd->obj) {
@@ -1229,6 +1241,8 @@  int do_command(struct netlink_ctx *ctx, struct cmd *cmd)
 		return do_command_add(ctx, cmd, true);
 	case CMD_INSERT:
 		return do_command_insert(ctx, cmd);
+	case CMD_REPLACE:
+		return do_command_replace(ctx, cmd);
 	case CMD_DELETE:
 		return do_command_delete(ctx, cmd);
 	case CMD_LIST:
diff --git a/src/scanner.l b/src/scanner.l
index b827489..1a9f43f 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -259,6 +259,7 @@  addrstring	({macaddr}|{ip4addr}|{ip6addr})
 "netdev"		{ return NETDEV; }
 
 "add"			{ return ADD; }
+"replace"		{ return REPLACE; }
 "update"		{ return UPDATE; }
 "create"		{ return CREATE; }
 "insert"		{ return INSERT; }