#include <assert.h>
#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#include <xtables.h>
#include "nft.h"
#include "nft-cache.h"
-void nft_cache_level_set(struct nft_handle *h, int level)
+void nft_cache_level_set(struct nft_handle *h, int level,
+ const struct nft_cmd *cmd)
{
struct nft_cache_req *req = &h->cache_req;
- if (level <= req->level)
+ if (level > req->level)
+ req->level = level;
+
+ if (!cmd)
return;
- req->level = level;
+ if (!req->table)
+ req->table = strdup(cmd->table);
+ else
+ assert(!strcmp(req->table, cmd->table));
}
static int genid_cb(const struct nlmsghdr *nlh, void *data)
__nft_build_cache(struct nft_handle *h)
{
struct nft_cache_req *req = &h->cache_req;
+ const struct builtin_table *t = NULL;
if (h->cache_init)
return;
+ if (req->table)
+ t = nft_table_builtin_find(h, req->table);
+
h->cache_init = true;
mnl_genid_get(h, &h->nft_genid);
if (req->level == NFT_CL_FAKE)
return;
if (req->level >= NFT_CL_CHAINS)
- fetch_chain_cache(h, NULL, NULL);
+ fetch_chain_cache(h, t, NULL);
if (req->level >= NFT_CL_SETS)
- fetch_set_cache(h, NULL, NULL);
+ fetch_set_cache(h, t, NULL);
if (req->level >= NFT_CL_RULES)
- fetch_rule_cache(h, NULL);
+ fetch_rule_cache(h, t);
}
static void __nft_flush_cache(struct nft_handle *h)
void nft_release_cache(struct nft_handle *h)
{
- if (!h->cache_index)
- return;
+ struct nft_cache_req *req = &h->cache_req;
+ while (h->cache_index)
+ flush_cache(h, &h->__cache[h->cache_index--], NULL);
flush_cache(h, &h->__cache[0], NULL);
- memcpy(&h->__cache[0], &h->__cache[1], sizeof(h->__cache[0]));
- memset(&h->__cache[1], 0, sizeof(h->__cache[1]));
- h->cache_index = 0;
h->cache = &h->__cache[0];
+ h->cache_init = false;
+
+ if (req->level != NFT_CL_FAKE)
+ req->level = NFT_CL_TABLES;
+ if (req->table) {
+ free(req->table);
+ req->table = NULL;
+ }
}
struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h)
free(cmd);
}
-static void nft_cmd_rule_bridge(struct nft_handle *h, const char *chain,
- const char *table)
+static void nft_cmd_rule_bridge(struct nft_handle *h, const struct nft_cmd *cmd)
{
const struct builtin_table *t;
- t = nft_table_builtin_find(h, table);
+ t = nft_table_builtin_find(h, cmd->table);
if (!t)
return;
* rule in nftables, rule cache is required here to treat them right.
*/
if (h->family == NFPROTO_BRIDGE &&
- !nft_chain_builtin_find(t, chain))
- nft_cache_level_set(h, NFT_CL_RULES);
+ !nft_chain_builtin_find(t, cmd->chain))
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
else
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
}
int nft_cmd_rule_append(struct nft_handle *h, const char *chain,
{
struct nft_cmd *cmd;
- nft_cmd_rule_bridge(h, chain, table);
-
cmd = nft_cmd_new(h, NFT_COMPAT_RULE_APPEND, table, chain, state, -1,
verbose);
if (!cmd)
return 0;
+ nft_cmd_rule_bridge(h, cmd);
+
return 1;
}
{
struct nft_cmd *cmd;
- nft_cmd_rule_bridge(h, chain, table);
-
cmd = nft_cmd_new(h, NFT_COMPAT_RULE_INSERT, table, chain, state,
rulenum, verbose);
if (!cmd)
return 0;
+ nft_cmd_rule_bridge(h, cmd);
+
if (cmd->rulenum > 0)
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
else
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
* rule cache.
*/
if (h->family == NFPROTO_BRIDGE)
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
else
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
cmd->rename = strdup(newname);
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
cmd->format = format;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
if (counters)
cmd->counters = *counters;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_TABLES);
+ nft_cache_level_set(h, NFT_CL_TABLES, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
cmd->counters_save = counters;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
cmd->policy = strdup(policy);
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}