@@ -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;
@@ -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);
}
;
@@ -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:
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@riseup.net> --- src/evaluate.c | 6 ++++++ src/parser_bison.y | 32 ++++++++++++++++++++++++-------- src/rule.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 73 insertions(+), 10 deletions(-)