]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add support to command "destroy"
authorFernando F. Mancera <ffmancera@riseup.net>
Mon, 6 Feb 2023 10:06:42 +0000 (11:06 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 6 Feb 2023 10:09:38 +0000 (11:09 +0100)
"destroy" command performs a deletion as "delete" command but does not fail
if the object does not exist. As there is no NLM_F_* flag for ignoring such
error, it needs to be ignored directly on error handling.

Example of use:

# nft list ruleset
        table ip filter {
                chain output {
                }
        }
        # nft destroy table ip missingtable
# echo $?
0
        # nft list ruleset
        table ip filter {
                chain output {
                }
        }

Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
14 files changed:
doc/nft.txt
include/linux/netfilter/nf_tables.h
include/rule.h
src/cache.c
src/evaluate.c
src/mnl.c
src/parser_bison.y
src/parser_json.c
src/rule.c
src/scanner.l
tests/shell/testcases/rule_management/0011destroy_0 [new file with mode: 0755]
tests/shell/testcases/rule_management/0012destroy_0 [new file with mode: 0755]
tests/shell/testcases/rule_management/dumps/0011destroy_0.nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0012destroy_0.nft [new file with mode: 0644]

index 18c18468c31b0bce8865092227e69e96970699ce..7de4935b4b375edd28a29657f5b56d1b7a7e5fa9 100644 (file)
@@ -322,9 +322,10 @@ TABLES
 ------
 [verse]
 {*add* | *create*} *table* ['family'] 'table' [ {*comment* 'comment' *;*'} *{ flags* 'flags' *; }*]
-{*delete* | *list* | *flush*} *table* ['family'] 'table'
+{*delete* | *destroy* | *list* | *flush*} *table* ['family'] 'table'
 *list tables* ['family']
 *delete table* ['family'] *handle* 'handle'
+*destroy table* ['family'] *handle* 'handle'
 
 Tables are containers for chains, sets and stateful objects. They are identified
 by their address family and their name. The address family must be one of *ip*,
@@ -368,6 +369,7 @@ add table inet mytable
 [horizontal]
 *add*:: Add a new table for the given family with the given name.
 *delete*:: Delete the specified table.
+*destroy*:: Delete the specified table, it does not fail if it does not exist.
 *list*:: List all chains and rules of the specified table.
 *flush*:: Flush all chains and rules of the specified table.
 
@@ -375,9 +377,10 @@ CHAINS
 ------
 [verse]
 {*add* | *create*} *chain* ['family'] 'table' 'chain' [*{ type* 'type' *hook* 'hook' [*device* 'device'] *priority* 'priority' *;* [*policy* 'policy' *;*] [*comment* 'comment' *;*'] *}*]
-{*delete* | *list* | *flush*} *chain* ['family'] 'table' 'chain'
+{*delete* | *destroy* | *list* | *flush*} *chain* ['family'] 'table' 'chain'
 *list chains* ['family']
 *delete chain* ['family'] 'table' *handle* 'handle'
+*destroy chain* ['family'] 'table' *handle* 'handle'
 *rename chain* ['family'] 'table' 'chain' 'newname'
 
 Chains are containers for rules. They exist in two kinds, base chains and
@@ -390,6 +393,7 @@ organization.
 are specified, the chain is created as a base chain and hooked up to the networking stack.
 *create*:: Similar to the *add* command, but returns an error if the chain already exists.
 *delete*:: Delete the specified chain. The chain must not contain any rules or be used as jump target.
+*destroy*:: Delete the specified chain, it does not fail if it does not exist. The chain must not contain any rules or be used as jump target.
 *rename*:: Rename the specified chain.
 *list*:: List all rules of the specified chain.
 *flush*:: Flush all rules of the specified chain.
@@ -482,6 +486,7 @@ RULES
 {*add* | *insert*} *rule* ['family'] 'table' 'chain' [*handle* 'handle' | *index* 'index'] 'statement' ... [*comment* 'comment']
 *replace rule* ['family'] 'table' 'chain' *handle* 'handle' 'statement' ... [*comment* 'comment']
 {*delete* | *reset*} *rule* ['family'] 'table' 'chain' *handle* 'handle'
+*destroy rule* ['family'] 'table' 'chain' *handle* 'handle'
 *reset rules* ['family']
 *reset rules* *table* ['family'] 'table'
 *reset rules* *chain* ['family'] 'table' ['chain']
@@ -512,6 +517,7 @@ case the rule is inserted after the specified rule.
 beginning of the chain or before the specified rule.
 *replace*:: Similar to *add*, but the rule replaces the specified rule.
 *delete*:: Delete the specified rule.
+*destroy*:: Delete the specified rule, it does not fail if it does not exist.
 *reset*:: Reset rule-contained state, i.e. counter and quota statement values.
 
 .*add a rule to ip table output chain*
@@ -563,10 +569,10 @@ section describes nft set syntax in more detail.
 
 [verse]
 *add set* ['family'] 'table' 'set' *{ type* 'type' | *typeof* 'expression' *;* [*flags* 'flags' *;*] [*timeout* 'timeout' *;*] [*gc-interval* 'gc-interval' *;*] [*elements = {* 'element'[*,* ...] *} ;*] [*size* 'size' *;*] [*comment* 'comment' *;*'] [*policy* 'policy' *;*] [*auto-merge ;*] *}*
-{*delete* | *list* | *flush*} *set* ['family'] 'table' 'set'
+{*delete* | *destroy* | *list* | *flush*} *set* ['family'] 'table' 'set'
 *list sets* ['family']
 *delete set* ['family'] 'table' *handle* 'handle'
-{*add* | *delete*} *element* ['family'] 'table' 'set' *{* 'element'[*,* ...] *}*
+{*add* | *delete* | *destroy* } *element* ['family'] 'table' 'set' *{* 'element'[*,* ...] *}*
 
 Sets are element containers of a user-defined data type, they are uniquely
 identified by a user-defined name and attached to tables. Their behaviour can
@@ -575,6 +581,7 @@ be tuned with the flags that can be specified at set creation time.
 [horizontal]
 *add*:: Add a new set in the specified table. See the Set specification table below for more information about how to specify properties of a set.
 *delete*:: Delete the specified set.
+*destroy*:: Delete the specified set, it does not fail if it does not exist.
 *list*:: Display the elements in the specified set.
 *flush*:: Remove all elements from the specified set.
 
@@ -616,7 +623,7 @@ MAPS
 -----
 [verse]
 *add map* ['family'] 'table' 'map' *{ type* 'type' | *typeof* 'expression' [*flags* 'flags' *;*] [*elements = {* 'element'[*,* ...] *} ;*] [*size* 'size' *;*] [*comment* 'comment' *;*'] [*policy* 'policy' *;*] *}*
-{*delete* | *list* | *flush*} *map* ['family'] 'table' 'map'
+{*delete* | *destroy* | *list* | *flush*} *map* ['family'] 'table' 'map'
 *list maps* ['family']
 
 Maps store data based on some specific key used as input. They are uniquely identified by a user-defined name and attached to tables.
@@ -624,6 +631,7 @@ Maps store data based on some specific key used as input. They are uniquely iden
 [horizontal]
 *add*:: Add a new map in the specified table.
 *delete*:: Delete the specified map.
+*destroy*:: Delete the specified map, it does not fail if it does not exist.
 *list*:: Display the elements in the specified map.
 *flush*:: Remove all elements from the specified map.
 *add element*:: Comma-separated list of elements to add into the specified map.
@@ -658,7 +666,7 @@ ELEMENTS
 --------
 [verse]
 ____
-{*add* | *create* | *delete* | *get* } *element* ['family'] 'table' 'set' *{* 'ELEMENT'[*,* ...] *}*
+{*add* | *create* | *delete* | *destroy* | *get* } *element* ['family'] 'table' 'set' *{* 'ELEMENT'[*,* ...] *}*
 
 'ELEMENT' := 'key_expression' 'OPTIONS' [*:* 'value_expression']
 'OPTIONS' := [*timeout* 'TIMESPEC'] [*expires* 'TIMESPEC'] [*comment* 'string']
@@ -696,7 +704,7 @@ FLOWTABLES
 [verse]
 {*add* | *create*} *flowtable* ['family'] 'table' 'flowtable' *{ hook* 'hook' *priority* 'priority' *; devices = {* 'device'[*,* ...] *} ; }*
 *list flowtables* ['family']
-{*delete* | *list*} *flowtable* ['family'] 'table' 'flowtable'
+{*delete* | *destroy* | *list*} *flowtable* ['family'] 'table' 'flowtable'
 *delete* *flowtable* ['family'] 'table' *handle* 'handle'
 
 Flowtables allow you to accelerate packet forwarding in software. Flowtables
@@ -720,6 +728,7 @@ and subtraction can be used to set relative priority, e.g. filter + 5 equals to
 [horizontal]
 *add*:: Add a new flowtable for the given family with the given name.
 *delete*:: Delete the specified flowtable.
+*destroy*:: Delete the specified flowtable, it does not fail if it does not exist.
 *list*:: List all flowtables.
 
 LISTING
@@ -736,12 +745,15 @@ kernel modules, such as nf_conntrack.
 STATEFUL OBJECTS
 ----------------
 [verse]
-{*add* | *delete* | *list* | *reset*} *counter* ['family'] 'table' 'object'
-{*add* | *delete* | *list* | *reset*} *quota* ['family'] 'table' 'object'
-{*add* | *delete* | *list*} *limit* ['family'] 'table' 'object'
+{*add* | *delete* | *destroy* | *list* | *reset*} *counter* ['family'] 'table' 'object'
+{*add* | *delete* | *destroy* | *list* | *reset*} *quota* ['family'] 'table' 'object'
+{*add* | *delete* | *destroy* | *list*} *limit* ['family'] 'table' 'object'
 *delete* 'counter' ['family'] 'table' *handle* 'handle'
 *delete* 'quota' ['family'] 'table' *handle* 'handle'
 *delete* 'limit' ['family'] 'table' *handle* 'handle'
+*destroy* 'counter' ['family'] 'table' *handle* 'handle'
+*destroy* 'quota' ['family'] 'table' *handle* 'handle'
+*destroy* 'limit' ['family'] 'table' *handle* 'handle'
 *list counters* ['family']
 *list quotas* ['family']
 *list limits* ['family']
@@ -757,6 +769,7 @@ keywords "type name" are used e.g. "counter name".
 [horizontal]
 *add*:: Add a new stateful object in the specified table.
 *delete*:: Delete the specified object.
+*destroy*:: Delete the specified object, it does not fail if it does not exist.
 *list*:: Display stateful information the object holds.
 *reset*:: List-and-reset stateful object.
 
index 3d045030e3ad3f2418cddb222433cdc61a1f1644..ff677f3a6cadbe831ddff2d2996dc61c51e350d8 100644 (file)
@@ -97,6 +97,14 @@ enum nft_verdicts {
  * @NFT_MSG_NEWFLOWTABLE: add new flow table (enum nft_flowtable_attributes)
  * @NFT_MSG_GETFLOWTABLE: get flow table (enum nft_flowtable_attributes)
  * @NFT_MSG_DELFLOWTABLE: delete flow table (enum nft_flowtable_attributes)
+ * @NFT_MSG_GETRULE_RESET: get rules and reset stateful expressions (enum nft_obj_attributes)
+ * @NFT_MSG_DESTROYTABLE: destroy a table (enum nft_table_attributes)
+ * @NFT_MSG_DESTROYCHAIN: destroy a chain (enum nft_chain_attributes)
+ * @NFT_MSG_DESTROYRULE: destroy a rule (enum nft_rule_attributes)
+ * @NFT_MSG_DESTROYSET: destroy a set (enum nft_set_attributes)
+ * @NFT_MSG_DESTROYSETELEM: destroy a set element (enum nft_set_elem_attributes)
+ * @NFT_MSG_DESTROYOBJ: destroy a stateful object (enum nft_object_attributes)
+ * @NFT_MSG_DESTROYFLOWTABLE: destroy flow table (enum nft_flowtable_attributes)
  */
 enum nf_tables_msg_types {
        NFT_MSG_NEWTABLE,
@@ -125,6 +133,13 @@ enum nf_tables_msg_types {
        NFT_MSG_GETFLOWTABLE,
        NFT_MSG_DELFLOWTABLE,
        NFT_MSG_GETRULE_RESET,
+       NFT_MSG_DESTROYTABLE,
+       NFT_MSG_DESTROYCHAIN,
+       NFT_MSG_DESTROYRULE,
+       NFT_MSG_DESTROYSET,
+       NFT_MSG_DESTROYSETELEM,
+       NFT_MSG_DESTROYOBJ,
+       NFT_MSG_DESTROYFLOWTABLE,
        NFT_MSG_MAX,
 };
 
index 22c611f6068f3afbe2728c5d7a9b56414ec3ed7d..0828d16122aca7a024ead11f7d410de22fb2afc6 100644 (file)
@@ -563,6 +563,7 @@ void flowtable_print(const struct flowtable *n, struct output_ctx *octx);
  * @CMD_EXPORT:                export the ruleset in a given format
  * @CMD_MONITOR:       event listener
  * @CMD_DESCRIBE:      describe an expression
+ * @CMD_DESTROY:       destroy object
  */
 enum cmd_ops {
        CMD_INVALID,
@@ -580,6 +581,7 @@ enum cmd_ops {
        CMD_EXPORT,
        CMD_MONITOR,
        CMD_DESCRIBE,
+       CMD_DESTROY,
 };
 
 /**
index 0f5d1099f1027767f3367238e5b0763969fe68b8..38bc219abc579d7e1a4f2c3dbe30ee5e0296da2c 100644 (file)
@@ -416,6 +416,7 @@ int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds,
                        flags = NFT_CACHE_FULL;
                        break;
                case CMD_DELETE:
+               case CMD_DESTROY:
                        flags |= NFT_CACHE_TABLE |
                                 NFT_CACHE_CHAIN |
                                 NFT_CACHE_SET |
index 2182d8f1d73291b6abee7bf2021d7fc193ca40b6..128b750406e5941ac5387a8d3f3ad45522b8cf75 100644 (file)
@@ -1677,6 +1677,7 @@ static int interval_set_eval(struct eval_ctx *ctx, struct set *set,
                }
                break;
        case CMD_DELETE:
+       case CMD_DESTROY:
                ret = set_delete(ctx->msgs, ctx->cmd, set, init,
                                 ctx->nft->debug_mask);
                break;
@@ -5560,6 +5561,7 @@ static const char * const cmd_op_name[] = {
        [CMD_EXPORT]    = "export",
        [CMD_MONITOR]   = "monitor",
        [CMD_DESCRIBE]  = "describe",
+       [CMD_DESTROY]   = "destroy",
 };
 
 static const char *cmd_op_to_name(enum cmd_ops op)
@@ -5592,6 +5594,7 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
        case CMD_INSERT:
                return cmd_evaluate_add(ctx, cmd);
        case CMD_DELETE:
+       case CMD_DESTROY:
                return cmd_evaluate_delete(ctx, cmd);
        case CMD_GET:
                return cmd_evaluate_get(ctx, cmd);
index ca01516ca72a2c0785ec840111c380b1cef1d34a..d5fd58c302b82bd9431a4096eed3c9f33196204a 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -592,6 +592,7 @@ int mnl_nft_rule_replace(struct netlink_ctx *ctx, struct cmd *cmd)
 
 int mnl_nft_rule_del(struct netlink_ctx *ctx, struct cmd *cmd)
 {
+       enum nf_tables_msg_types msg_type = NFT_MSG_DELRULE;
        struct handle *h = &cmd->handle;
        struct nftnl_rule *nlr;
        struct nlmsghdr *nlh;
@@ -602,8 +603,11 @@ int mnl_nft_rule_del(struct netlink_ctx *ctx, struct cmd *cmd)
 
        nftnl_rule_set_u32(nlr, NFTNL_RULE_FAMILY, h->family);
 
+       if (cmd->op == CMD_DESTROY)
+               msg_type = NFT_MSG_DESTROYRULE;
+
        nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
-                                   NFT_MSG_DELRULE,
+                                   msg_type,
                                    nftnl_rule_get_u32(nlr, NFTNL_RULE_FAMILY),
                                    0, ctx->seqnum);
 
@@ -857,6 +861,7 @@ int mnl_nft_chain_rename(struct netlink_ctx *ctx, const struct cmd *cmd,
 
 int mnl_nft_chain_del(struct netlink_ctx *ctx, struct cmd *cmd)
 {
+       enum nf_tables_msg_types msg_type = NFT_MSG_DELCHAIN;
        struct nftnl_chain *nlc;
        struct nlmsghdr *nlh;
 
@@ -866,8 +871,11 @@ int mnl_nft_chain_del(struct netlink_ctx *ctx, struct cmd *cmd)
 
        nftnl_chain_set_u32(nlc, NFTNL_CHAIN_FAMILY, cmd->handle.family);
 
+       if (cmd->op == CMD_DESTROY)
+               msg_type = NFT_MSG_DESTROYCHAIN;
+
        nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
-                                   NFT_MSG_DELCHAIN,
+                                   msg_type,
                                    cmd->handle.family,
                                    0, ctx->seqnum);
 
@@ -1002,6 +1010,7 @@ int mnl_nft_table_add(struct netlink_ctx *ctx, struct cmd *cmd,
 
 int mnl_nft_table_del(struct netlink_ctx *ctx, struct cmd *cmd)
 {
+       enum nf_tables_msg_types msg_type = NFT_MSG_DELTABLE;
        struct nftnl_table *nlt;
        struct nlmsghdr *nlh;
 
@@ -1011,10 +1020,11 @@ int mnl_nft_table_del(struct netlink_ctx *ctx, struct cmd *cmd)
 
        nftnl_table_set_u32(nlt, NFTNL_TABLE_FAMILY, cmd->handle.family);
 
-       nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
-                                   NFT_MSG_DELTABLE,
-                                   cmd->handle.family,
-                                   0, ctx->seqnum);
+       if (cmd->op == CMD_DESTROY)
+               msg_type = NFT_MSG_DESTROYTABLE;
+
+       nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch), msg_type,
+                                   cmd->handle.family, 0, ctx->seqnum);
 
        if (cmd->handle.table.name) {
                cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.table.location);
@@ -1248,6 +1258,7 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, struct cmd *cmd,
 
 int mnl_nft_set_del(struct netlink_ctx *ctx, struct cmd *cmd)
 {
+       enum nf_tables_msg_types msg_type = NFT_MSG_DELSET;
        const struct handle *h = &cmd->handle;
        struct nftnl_set *nls;
        struct nlmsghdr *nlh;
@@ -1258,8 +1269,11 @@ int mnl_nft_set_del(struct netlink_ctx *ctx, struct cmd *cmd)
 
        nftnl_set_set_u32(nls, NFTNL_SET_FAMILY, h->family);
 
+       if (cmd->op == CMD_DESTROY)
+               msg_type = NFT_MSG_DESTROYSET;
+
        nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
-                                   NFT_MSG_DELSET,
+                                   msg_type,
                                    h->family,
                                    0, ctx->seqnum);
 
@@ -1463,6 +1477,7 @@ int mnl_nft_obj_add(struct netlink_ctx *ctx, struct cmd *cmd,
 
 int mnl_nft_obj_del(struct netlink_ctx *ctx, struct cmd *cmd, int type)
 {
+       enum nf_tables_msg_types msg_type = NFT_MSG_DELOBJ;
        struct nftnl_obj *nlo;
        struct nlmsghdr *nlh;
 
@@ -1473,8 +1488,11 @@ int mnl_nft_obj_del(struct netlink_ctx *ctx, struct cmd *cmd, int type)
        nftnl_obj_set_u32(nlo, NFTNL_OBJ_FAMILY, cmd->handle.family);
        nftnl_obj_set_u32(nlo, NFTNL_OBJ_TYPE, type);
 
+       if (cmd->op == CMD_DESTROY)
+               msg_type = NFT_MSG_DESTROYOBJ;
+
        nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
-                                   NFT_MSG_DELOBJ, cmd->handle.family,
+                                   msg_type, cmd->handle.family,
                                    0, ctx->seqnum);
 
        cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.table.location);
@@ -1747,6 +1765,7 @@ int mnl_nft_setelem_flush(struct netlink_ctx *ctx, const struct cmd *cmd)
 int mnl_nft_setelem_del(struct netlink_ctx *ctx, struct cmd *cmd,
                        const struct handle *h, const struct expr *init)
 {
+       enum nf_tables_msg_types msg_type = NFT_MSG_DELSETELEM;
        struct nftnl_set *nls;
        int err;
 
@@ -1763,7 +1782,10 @@ int mnl_nft_setelem_del(struct netlink_ctx *ctx, struct cmd *cmd,
 
        netlink_dump_set(nls, ctx);
 
-       err = mnl_nft_setelem_batch(nls, cmd, ctx->batch, NFT_MSG_DELSETELEM, 0,
+       if (cmd->op == CMD_DESTROY)
+               msg_type = NFT_MSG_DESTROYSETELEM;
+
+       err = mnl_nft_setelem_batch(nls, cmd, ctx->batch, msg_type, 0,
                                    ctx->seqnum, init, ctx);
        nftnl_set_free(nls);
 
@@ -1970,6 +1992,7 @@ int mnl_nft_flowtable_add(struct netlink_ctx *ctx, struct cmd *cmd,
 
 int mnl_nft_flowtable_del(struct netlink_ctx *ctx, struct cmd *cmd)
 {
+       enum nf_tables_msg_types msg_type = NFT_MSG_DELFLOWTABLE;
        struct nftnl_flowtable *flo;
        const char **dev_array;
        struct nlmsghdr *nlh;
@@ -1991,8 +2014,11 @@ int mnl_nft_flowtable_del(struct netlink_ctx *ctx, struct cmd *cmd)
                nft_flowtable_dev_array_free(dev_array);
        }
 
+       if (cmd->op == CMD_DESTROY)
+               msg_type = NFT_MSG_DESTROYFLOWTABLE;
+
        nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
-                                   NFT_MSG_DELFLOWTABLE, cmd->handle.family,
+                                   msg_type, cmd->handle.family,
                                    0, ctx->seqnum);
 
        cmd_add_loc(cmd, nlh->nlmsg_len, &cmd->handle.table.location);
index 62a4809b9ee7e7c09d898e19ba41dd149e7a4fa5..b229de7a5cf7d065b6ac65a8b4f68a93facbff21 100644 (file)
@@ -291,6 +291,8 @@ int nft_lex(void *, void *, void *);
 %token DESCRIBE                        "describe"
 %token IMPORT                  "import"
 %token EXPORT                  "export"
+%token DESTROY                 "destroy"
+
 %token MONITOR                 "monitor"
 
 %token ALL                     "all"
@@ -650,8 +652,8 @@ int nft_lex(void *, void *, void *);
 %type <cmd>                    line
 %destructor { cmd_free($$); }  line
 
-%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 <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 destroy_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 destroy_cmd
 
 %type <handle>                 table_spec tableid_spec table_or_id_spec
 %destructor { handle_free(&$$); } table_spec tableid_spec table_or_id_spec
@@ -1102,6 +1104,7 @@ base_cmd          :       /* empty */     add_cmd         { $$ = $1; }
                        |       EXPORT          export_cmd      close_scope_export      { $$ = $2; }
                        |       MONITOR         monitor_cmd     close_scope_monitor     { $$ = $2; }
                        |       DESCRIBE        describe_cmd    { $$ = $2; }
+                       |       DESTROY         destroy_cmd     { $$ = $2; }
                        ;
 
 add_cmd                        :       TABLE           table_spec
@@ -1409,6 +1412,74 @@ delete_cmd               :       TABLE           table_or_id_spec
                        }
                        ;
 
+destroy_cmd            :       TABLE           table_or_id_spec
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_TABLE, &$2, &@$, NULL);
+                       }
+                       |       CHAIN           chain_or_id_spec
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_CHAIN, &$2, &@$, NULL);
+                       }
+                       |       RULE            ruleid_spec
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_RULE, &$2, &@$, NULL);
+                       }
+                       |       SET             set_or_id_spec
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_SET, &$2, &@$, NULL);
+                       }
+                       |       MAP             set_spec
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_SET, &$2, &@$, NULL);
+                       }
+                       |       ELEMENT         set_spec        set_block_expr
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
+                       }
+                       |       FLOWTABLE       flowtable_spec
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_FLOWTABLE, &$2, &@$, NULL);
+                       }
+                       |       FLOWTABLE       flowtableid_spec
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_FLOWTABLE, &$2, &@$, NULL);
+                       }
+                       |       FLOWTABLE       flowtable_spec  flowtable_block_alloc
+                                               '{'     flowtable_block '}'
+                       {
+                               $5->location = @5;
+                               handle_merge(&$3->handle, &$2);
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_FLOWTABLE, &$2, &@$, $5);
+                       }
+                       |       COUNTER         obj_or_id_spec  close_scope_counter
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_COUNTER, &$2, &@$, NULL);
+                       }
+                       |       QUOTA           obj_or_id_spec  close_scope_quota
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_QUOTA, &$2, &@$, NULL);
+                       }
+                       |       CT      ct_obj_type     obj_spec        ct_obj_alloc    close_scope_ct
+                       {
+                               $$ = cmd_alloc_obj_ct(CMD_DESTROY, $2, &$3, &@$, $4);
+                               if ($2 == NFT_OBJECT_CT_TIMEOUT)
+                                       init_list_head(&$4->ct_timeout.timeout_list);
+                       }
+                       |       LIMIT           obj_or_id_spec  close_scope_limit
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_LIMIT, &$2, &@$, NULL);
+                       }
+                       |       SECMARK         obj_or_id_spec  close_scope_secmark
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_SECMARK, &$2, &@$, NULL);
+                       }
+                       |       SYNPROXY        obj_or_id_spec  close_scope_synproxy
+                       {
+                               $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_SYNPROXY, &$2, &@$, NULL);
+                       }
+                       ;
+
+
 get_cmd                        :       ELEMENT         set_spec        set_block_expr
                        {
                                $$ = cmd_alloc(CMD_GET, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
index dfab3f9cbc7d3e5fca263d92b4bed4d177c969e8..ec0c02a044e23a33f74ea36f99c95e90785e6265 100644 (file)
@@ -2936,7 +2936,7 @@ static struct cmd *json_parse_cmd_add_rule(struct json_ctx *ctx, json_t *root,
        if (op != CMD_DELETE &&
            json_unpack_err(ctx, root, "{s:o}", "expr", &tmp))
                return NULL;
-       else if (op == CMD_DELETE &&
+       else if ((op == CMD_DELETE || op == CMD_DESTROY) &&
                 json_unpack_err(ctx, root, "{s:I}", "handle", &h.handle.id))
                return NULL;
 
@@ -2947,7 +2947,7 @@ static struct cmd *json_parse_cmd_add_rule(struct json_ctx *ctx, json_t *root,
        h.table.name = xstrdup(h.table.name);
        h.chain.name = xstrdup(h.chain.name);
 
-       if (op == CMD_DELETE)
+       if (op == CMD_DELETE || op == CMD_DESTROY)
                return cmd_alloc(op, obj, &h, int_loc, NULL);
 
        if (!json_is_array(tmp)) {
@@ -3043,7 +3043,7 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
        if (op != CMD_DELETE &&
            json_unpack_err(ctx, root, "{s:s}", "name", &h.set.name)) {
                return NULL;
-       } else if (op == CMD_DELETE &&
+       } else if ((op == CMD_DELETE || op == CMD_DESTROY) &&
                   json_unpack(root, "{s:s}", "name", &h.set.name) &&
                   json_unpack(root, "{s:I}", "handle", &h.handle.id)) {
                json_error(ctx, "Either name or handle required to delete a set.");
@@ -3060,6 +3060,7 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
 
        switch (op) {
        case CMD_DELETE:
+       case CMD_DESTROY:
        case CMD_LIST:
        case CMD_FLUSH:
                return cmd_alloc(op, obj, &h, int_loc, NULL);
@@ -3241,7 +3242,7 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx,
        if (op != CMD_DELETE &&
            json_unpack_err(ctx, root, "{s:s}", "name", &h.flowtable.name)) {
                return NULL;
-       } else if (op == CMD_DELETE &&
+       } else if ((op == CMD_DELETE || op == CMD_DESTROY) &&
                   json_unpack(root, "{s:s}", "name", &h.flowtable.name) &&
                   json_unpack(root, "{s:I}", "handle", &h.handle.id)) {
                json_error(ctx, "Either name or handle required to delete a flowtable.");
@@ -3256,7 +3257,7 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx,
        if (h.flowtable.name)
                h.flowtable.name = xstrdup(h.flowtable.name);
 
-       if (op == CMD_DELETE || op == CMD_LIST)
+       if (op == CMD_DELETE || op == CMD_LIST || op == CMD_DESTROY)
                return cmd_alloc(op, cmd_obj, &h, int_loc, NULL);
 
        if (json_unpack_err(ctx, root, "{s:s, s:I}",
@@ -3345,7 +3346,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
             cmd_obj == NFT_OBJECT_CT_HELPER) &&
            json_unpack_err(ctx, root, "{s:s}", "name", &h.obj.name)) {
                return NULL;
-       } else if (op == CMD_DELETE &&
+       } else if ((op == CMD_DELETE || op == CMD_DESTROY) &&
                   cmd_obj != NFT_OBJECT_CT_HELPER &&
                   json_unpack(root, "{s:s}", "name", &h.obj.name) &&
                   json_unpack(root, "{s:I}", "handle", &h.handle.id)) {
@@ -3361,7 +3362,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
        if (h.obj.name)
                h.obj.name = xstrdup(h.obj.name);
 
-       if (op == CMD_DELETE || op == CMD_LIST) {
+       if (op == CMD_DELETE || op == CMD_LIST || op == CMD_DESTROY) {
                if (cmd_obj == NFT_OBJECT_CT_HELPER)
                        return cmd_alloc_obj_ct(op, NFT_OBJECT_CT_HELPER,
                                                &h, int_loc, obj_alloc(int_loc));
@@ -3909,6 +3910,7 @@ static struct cmd *json_parse_cmd(struct json_ctx *ctx, json_t *root)
                { "reset", CMD_RESET, json_parse_cmd_reset },
                { "flush", CMD_FLUSH, json_parse_cmd_flush },
                { "rename", CMD_RENAME, json_parse_cmd_rename },
+               { "destroy", CMD_DESTROY, json_parse_cmd_add },
                //{ "export", CMD_EXPORT, json_parse_cmd_export },
                //{ "monitor", CMD_MONITOR, json_parse_cmd_monitor },
                //{ "describe", CMD_DESCRIBE, json_parse_cmd_describe }
index 371c803a57c6067695d822bd86d8fa18b9c71795..a58fd1f2483a6c07062f7bd73ed1df03f32a79bb 100644 (file)
@@ -2738,6 +2738,7 @@ int do_command(struct netlink_ctx *ctx, struct cmd *cmd)
        case CMD_REPLACE:
                return do_command_replace(ctx, cmd);
        case CMD_DELETE:
+       case CMD_DESTROY:
                return do_command_delete(ctx, cmd);
        case CMD_GET:
                return do_command_get(ctx, cmd);
index aa0a0a9f94fdf62860fae219c23abadd237ab0be..c0c49b97ade7a407edf6abe317b095457c2bec01 100644 (file)
@@ -359,6 +359,7 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 "import"                { scanner_push_start_cond(yyscanner, SCANSTATE_CMD_IMPORT); return IMPORT; }
 "export"               { scanner_push_start_cond(yyscanner, SCANSTATE_CMD_EXPORT); return EXPORT; }
 "monitor"              { scanner_push_start_cond(yyscanner, SCANSTATE_CMD_MONITOR); return MONITOR; }
+"destroy"              { return DESTROY; }
 
 "position"             { return POSITION; }
 "index"                        { return INDEX; }
diff --git a/tests/shell/testcases/rule_management/0011destroy_0 b/tests/shell/testcases/rule_management/0011destroy_0
new file mode 100755 (executable)
index 0000000..895c24a
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+set -e
+$NFT add table t
+$NFT add chain t c
+$NFT insert rule t c accept # should have handle 2
+
+$NFT destroy rule t c handle 2
diff --git a/tests/shell/testcases/rule_management/0012destroy_0 b/tests/shell/testcases/rule_management/0012destroy_0
new file mode 100755 (executable)
index 0000000..1b61155
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+set -e
+$NFT add table t
+$NFT add chain t c
+
+$NFT destroy rule t c handle 3333
diff --git a/tests/shell/testcases/rule_management/dumps/0011destroy_0.nft b/tests/shell/testcases/rule_management/dumps/0011destroy_0.nft
new file mode 100644 (file)
index 0000000..1e0d1d6
--- /dev/null
@@ -0,0 +1,4 @@
+table ip t {
+       chain c {
+       }
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0012destroy_0.nft b/tests/shell/testcases/rule_management/dumps/0012destroy_0.nft
new file mode 100644 (file)
index 0000000..1e0d1d6
--- /dev/null
@@ -0,0 +1,4 @@
+table ip t {
+       chain c {
+       }
+}