diff mbox

[nftables] Add support for insertion inside rule list

Message ID 20130719122833.GA30497@localhost
State Accepted
Headers show

Commit Message

Pablo Neira Ayuso July 19, 2013, 12:28 p.m. UTC
Hi Eric,

On Sat, Jul 06, 2013 at 05:33:57PM +0200, Eric Leblond wrote:
> This patch adds support for "insert before" and "add after"
> rule operation.
> The rule handle syntax has an new optional after/before field
> which take a handle as argument.
> Here is two examples:
>   nft add rule filter output after 5  ip daddr 1.2.3.1 drop
>   nft insert rule filter output before 5  ip daddr 1.2.3.1 drop

While testing this new feature, I noticed that the parser was
accepting this:

nft add rule filter output after 5  ip daddr 1.2.3.1 drop
nft insert rule filter output after 5  ip daddr 1.2.3.1 drop

Note that 'add' and 'insert' become semantically equivalent, which
seems inconsistent to me.

While fixing it using the 'before' and 'after', I noticed that 'add'
and 'insert' already tell us where to put the new rule, so 'after' and
'before' were repeating again what we want to do. I have reworked this
patch to change this initial syntax:

nft add rule filter output position 5  ip daddr 1.2.3.1 drop
nft insert rule filter output position 5  ip daddr 1.2.3.1 drop

We can support the after and before, but that would imply some extra
evaluation after the parsing that would make the patch bigger. So I
prefered to go the simpler solution.

Please, find the new patch attached. Thanks.

Comments

Eric Leblond July 19, 2013, 2:31 p.m. UTC | #1
Hello,

Le vendredi 19 juillet 2013 à 14:28 +0200, Pablo Neira Ayuso a écrit :
> Hi Eric,
> 
> On Sat, Jul 06, 2013 at 05:33:57PM +0200, Eric Leblond wrote:
> > This patch adds support for "insert before" and "add after"
> > rule operation.
> > The rule handle syntax has an new optional after/before field
> > which take a handle as argument.
> > Here is two examples:
> >   nft add rule filter output after 5  ip daddr 1.2.3.1 drop
> >   nft insert rule filter output before 5  ip daddr 1.2.3.1 drop
> 
> While testing this new feature, I noticed that the parser was
> accepting this:
> 
> nft add rule filter output after 5  ip daddr 1.2.3.1 drop
> nft insert rule filter output after 5  ip daddr 1.2.3.1 drop
> 
> Note that 'add' and 'insert' become semantically equivalent, which
> seems inconsistent to me.

Yes, forgot to mention that.

> While fixing it using the 'before' and 'after', I noticed that 'add'
> and 'insert' already tell us where to put the new rule, so 'after' and
> 'before' were repeating again what we want to do. I have reworked this
> patch to change this initial syntax:
> 
> nft add rule filter output position 5  ip daddr 1.2.3.1 drop
> nft insert rule filter output position 5  ip daddr 1.2.3.1 drop
> 
> We can support the after and before, but that would imply some extra
> evaluation after the parsing that would make the patch bigger. So I
> prefered to go the simpler solution.

I agree with the following modification. I did not find better than this
so, it is ok for me :)

Patch tested. It works well.

BR,
--
Eric
Pablo Neira Ayuso July 19, 2013, 3:50 p.m. UTC | #2
On Fri, Jul 19, 2013 at 04:31:27PM +0200, Eric Leblond wrote:
[...]
> > While fixing it using the 'before' and 'after', I noticed that 'add'
> > and 'insert' already tell us where to put the new rule, so 'after' and
> > 'before' were repeating again what we want to do. I have reworked this
> > patch to change this initial syntax:
> > 
> > nft add rule filter output position 5  ip daddr 1.2.3.1 drop
> > nft insert rule filter output position 5  ip daddr 1.2.3.1 drop
> > 
> > We can support the after and before, but that would imply some extra
> > evaluation after the parsing that would make the patch bigger. So I
> > prefered to go the simpler solution.
> 
> I agree with the following modification. I did not find better than this
> so, it is ok for me :)
> 
> Patch tested. It works well.

I have applied this patch, thanks for testing.
--
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

From f8afcae4af949c1f8c71fc4dbbffdbddbedb7adf Mon Sep 17 00:00:00 2001
From: Eric Leblond <eric@regit.org>
Date: Sat, 6 Jul 2013 17:33:57 +0200
Subject: [PATCH] src: Add support for insertion inside rule list

This patch adds support to insert and to add rule using a rule
handle as reference. The rule handle syntax has an new optional
position field which take a handle as argument.

Two examples:

  nft add rule filter output position 5 ip daddr 1.2.3.1 drop
  nft insert rule filter output position 5 ip daddr 1.2.3.1 drop

