summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-05-09 16:03:42 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-05-09 18:29:21 +0200
commit816d8c7659c1d90ce6827baaa939820a3bae2ae0 (patch)
treefca73c0fcee84c77dfd27a4067dd3f27aa25e79d /src
parent5a7775a1d699ced8a0c760d4849c4e84bac9268a (diff)
Support 'add/insert rule index <IDX>'
Allow to specify an absolute rule position in add/insert commands like with iptables. The translation to rule handle takes place in userspace, so no kernel support for this is needed. Possible undesired effects are pointed out in man page to make users aware that this way of specifying a rule location might not be ideal. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/evaluate.c45
-rw-r--r--src/parser_bison.y18
-rw-r--r--src/rule.c2
-rw-r--r--src/scanner.l1
4 files changed, 64 insertions, 2 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 46c97606..cb27f7c2 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2851,6 +2851,47 @@ static int flowtable_evaluate(struct eval_ctx *ctx, struct flowtable *ft)
return 0;
}
+/* Convert rule's handle.index into handle.position. */
+static int rule_translate_index(struct eval_ctx *ctx, struct rule *rule)
+{
+ struct table *table;
+ struct chain *chain;
+ uint64_t index = 0;
+ struct rule *r;
+ int ret;
+
+ /* update cache with CMD_LIST so that rules are fetched, too */
+ ret = cache_update(ctx->nf_sock, ctx->cache, CMD_LIST,
+ ctx->msgs, ctx->debug_mask, ctx->octx);
+ if (ret < 0)
+ return ret;
+
+ table = table_lookup(&rule->handle, ctx->cache);
+ if (!table)
+ return cmd_error(ctx, &rule->handle.table.location,
+ "Could not process rule: %s",
+ strerror(ENOENT));
+
+ chain = chain_lookup(table, &rule->handle);
+ if (!chain)
+ return cmd_error(ctx, &rule->handle.chain.location,
+ "Could not process rule: %s",
+ strerror(ENOENT));
+
+ list_for_each_entry(r, &chain->rules, list) {
+ if (++index < rule->handle.index.id)
+ continue;
+ rule->handle.position.id = r->handle.handle.id;
+ rule->handle.position.location = rule->handle.index.location;
+ break;
+ }
+ if (!rule->handle.position.id)
+ return cmd_error(ctx, &rule->handle.index.location,
+ "Could not process rule: %s",
+ strerror(EINVAL));
+ return 0;
+}
+
static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule)
{
struct stmt *stmt, *tstmt = NULL;
@@ -2879,6 +2920,10 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule)
return -1;
}
+ if (rule->handle.index.id &&
+ rule_translate_index(ctx, rule))
+ return -1;
+
return 0;
}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 174150aa..0e3ee84f 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -485,6 +485,7 @@ int nft_lex(void *, void *, void *);
%token SEED "seed"
%token POSITION "position"
+%token INDEX "index"
%token COMMENT "comment"
%token XML "xml"
@@ -512,8 +513,8 @@ int nft_lex(void *, void *, void *);
%type <cmd> base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd get_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd
%destructor { cmd_free($$); } base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd get_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd
-%type <handle> table_spec tableid_spec chain_spec chainid_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
-%destructor { handle_free(&$$); } table_spec tableid_spec chain_spec chainid_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec
+%type <handle> table_spec tableid_spec chain_spec chainid_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec index_spec
+%destructor { handle_free(&$$); } table_spec tableid_spec chain_spec chainid_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec index_spec
%type <handle> set_spec setid_spec set_identifier flowtable_identifier obj_spec objid_spec obj_identifier
%destructor { handle_free(&$$); } set_spec setid_spec set_identifier obj_spec objid_spec obj_identifier
%type <val> family_spec family_spec_explicit chain_policy prio_spec
@@ -1961,6 +1962,14 @@ position_spec : POSITION NUM
}
;
+index_spec : INDEX NUM
+ {
+ memset(&$$, 0, sizeof($$));
+ $$.index.location = @$;
+ $$.index.id = $2 + 1;
+ }
+ ;
+
rule_position : chain_spec
{
$$ = $1;
@@ -1978,6 +1987,11 @@ rule_position : chain_spec
handle_merge(&$1, &$2);
$$ = $1;
}
+ | chain_spec index_spec
+ {
+ handle_merge(&$1, &$2);
+ $$ = $1;
+ }
;
ruleid_spec : chain_spec handle_spec
diff --git a/src/rule.c b/src/rule.c
index a365876d..279b741b 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -60,6 +60,8 @@ void handle_merge(struct handle *dst, const struct handle *src)
dst->handle = src->handle;
if (dst->position.id == 0)
dst->position = src->position;
+ if (dst->index.id == 0)
+ dst->index = src->index;
}
static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h,
diff --git a/src/scanner.l b/src/scanner.l
index bd641345..6a861cf2 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -285,6 +285,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"monitor" { return MONITOR; }
"position" { return POSITION; }
+"index" { return INDEX; }
"comment" { return COMMENT; }
"constant" { return CONSTANT; }