]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: reset internal stateful objects
authorPablo Neira Ayuso <pablo@netfilter.org>
Sun, 27 Nov 2016 22:42:54 +0000 (23:42 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 3 Jan 2017 13:21:53 +0000 (14:21 +0100)
This patch allows you to atomically dump and reset stateful objects, eg.

 # nft list counters
 table ip filter {
        counter test {
              packets 1024 bytes 100000
        }
 }
 # nft reset quotas table filter
 counter test {
        packets 1024 bytes 100000
 }
 # nft reset quotas table filter
 counter test {
        packets 0 bytes 0
 }

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/mnl.h
include/netlink.h
include/rule.h
src/evaluate.c
src/mnl.c
src/netlink.c
src/parser_bison.y
src/rule.c
src/scanner.l

index d178bd27a75a7992da59501558cf035b7c074f64..4a99972d416384eee39f8dffb513f7c637809f10 100644 (file)
@@ -87,7 +87,8 @@ int mnl_nft_setelem_batch_flush(struct nftnl_set *nls, unsigned int flags,
 int mnl_nft_setelem_get(struct mnl_socket *nf_sock, struct nftnl_set *nls);
 
 struct nftnl_obj_list *mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family,
-                                       const char *table);
+                                       const char *table, uint32_t type,
+                                       bool reset);
 int mnl_nft_obj_batch_add(struct nftnl_obj *nln, unsigned int flags,
                          uint32_t seqnum);
 int mnl_nft_obj_batch_del(struct nftnl_obj *nln, unsigned int flags,
index 841211c43760ca1049d11e71a7b0a051048765bc..450aba571a979ca7aff1320e100b9de42d373b79 100644 (file)
@@ -170,11 +170,13 @@ extern int netlink_flush_setelems(struct netlink_ctx *ctx, const struct handle *
                                  const struct location *loc);
 
 extern int netlink_list_objs(struct netlink_ctx *ctx, const struct handle *h,
-                              const struct location *loc);
+                            const struct location *loc);
+extern int netlink_reset_objs(struct netlink_ctx *ctx, const struct handle *h,
+                             const struct location *loc, uint32_t type);
 extern int netlink_add_obj(struct netlink_ctx *ctx, const struct handle *h,
                           struct obj *obj, bool excl);
 extern int netlink_delete_obj(struct netlink_ctx *ctx, const struct handle *h,
-                             struct location *loc, enum stmt_types type);
+                             struct location *loc, uint32_t type);
 
 extern void netlink_dump_table(const struct nftnl_table *nlt);
 extern void netlink_dump_chain(const struct nftnl_chain *nlc);
index 88acbcc7b1633e076d71e665ea89bdc43694eceb..9028c84b0033d6c9181d3c7fba6615915b23e633 100644 (file)
@@ -294,6 +294,7 @@ const char *obj_type_name(uint32_t type);
  * @CMD_INSERT:                insert object
  * @CMD_DELETE:                delete object
  * @CMD_LIST:          list container
+ * @CMD_RESET:         reset container
  * @CMD_FLUSH:         flush container
  * @CMD_RENAME:                rename object
  * @CMD_EXPORT:                export the ruleset in a given format
