diff options
Diffstat (limited to 'iptables')
-rw-r--r-- | iptables/nft-cache.c | 40 | ||||
-rw-r--r-- | iptables/nft-cache.h | 4 | ||||
-rw-r--r-- | iptables/nft-cmd.c | 57 | ||||
-rw-r--r-- | iptables/nft.c | 2 | ||||
-rw-r--r-- | iptables/nft.h | 1 | ||||
-rw-r--r-- | iptables/xtables-restore.c | 2 | ||||
-rw-r--r-- | iptables/xtables-save.c | 2 |
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); |