This patch introduces deletion in a similar fashion as in iptables, thus, we can delete the first rule that matches our description, for example: $ nft list -a ruleset table ip t { chain c { ip saddr 1.1.1.1 counter packets 0 bytes 0 # handle 1 ip saddr 1.1.1.2 counter packets 0 bytes 0 # handle 2 ip saddr 1.1.1.2 counter packets 0 bytes 0 # handle 3 ip saddr 1.1.1.4 counter packets 0 bytes 0 # handle 4 } } $ nft delete rule table chain ip saddr 1.1.1.2 counter $ nft list -a ruleset table ip t { chain c { ip saddr 1.1.1.1 counter packets 0 bytes 0 # handle 1 ip saddr 1.1.1.2 counter packets 0 bytes 0 # handle 3 ip saddr 1.1.1.4 counter packets 0 bytes 0 # handle 4 } } Also a custom error is thrown when user commits a syntax error: $ nft delete rule t c position 3 ... <cmdline>:1:17-24: Error: Expected `handle' or rule description delete rule t c position 3 ... Signed-off-by: Carlos Falgueras García <carlosfg@xxxxxxxxxx> --- src/evaluate.c | 6 ++++++ src/parser_bison.y | 32 ++++++++++++++++++++++++-------- src/rule.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/src/evaluate.c b/src/evaluate.c index 2f94ac6..f7b349b 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2661,7 +2661,13 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd) return setelem_evaluate(ctx, &cmd->expr); case CMD_OBJ_SET: + return 0; case CMD_OBJ_RULE: + /* CMD_LIST force caching all ruleset */ + ret = cache_update(CMD_LIST, ctx->msgs); + if (ret < 0) + return ret; + return rule_evaluate(ctx, cmd->rule); case CMD_OBJ_CHAIN: case CMD_OBJ_TABLE: return 0; diff --git a/src/parser_bison.y b/src/parser_bison.y index 93c283f..713002e 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -427,8 +427,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %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 handle_spec position_spec rule_position ruleset_spec -%destructor { handle_free(&$$); } table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec +%type <handle> table_spec chain_spec chain_identifier handle_spec position_spec rule_position ruleset_spec +%destructor { handle_free(&$$); } table_spec chain_spec chain_identifier handle_spec position_spec rule_position ruleset_spec %type <handle> set_spec set_identifier %destructor { handle_free(&$$); } set_spec set_identifier %type <val> family_spec family_spec_explicit chain_policy prio_spec @@ -440,7 +440,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %destructor { close_scope(state); table_free($$); } table_block_alloc %type <chain> chain_block_alloc chain_block %destructor { close_scope(state); chain_free($$); } chain_block_alloc -%type <rule> rule rule_alloc +%type <rule> rule ruleid_spec rule_alloc %destructor { rule_free($$); } rule %type <val> set_flag_list set_flag @@ -747,9 +747,10 @@ add_cmd : TABLE table_spec } ; -replace_cmd : RULE ruleid_spec rule +replace_cmd : RULE chain_spec handle_spec rule { - $$ = cmd_alloc(CMD_REPLACE, CMD_OBJ_RULE, &$2, &@$, $3); + handle_merge(&$2, &$3); + $$ = cmd_alloc(CMD_REPLACE, CMD_OBJ_RULE, &$2, &@$, $4); } ; @@ -794,7 +795,7 @@ delete_cmd : TABLE table_spec } | RULE ruleid_spec { - $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_RULE, &$2, &@$, NULL); + $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_RULE, &$2->handle, &@$, $2); } | SET set_spec { @@ -1285,8 +1286,23 @@ rule_position : chain_spec ruleid_spec : chain_spec handle_spec { - $$ = $1; - handle_merge(&$$, &$2); + $$ = rule_alloc(&@$, NULL); + $$->handle = $1; + handle_merge(&$$->handle, &$2); + } + | + chain_spec rule + { + $$ = $2; + handle_merge(&$$->handle, &$1); + } + | chain_spec err_recovering error + { + erec_queue(error(&@3, "Expected `handle' or rule description"), + state->msgs); + state->err_recovering = false; + $$ = rule_alloc(&@$, NULL); + handle_merge(&$$->handle, &$1); } ; diff --git a/src/rule.c b/src/rule.c index 14e57f2..d04c1ca 100644 --- a/src/rule.c +++ b/src/rule.c @@ -402,6 +402,32 @@ void rule_print(const struct rule *rule) printf(" # handle %" PRIu64, rule->handle.handle.id); } +static struct rule *search_first_rule(const struct rule *rule) +{ + struct nftnl_rule *nlr1, *nlr2; + struct rule *rule_idx; + struct table *table; + struct chain *chain; + + table = table_lookup(&rule->handle); + if (!table) + return NULL; + chain = chain_lookup(table, &rule->handle); + if (!chain) + return NULL; + + nlr1 = alloc_nftnl_rule(&rule->handle); + netlink_linearize_rule(NULL, nlr1, rule); + + list_for_each_entry(rule_idx, &chain->rules, list) { + nlr2 = alloc_nftnl_rule(&rule_idx->handle); + netlink_linearize_rule(NULL, nlr2, rule_idx); + if (nftnl_rule_cmp(nlr1, nlr2)) + return rule_idx; + } + return NULL; +} + struct rule *rule_lookup(const struct chain *chain, uint64_t handle) { struct rule *rule; @@ -1010,6 +1036,22 @@ static int do_delete_setelems(struct netlink_ctx *ctx, const struct handle *h, return 0; } +static int do_delete_rule(struct netlink_ctx *ctx, const struct cmd *cmd) +{ + struct rule *rule; + + /* Delete by handle */ + if (cmd->handle.handle.id) + return netlink_del_rule_batch(ctx, &cmd->handle, &cmd->location); + + /* Delete by description */ + rule = search_first_rule(cmd->rule); + if (!rule) + return 0; + return netlink_del_rule_batch(ctx, &rule->handle, + &rule->handle.position.location); +} + static int do_command_delete(struct netlink_ctx *ctx, struct cmd *cmd) { switch (cmd->obj) { @@ -1018,8 +1060,7 @@ static int do_command_delete(struct netlink_ctx *ctx, struct cmd *cmd) case CMD_OBJ_CHAIN: return netlink_delete_chain(ctx, &cmd->handle, &cmd->location); case CMD_OBJ_RULE: - return netlink_del_rule_batch(ctx, &cmd->handle, - &cmd->location); + return do_delete_rule(ctx, cmd); case CMD_OBJ_SET: return netlink_delete_set(ctx, &cmd->handle, &cmd->location); case CMD_OBJ_SETELEM: -- 2.8.3 -- 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