@@ -308,6 +309,7 @@ enum cmd_ops {
        CMD_INSERT,
        CMD_DELETE,
        CMD_LIST,
+       CMD_RESET,
        CMD_FLUSH,
        CMD_RENAME,
        CMD_EXPORT,
index 9bc3b7d6477aafde5bf3e44756b04884d90c74f7..cedf259fcba9ef61a14f59bc0da4d0eb7186c09b 100644 (file)
@@ -3052,6 +3052,7 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
        case CMD_DELETE:
                return cmd_evaluate_delete(ctx, cmd);
        case CMD_LIST:
+       case CMD_RESET:
                return cmd_evaluate_list(ctx, cmd);
        case CMD_FLUSH:
                return cmd_evaluate_flush(ctx, cmd);
index 9458e21bf8b437db6599ef5b197ce59c2f0ee61f..52cb7736e3240cc36162b9cf5d9174340609d179 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -851,22 +851,30 @@ err_free:
 
 
 struct nftnl_obj_list *
-mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family, const char *table)
+mnl_nft_obj_dump(struct mnl_socket *nf_sock, int family, const char *table,
+                uint32_t type, bool reset)
 {
        struct nftnl_obj_list *nln_list;
        char buf[MNL_SOCKET_BUFFER_SIZE];
        struct nftnl_obj *n;
        struct nlmsghdr *nlh;
-       int ret;
+       int msg_type, ret;
+
+       if (reset)
+               msg_type = NFT_MSG_GETOBJ_RESET;
+       else
+               msg_type = NFT_MSG_GETOBJ;
 
        n = nftnl_obj_alloc();
        if (n == NULL)
                memory_allocation_error();
 
-       nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETOBJ, family,
+       nlh = nftnl_nlmsg_build_hdr(buf, msg_type, family,
                                    NLM_F_DUMP | NLM_F_ACK, seq);
        if (table != NULL)
                nftnl_obj_set(n, NFTNL_OBJ_TABLE, table);
+       if (type != NFT_OBJECT_UNSPEC)
+               nftnl_obj_set_u32(n, NFTNL_OBJ_TYPE, type);
        nftnl_obj_nlmsg_build_payload(nlh, n);
        nftnl_obj_free(n);
 
index d11b3c01f2645a1bb577e941975d104208c4ac1b..68bed201a36d856dd9a793f5757c0352e43fa824 100644 (file)
@@ -1755,7 +1755,29 @@ int netlink_list_objs(struct netlink_ctx *ctx, const struct handle *h,
        struct nftnl_obj_list *obj_cache;
        int err;
 
-       obj_cache = mnl_nft_obj_dump(nf_sock, h->family, h->table);
+       obj_cache = mnl_nft_obj_dump(nf_sock, h->family, h->table,
+                                    NFT_OBJECT_UNSPEC, false);
+       if (obj_cache == NULL) {
+               if (errno == EINTR)
+                       return -1;
+
+               return netlink_io_error(ctx, loc,
+                                       "Could not receive stateful objects from kernel: %s",
+                                       strerror(errno));
+       }
+
+       err = nftnl_obj_list_foreach(obj_cache, list_obj_cb, ctx);
+       nftnl_obj_list_free(obj_cache);
+       return err;
+}
+
+int netlink_reset_objs(struct netlink_ctx *ctx, const struct handle *h,
+                      const struct location *loc, uint32_t type)
+{
+       struct nftnl_obj_list *obj_cache;
+       int err;
+
+       obj_cache = mnl_nft_obj_dump(nf_sock, h->family, h->table, type, true);
        if (obj_cache == NULL) {
                if (errno == EINTR)
                        return -1;
index fd3f0d8251a67caca9a0ee1e28d853e18585d003..b571fbbed5f349dee6cba40cfb2a414d31cd2c49 100644 (file)
@@ -199,6 +199,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token INSERT                  "insert"
 %token DELETE                  "delete"
 %token LIST                    "list"
+%token RESET                   "reset"
 %token FLUSH                   "flush"
 %token RENAME                  "rename"
 %token DESCRIBE                        "describe"
@@ -442,8 +443,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %type <cmd>                    line
 %destructor { cmd_free($$); }  line
 
-%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 <cmd>                    base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_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 reset_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
@@ -725,6 +726,7 @@ base_cmd            :       /* empty */     add_cmd         { $$ = $1; }
                        |       INSERT          insert_cmd      { $$ = $2; }
                        |       DELETE          delete_cmd      { $$ = $2; }
                        |       LIST            list_cmd        { $$ = $2; }
+                       |       RESET           reset_cmd       { $$ = $2; }
                        |       FLUSH           flush_cmd       { $$ = $2; }
                        |       RENAME          rename_cmd      { $$ = $2; }
                        |       EXPORT          export_cmd      { $$ = $2; }
@@ -968,6 +970,24 @@ list_cmd           :       TABLE           table_spec
                        }
                        ;
 
+reset_cmd              :       COUNTERS        ruleset_spec
+                       {
+                               $$ = cmd_alloc(CMD_RESET, CMD_OBJ_COUNTERS, &$2, &@$, NULL);
+                       }
+                       |       COUNTERS        TABLE   table_spec
+                       {
+                               $$ = cmd_alloc(CMD_RESET, CMD_OBJ_COUNTERS, &$3, &@$, NULL);
+                       }
+                       |       QUOTAS          ruleset_spec
+                       {
+                               $$ = cmd_alloc(CMD_RESET, CMD_OBJ_QUOTAS, &$2, &@$, NULL);
+                       }
+                       |       QUOTAS          TABLE   table_spec
+                       {
+                               $$ = cmd_alloc(CMD_RESET, CMD_OBJ_QUOTAS, &$3, &@$, NULL);
+                       }
+                       ;
+
 flush_cmd              :       TABLE           table_spec
                        {
                                $$ = cmd_alloc(CMD_FLUSH, CMD_OBJ_TABLE, &$2, &@$, NULL);
index 29b1450666dbf720341eeaba1d80b810cbe8a78d..9eeb436cd37a62bfc90df01e8119d72666eb5177 100644 (file)
@@ -95,11 +95,13 @@ static int cache_init_objects(struct netlink_ctx *ctx, enum cmd_ops cmd)
                        return -1;
                list_splice_tail_init(&ctx->list, &table->chains);
 
-               /* Don't check for errors on listings, this would break nft with
-                * old kernels with no stateful object support.
-                */
-               netlink_list_objs(ctx, &table->handle, &internal_location);
-               list_splice_tail_init(&ctx->list, &table->objs);
+               if (cmd != CMD_RESET) {
+                       /* Don't check for errors on listings, this would break
+                        * nft with old kernels with no stateful object support.
+                        */
+                       netlink_list_objs(ctx, &table->handle, &internal_location);
+                       list_splice_tail_init(&ctx->list, &table->objs);
+               }
 
                /* Skip caching other objects to speed up things: We only need
                 * a full cache when listing the existing ruleset.
@@ -1398,6 +1400,35 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
        return 0;
 }
 
+static int do_command_reset(struct netlink_ctx *ctx, struct cmd *cmd)
+{
+       struct obj *obj, *next;
+       struct table *table;
+       uint32_t type;
+       int ret;
+
+       switch (cmd->obj) {
+       case CMD_OBJ_COUNTERS:
+               type = NFT_OBJECT_COUNTER;
+               break;
+       case CMD_OBJ_QUOTAS:
+               type = NFT_OBJECT_QUOTA;
+               break;
+       default:
+               BUG("invalid command object type %u\n", cmd->obj);
+       }
+
+       ret = netlink_reset_objs(ctx, &cmd->handle, &cmd->location, type);
+       list_for_each_entry_safe(obj, next, &ctx->list, list) {
+               table = table_lookup(&obj->handle);
+               list_move(&obj->list, &table->objs);
+       }
+       if (ret < 0)
+               return ret;
+
+       return do_list_obj(ctx, cmd, type);
+}
+
 static int do_command_flush(struct netlink_ctx *ctx, struct cmd *cmd)
 {
        switch (cmd->obj) {
@@ -1518,6 +1549,8 @@ int do_command(struct netlink_ctx *ctx, struct cmd *cmd)
                return do_command_delete(ctx, cmd);
        case CMD_LIST:
                return do_command_list(ctx, cmd);
+       case CMD_RESET:
+               return do_command_reset(ctx, cmd);
        case CMD_FLUSH:
                return do_command_flush(ctx, cmd);
        case CMD_RENAME:
index cb989320324426ac8f0acaebd8d3eb3cfae00b24..1aa2e96b9f647367d40403820603389eb7b9ed34 100644 (file)
@@ -268,6 +268,7 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 "insert"               { return INSERT; }
 "delete"               { return DELETE; }
 "list"                 { return LIST; }
+"reset"                        { return RESET; }
 "flush"                        { return FLUSH; }
 "rename"               { return RENAME; }
 "export"               { return EXPORT; }