summaryrefslogtreecommitdiffstats
path: root/src/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cache.c')
-rw-r--r--src/cache.c93
1 files changed, 71 insertions, 22 deletions
diff --git a/src/cache.c b/src/cache.c
index f790f995..c000e32c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -6,6 +6,8 @@
* later) as published by the Free Software Foundation.
*/
+#include <nft.h>
+
#include <expression.h>
#include <statement.h>
#include <rule.h>
@@ -124,9 +126,9 @@ void nft_cache_filter_fini(struct nft_cache_filter *filter)
struct nft_filter_obj *obj, *next;
list_for_each_entry_safe(obj, next, &filter->obj[i].head, list)
- xfree(obj);
+ free(obj);
}
- xfree(filter);
+ free(filter);
}
static void cache_filter_add(struct nft_cache_filter *filter,
@@ -201,8 +203,12 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd,
{
switch (cmd->obj) {
case CMD_OBJ_TABLE:
- if (filter && cmd->handle.table.name) {
+ if (filter)
filter->list.family = cmd->handle.family;
+ if (!cmd->handle.table.name) {
+ flags |= NFT_CACHE_TABLE;
+ break;
+ } else if (filter) {
filter->list.table = cmd->handle.table.name;
}
flags |= NFT_CACHE_FULL;
@@ -212,6 +218,10 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd,
filter->list.family = cmd->handle.family;
filter->list.table = cmd->handle.table.name;
filter->list.chain = cmd->handle.chain.name;
+ /* implicit terse listing to fetch content of anonymous
+ * sets only when chain name is specified.
+ */
+ flags |= NFT_CACHE_TERSE;
}
flags |= NFT_CACHE_FULL;
break;
@@ -224,8 +234,6 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd,
}
if (filter->list.table && filter->list.set)
flags |= NFT_CACHE_TABLE | NFT_CACHE_SET | NFT_CACHE_SETELEM;
- else if (nft_output_terse(&nft->output))
- flags |= NFT_CACHE_FULL | NFT_CACHE_TERSE;
else
flags |= NFT_CACHE_FULL;
break;
@@ -235,6 +243,8 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd,
case CMD_OBJ_SETS:
case CMD_OBJ_MAPS:
flags |= NFT_CACHE_TABLE | NFT_CACHE_SET;
+ if (!nft_output_terse(&nft->output))
+ flags |= NFT_CACHE_SETELEM;
break;
case CMD_OBJ_FLOWTABLE:
if (filter &&
@@ -249,17 +259,45 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd,
flags |= NFT_CACHE_TABLE | NFT_CACHE_FLOWTABLE;
break;
case CMD_OBJ_RULESET:
- if (nft_output_terse(&nft->output))
- flags |= NFT_CACHE_FULL | NFT_CACHE_TERSE;
- else
- flags |= NFT_CACHE_FULL;
- break;
default:
flags |= NFT_CACHE_FULL;
break;
}
flags |= NFT_CACHE_REFRESH;
+ if (nft_output_terse(&nft->output))
+ flags |= NFT_CACHE_TERSE;
+
+ return flags;
+}
+
+static unsigned int evaluate_cache_reset(struct cmd *cmd, unsigned int flags,
+ struct nft_cache_filter *filter)
+{
+ switch (cmd->obj) {
+ case CMD_OBJ_RULES:
+ case CMD_OBJ_RULE:
+ if (filter) {
+ if (cmd->handle.table.name) {
+ filter->list.family = cmd->handle.family;
+ filter->list.table = cmd->handle.table.name;
+ }
+ if (cmd->handle.chain.name)
+ filter->list.chain = cmd->handle.chain.name;
+ }
+ flags |= NFT_CACHE_SET | NFT_CACHE_FLOWTABLE |
+ NFT_CACHE_OBJECT | NFT_CACHE_CHAIN;
+ break;
+ case CMD_OBJ_ELEMENTS:
+ case CMD_OBJ_SET:
+ case CMD_OBJ_MAP:
+ flags |= NFT_CACHE_SET;
+ break;
+ default:
+ flags |= NFT_CACHE_TABLE;
+ break;
+ }
+
return flags;
}
@@ -277,6 +315,7 @@ static int nft_handle_validate(const struct cmd *cmd, struct list_head *msgs)
}
break;
case CMD_OBJ_RULE:
+ case CMD_OBJ_RULES:
case CMD_OBJ_CHAIN:
case CMD_OBJ_CHAINS:
if (h->table.name &&
@@ -342,7 +381,9 @@ static int nft_handle_validate(const struct cmd *cmd, struct list_head *msgs)
case CMD_OBJ_CT_HELPER:
case CMD_OBJ_CT_HELPERS:
case CMD_OBJ_CT_TIMEOUT:
+ case CMD_OBJ_CT_TIMEOUTS:
case CMD_OBJ_CT_EXPECT:
+ case CMD_OBJ_CT_EXPECTATIONS:
if (h->table.name &&
strlen(h->table.name) > NFT_NAME_MAXLEN) {
loc = &h->table.location;
@@ -391,6 +432,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 |
@@ -403,7 +445,7 @@ int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds,
flags = evaluate_cache_get(cmd, flags);
break;
case CMD_RESET:
- flags |= NFT_CACHE_TABLE;
+ flags |= evaluate_cache_reset(cmd, flags, filter);
break;
case CMD_LIST:
flags |= evaluate_cache_list(nft, cmd, flags, filter);
@@ -591,31 +633,36 @@ static int list_rule_cb(struct nftnl_rule *nlr, void *data)
table = nftnl_rule_get_str(nlr, NFTNL_RULE_TABLE);
chain = nftnl_rule_get_str(nlr, NFTNL_RULE_CHAIN);
- if (h->family != family ||
- strcmp(table, h->table.name) != 0 ||
+ if ((h->family != NFPROTO_UNSPEC && h->family != family) ||
+ (h->table.name && strcmp(table, h->table.name) != 0) ||
(h->chain.name && strcmp(chain, h->chain.name) != 0))
return 0;
netlink_dump_rule(nlr, ctx);
rule = netlink_delinearize_rule(ctx, nlr);
+ assert(rule);
list_add_tail(&rule->list, &ctx->list);
return 0;
}
-static int rule_cache_dump(struct netlink_ctx *ctx, const struct handle *h,
- const struct nft_cache_filter *filter)
+int rule_cache_dump(struct netlink_ctx *ctx, const struct handle *h,
+ const struct nft_cache_filter *filter,
+ bool dump, bool reset)
{
struct nftnl_rule_list *rule_cache;
const char *table = NULL;
const char *chain = NULL;
+ uint64_t rule_handle = 0;
if (filter) {
table = filter->list.table;
chain = filter->list.chain;
+ rule_handle = filter->list.rule_handle;
}
- rule_cache = mnl_nft_rule_dump(ctx, h->family, table, chain);
+ rule_cache = mnl_nft_rule_dump(ctx, h->family,
+ table, chain, rule_handle, dump, reset);
if (rule_cache == NULL) {
if (errno == EINTR)
return -1;
@@ -947,7 +994,7 @@ static int rule_init_cache(struct netlink_ctx *ctx, struct table *table,
struct chain *chain;
int ret;
- ret = rule_cache_dump(ctx, &table->handle, filter);
+ ret = rule_cache_dump(ctx, &table->handle, filter, true, false);
list_for_each_entry_safe(rule, nrule, &ctx->list, list) {
chain = chain_cache_find(table, rule->handle.chain.name);
@@ -980,8 +1027,10 @@ static int implicit_chain_cache(struct netlink_ctx *ctx, struct table *table,
int ret = 0;
list_for_each_entry(chain, &table->chain_bindings, cache.list) {
- filter.list.table = table->handle.table.name;
- filter.list.chain = chain->handle.chain.name;
+ filter.list = (typeof(filter.list)) {
+ .table = table->handle.table.name,
+ .chain = chain->handle.chain.name,
+ };
ret = rule_init_cache(ctx, table, &filter);
}
@@ -1034,7 +1083,7 @@ static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags,
continue;
ret = netlink_list_setelems(ctx, &set->handle,
- set);
+ set, false);
if (ret < 0)
goto cache_fails;
}
@@ -1047,7 +1096,7 @@ static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags,
continue;
ret = netlink_list_setelems(ctx, &set->handle,
- set);
+ set, false);
if (ret < 0)
goto cache_fails;
}
@@ -1230,7 +1279,7 @@ void cache_init(struct cache *cache)
void cache_free(struct cache *cache)
{
- xfree(cache->ht);
+ free(cache->ht);
}
void cache_add(struct cache_item *item, struct cache *cache, uint32_t hash)