diff options
author | Phil Sutter <phil@nwl.cc> | 2018-05-09 16:03:42 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2018-05-09 18:29:21 +0200 |
commit | 816d8c7659c1d90ce6827baaa939820a3bae2ae0 (patch) | |
tree | fca73c0fcee84c77dfd27a4067dd3f27aa25e79d /src/evaluate.c | |
parent | 5a7775a1d699ced8a0c760d4849c4e84bac9268a (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/evaluate.c')
-rw-r--r-- | src/evaluate.c | 45 |
1 files changed, 45 insertions, 0 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; } |