Signed-off-by: Eric Leblond <eric@regit.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/rule.h            |    2 ++
 src/mnl.c                 |    2 +-
 src/netlink.c             |    2 ++
 src/netlink_delinearize.c |    2 ++
 src/parser.y              |   17 +++++++++++++++--
 src/rule.c                |    2 ++
 src/scanner.l             |    2 ++
 7 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index e0debe3..2577cff 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -13,6 +13,7 @@ 
  * @chain:	chain name (chains and rules only)
  * @set:	set name (sets only)
  * @handle:	rule handle (rules only)
+ * @position:	rule position (rules only)
  */
 struct handle {
 	uint32_t		family;
@@ -20,6 +21,7 @@  struct handle {
 	const char		*chain;
 	const char		*set;
 	uint64_t		handle;
+	uint64_t		position;
 };
 
 extern void handle_merge(struct handle *dst, const struct handle *src);
diff --git a/src/mnl.c b/src/mnl.c
index a58f7ea..928d692 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -61,7 +61,7 @@  int mnl_nft_rule_add(struct mnl_socket *nf_sock, struct nft_rule *nlr,
 
 	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE,
 			nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY),
-			NLM_F_APPEND|NLM_F_ACK|NLM_F_CREATE, seq);
+			flags|NLM_F_ACK|NLM_F_CREATE, seq);
 	nft_rule_nlmsg_build_payload(nlh, nlr);
 
 	return mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
diff --git a/src/netlink.c b/src/netlink.c
index 2a7bdb5..5129cac 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -105,6 +105,8 @@  struct nft_rule *alloc_nft_rule(const struct handle *h)
 		nft_rule_attr_set_str(nlr, NFT_RULE_ATTR_CHAIN, h->chain);
 	if (h->handle)
 		nft_rule_attr_set_u64(nlr, NFT_RULE_ATTR_HANDLE, h->handle);
+	if (h->position)
+		nft_rule_attr_set_u64(nlr, NFT_RULE_ATTR_POSITION, h->position);
 	return nlr;
 }
 
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 9348913..f92e83f 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -796,6 +796,8 @@  struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
 	h.table  = xstrdup(nft_rule_attr_get_str(nlr, NFT_RULE_ATTR_TABLE));
 	h.chain  = xstrdup(nft_rule_attr_get_str(nlr, NFT_RULE_ATTR_CHAIN));
 	h.handle = nft_rule_attr_get_u64(nlr, NFT_RULE_ATTR_HANDLE);
+	if (nft_rule_attr_is_set(nlr, NFT_RULE_ATTR_POSITION))
+		h.position = nft_rule_attr_get_u64(nlr, NFT_RULE_ATTR_POSITION);
 
 	pctx->rule = rule_alloc(&internal_location, &h);
 	pctx->table = table_lookup(&h);
diff --git a/src/parser.y b/src/parser.y
index 2923b59..91981e9 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -326,6 +326,8 @@  static void location_update(struct location *loc, struct location *rhs, int n)
 %token SNAT			"snat"
 %token DNAT			"dnat"
 
+%token POSITION			"position"
+
 %type <string>			identifier string
 %destructor { xfree($$); }	identifier string
 
@@ -339,7 +341,7 @@  static void location_update(struct location *loc, struct location *rhs, int n)
 %destructor { handle_free(&$$); } table_spec tables_spec chain_spec chain_identifier ruleid_spec
 %type <handle>			set_spec set_identifier
 %destructor { handle_free(&$$); } set_spec set_identifier
-%type <val>			handle_spec family_spec
+%type <val>			handle_spec family_spec position_spec
 
 %type <table>			table_block_alloc table_block
 %destructor { table_free($$); }	table_block_alloc
@@ -842,10 +844,21 @@  handle_spec		:	/* empty */
 			}
 			;
 
-ruleid_spec		:	chain_spec	handle_spec
+position_spec		:	/* empty */
+			{
+				$$ = 0;
+			}
+			|	POSITION	NUM
+			{
+				$$ = $2;
+			}
+			;
+
+ruleid_spec		:	chain_spec	handle_spec	position_spec
 			{
 				$$		= $1;
 				$$.handle	= $2;
+				$$.position	= $3;
 			}
 			;
 
diff --git a/src/rule.c b/src/rule.c
index 5a894cc..8368624 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -41,6 +41,8 @@  void handle_merge(struct handle *dst, const struct handle *src)
 		dst->set = xstrdup(src->set);
 	if (dst->handle == 0)
 		dst->handle = src->handle;
+	if (dst->position == 0)
+		dst->position = src->position;
 }
 
 struct set *set_alloc(const struct location *loc)
diff --git a/src/scanner.l b/src/scanner.l
index fe7b86c..7946e94 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -249,6 +249,8 @@  addrstring	({macaddr}|{ip4addr}|{ip6addr})
 "flush"			{ return FLUSH; }
 "rename"		{ return RENAME; }
 
+"position"		{ return POSITION; }
+
 "counter"		{ return COUNTER; }
 "packets"		{ return PACKETS; }
 "bytes"			{ return BYTES; }
-- 
1.7.10.4