summaryrefslogtreecommitdiffstats
path: root/iptables
diff options
context:
space:
mode:
Diffstat (limited to 'iptables')
-rw-r--r--iptables/nft-cache.c40
-rw-r--r--iptables/nft-cache.h4
-rw-r--r--iptables/nft-cmd.c57
-rw-r--r--iptables/nft.c2
-rw-r--r--iptables/nft.h1
-rw-r--r--iptables/xtables-restore.c2
-rw-r--r--iptables/xtables-save.c2
7 files changed, 64 insertions, 44 deletions
diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c
index 305f2c12..61184653 100644
--- a/iptables/nft-cache.c
+++ b/iptables/nft-cache.c
@@ -11,6 +11,7 @@
#include <assert.h>
#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#include <xtables.h>
@@ -24,14 +25,21 @@
#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)
@@ -435,10 +443,14 @@ static void
__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);
@@ -447,11 +459,11 @@ __nft_build_cache(struct nft_handle *h)
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)
@@ -575,14 +587,20 @@ void nft_cache_build(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)
diff --git a/iptables/nft-cache.h b/iptables/nft-cache.h
index 01dd15e1..f4291180 100644
--- a/iptables/nft-cache.h
+++ b/iptables/nft-cache.h
@@ -2,8 +2,10 @@
#define _NFT_CACHE_H_
struct nft_handle;
+struct nft_cmd;
-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);
void nft_rebuild_cache(struct nft_handle *h);
void nft_release_cache(struct nft_handle *h);
void flush_chain_cache(struct nft_handle *h, const char *tablename);
diff --git a/iptables/nft-cmd.c b/iptables/nft-cmd.c
index 8bf361a6..23f2761f 100644
--- a/iptables/nft-cmd.c
+++ b/iptables/nft-cmd.c
@@ -71,12 +71,11 @@ void nft_cmd_free(struct nft_cmd *cmd)
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;
@@ -84,10 +83,10 @@ static void nft_cmd_rule_bridge(struct nft_handle *h, const char *chain,
* 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,
@@ -96,13 +95,13 @@ 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;
}
@@ -112,17 +111,17 @@ int nft_cmd_rule_insert(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_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;
}
@@ -138,7 +137,7 @@ int nft_cmd_rule_delete(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
@@ -153,7 +152,7 @@ int nft_cmd_rule_delete_num(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
@@ -168,7 +167,7 @@ int nft_cmd_rule_flush(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
@@ -183,7 +182,7 @@ int nft_cmd_chain_zero_counters(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
@@ -198,7 +197,7 @@ int nft_cmd_chain_user_add(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
@@ -217,9 +216,9 @@ int nft_cmd_chain_user_del(struct nft_handle *h, const char *chain,
* 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;
}
@@ -236,7 +235,7 @@ int nft_cmd_chain_user_rename(struct nft_handle *h,const char *chain,
cmd->rename = strdup(newname);
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
@@ -253,7 +252,7 @@ int nft_cmd_rule_list(struct nft_handle *h, const char *chain,
cmd->format = format;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
@@ -269,7 +268,7 @@ int nft_cmd_rule_replace(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
@@ -284,7 +283,7 @@ int nft_cmd_rule_check(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
@@ -304,7 +303,7 @@ int nft_cmd_chain_set(struct nft_handle *h, const char *table,
if (counters)
cmd->counters = *counters;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
@@ -318,7 +317,7 @@ int nft_cmd_table_flush(struct nft_handle *h, const char *table)
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_TABLES);
+ nft_cache_level_set(h, NFT_CL_TABLES, cmd);
return 1;
}
@@ -333,7 +332,7 @@ int nft_cmd_chain_restore(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_CHAINS);
+ nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
return 1;
}
@@ -348,7 +347,7 @@ int nft_cmd_rule_zero_counters(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
@@ -365,7 +364,7 @@ int nft_cmd_rule_list_save(struct nft_handle *h, const char *chain,
cmd->counters_save = counters;
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
@@ -382,7 +381,7 @@ int ebt_cmd_user_chain_policy(struct nft_handle *h, const char *table,
cmd->policy = strdup(policy);
- nft_cache_level_set(h, NFT_CL_RULES);
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
return 1;
}
diff --git a/iptables/nft.c b/iptables/nft.c
index f9e53316..daf08604 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -816,7 +816,7 @@ void nft_fini(struct nft_handle *h)
list_for_each_entry_safe(cmd, next, &h->cmd_list, head)
nft_cmd_free(cmd);
- flush_chain_cache(h, NULL);
+ nft_release_cache(h);
mnl_socket_close(h->nl);
}
diff --git a/iptables/nft.h b/iptables/nft.h
index c6aece7d..4eaaa77f 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -73,6 +73,7 @@ enum obj_update_type {
struct nft_cache_req {
enum nft_cache_level level;
+ char *table;
};
struct nft_handle {
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 28ef366c..418a7400 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -261,7 +261,7 @@ void xtables_restore_parse(struct nft_handle *h,
char buffer[10240] = {};
if (!h->noflush)
- nft_cache_level_set(h, NFT_CL_FAKE);
+ nft_cache_level_set(h, NFT_CL_FAKE, NULL);
line = 0;
while (fgets(buffer, sizeof(buffer), p->in)) {
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index f927aa6e..0ce66e5d 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -239,7 +239,7 @@ xtables_save_main(int family, int argc, char *argv[],
exit(EXIT_FAILURE);
}
- nft_cache_level_set(&h, NFT_CL_RULES);
+ nft_cache_level_set(&h, NFT_CL_RULES, NULL);
nft_cache_build(&h);
ret = do_output(&h, tablename, &d);